Giter VIP home page Giter VIP logo

node-video's Introduction

This is a node.js module, writen in C++, that produces Theora/Ogg videos from the given RGB buffers.

It was written by Peteris Krumins ([email protected]). His blog is at http://www.catonmat.net -- good coders code, great reuse.


This module exports several objects that you can work with:

* FixedVideo - to create videos from fixed size frames
* StackedVideo - to create videos from fragmented frames (stack them together)
* AsyncStackedVideo - same as StackedVideo but asynchronous

// these are not there yet, still hacking them in right now.
// * StreamingVideo - to create streamable videos (works with HTML5 <video>)

##FixedVideo

FixedVideo object is for creating videos from fixed size frames. That is, each frame is exactly the same size, for example, each frame is 720x400 pixels.

Here is how to use FixedVideo. First you need to create a new instance of this object. The constructor takes two arguments width and height of the video:

var video = new FixedVideo(width, height);

Next, you need to set the output file this video will be written to. This is done via setOutputFile method, it can be relative or absolute path. If nodejs doesn't have the necessary permissions to write the file, it will throw an exception as soon as you submit the first frame. Here is how you use setOutputFile:

video.setOutputFile('./cool_video.ogv');

The .ogv extension stands for ogg-video.

Then you can also change the quality of the video via setQuality method. The quality must be between 0-63, where 0 is the worst quality and 63 is the best. The default quality is 31.

video.setQuality(63);   // best video quality

You can also change the frame rate with setFrameRate. The default is 25fps, to change it do this:

video.setFrameRate(50);  // frame rate is now 50 fps

The keyframe interval can also be controlled. Use setKeyFrameInterval to set it. It must be a power of two:

video.setKeyFrameInterval(128);  // keyframe every 128 frames

Important: All of the above options should be set before submitting the first frame.

Now, to start writing video, call newFrame method with frames sequentially. Frames must be RGB nodejs Buffer objects.

video.newFrame(rgb_frame);

FixedVideo is lazy by itself and will write headers of the video only after receiving the first frame, so the first frame may take longer to encode than subsequent, because there is a lot of initialization going on.

If at any time you're done writing video, call the end method,

video.end();

This will close all open files and free resources. But you can also leave it to garbage collector. If video goes out of scope, it also closes the video file and frees all resources.

##StackedVideo

StackedVideo object is for stacking many small frame updates together and then encoding the frame as a whole. Here is how it works. The first frame sent to StackedVideo must be a full frame (the width and height must match video's width and height). Next, you can either send another full frame for encoding or update parts of the last frame. It's useful in a situation like doing a screen recording, when only one smart part of the screen updates, you redraw just that portion and nothing else.

Must of the usage is just like you'd use FixedVideo object.

First create a StackedVideo object:

var stackedVideo = new StackedVideo(width, height);

Then set the output file:

stackedVideo.setOutputFile('./screencast.ogv');

Then set the quality, framerate, keyframe interval, via setQuality, setFrameRate, setKeyFrameInterval methods.

Now you have to submit a full frame to StackedVideo, do it via regular newFrame method:

stackedVideo.newFrame(rgb_frame);

This will encode this frame, and remember it. Now you can use push method to push an update to the frame. The usage is as following:

stackedVideo.push(rgb_rectangle, x, y, width, height);

This will put the rectangle of width x height at position (x, y). Make sure dimensions don't overflow or you'll get an exception. You can also push the first full frame with this method instead of using newFrame, make sure that (x,y) = (0,0) and width, height are video's width, height.

After you're done pushing all the updates you wanted, call endPush. This will encode the frame (and keep the previous frame in memory, so you can push more stuff):

stackedVideo.endPush();

Stacked videos can also duplicate previous frames cheaply to imitate VFR (variable frame rate). Pass millisecond argument to endPush to make it duplicate the previous for the right amount of time. Here is what I mean,

If you call,

stackedVideo.endPush((new Date).getTime());

every time, then the previous frame will be duplicated the right number of times so that video played at the right framerate.

When you're totally done with encoding, call the end method:

stackedVideo.end();

That will close all the file handles and free memory. Alternatively you can let the stackedVideo object go out of scope, which will have the same effect.

##AsyncStackedVideo

AsyncStackedVideo is the same as StackedVideo except it's asynchronous.

var asyncVideo = new AsyncStackedVideo(width, height);
asyncVideo.setOutputFile('./video.ogv');

To use it you must specify the temporary directory for fragments (it writes them asynchronously to disk):

asyncVideo.setTmpDir('/tmp/foo');

Next you .push fragments to it, and after you're done with one frame, you call .endPush.

Then when you're totally done with all the frames, call .encode and pass it a callback function, which will be called once the encoding is done:

asyncVideo.encode(function (ok, error) {
    if (ok) {
        // video was written to the file you set by .setOutputFile
    }
    else {
        // failure, examine 'error'
    }
});

##StreamingVideo

Also coming near you soon. This is the most awesome stuff!

##How to compile?

You need node.js installed to compile this module. When installed it comes with node-waf tool, run it in this libs dir:

node-waf configure build

This will produce video.node dll. After that, make sure NODE_PATH contains lib's dir.

Installation

npm install node-video [-g]

##Other stuff in this module

The discovery/ directory contains all the snippets I wrote to understand how to get video working. It's a habit of effective hackers to try lots of small things out until you get the whole picture of how things should work. I call it "the hacker's approach," where you hack stuff up quickly without any understanding, and then rewrite it to produce working modules.

I also tried libx264 but since it was only supported by Chrome, I went with libtheora. Maybe I'll add libx264 later as it gets support from more browsers.

This library was written for my and SubStack's StackVM startup.


Happy videoing!

Sincerely, Peteris Krumins http://www.catonmat.net

Contributors

  • Node v0.3 buffers (James Halliday substack)
  • Node v0.6 compatibility (Pascal Deschenes )

node-video's People

Contributors

pdeschen avatar pkrumins avatar rayzen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-video's Issues

Streaming

Seems like you never got to the video streaming?

Any chance you ever will?

Considering taking it on myself.

Can't require node-video module

I'm running on Mac OS X 10.6, and i'm trying to create a small test server with node.js to encode video receiving frames from a client, but when I require the video module with the code "var myVideo = require("video")" it throws the error ("Can't find module 'video').... i've installed node-video with npm, installed libtheora and configured the build with "node-waf configure build"...
I've tried to create even the NODE_PATH env, but it thorws another error (Can't load shered library)..

What's wrong??

Erros compiling in Mac OS X

I try to compile this module in Mac OS X (Snow Leopard) i fix some parts to work with my installations folders .

I modify wscript to point to the folders where i have the theora library /opt/local

so here is the patch:

    15,17c15,17
    <   conf.check(lib='ogg', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libogg/lib', '/usr/local/pkg/libogg/lib', '/usr/local/pkg/libogg-1.2.0/lib','/opt/local/lib'])
    <   conf.check(lib='theoradec', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libtheora/lib', '/usr/local/pkg/libtheora/lib', '/usr/local/pkg/libtheora-1.1.1/lib','/opt/local/lib'])
    <   conf.check(lib='theoraenc', uselib='THEORADEC', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libtheora/lib', '/usr/local/pkg/libtheora/lib', '/usr/local/pkg/libtheora-1.1.1/lib','/opt/local/lib'])
    ---
    >   conf.check(lib='ogg', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libogg/lib', '/usr/local/pkg/libogg/lib', '/usr/local/pkg/libogg-1.2.0/lib'])
    >   conf.check(lib='theoradec', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libtheora/lib', '/usr/local/pkg/libtheora/lib', '/usr/local/pkg/libtheora-1.1.1/lib'])
    >   conf.check(lib='theoraenc', uselib='THEORADEC', libpath=['/lib', '/usr/lib', '/usr/local/lib', '/usr/local/libtheora/lib', '/usr/local/pkg/libtheora/lib', '/usr/local/pkg/libtheora-1.1.1/lib']) 
    24c24
    <   obj.cxxflags = obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE","-I/opt/local/include"]
    ---
    >   obj.cxxflags = obj.cxxflags = ["-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"]

But i have another error when i try to build:

[4/8] cxx: src/stacked_video.cpp -> build/default/src/stacked_video_1.o
../src/fixed_video.cpp: In static member function ‘static v8::Handle<v8::Value> FixedVideo::NewFrame(const v8::Arguments&)’:
../src/fixed_video.cpp:102: error: ‘class node::Buffer’ has no member named ‘data’
../src/stacked_video.cpp: In static member function ‘static v8::Handle<v8::Value> StackedVideo::NewFrame(const v8::Arguments&)’:
../src/stacked_video.cpp:196: error: ‘class node::Buffer’ has no member named ‘data’
../src/stacked_video.cpp: In static member function ‘static v8::Handle<v8::Value> StackedVideo::Push(const v8::Arguments&)’:
../src/stacked_video.cpp:244: error: ‘class node::Buffer’ has no member named ‘data’ 
Waf: Leaving directory `/Users/msdark/node-video/build' 
Build failed:
 -> task failed (err #1): 
{task: cxx fixed_video.cpp -> fixed_video_1.o}
 -> task failed (err #1): 
{task: cxx stacked_video.cpp -> stacked_video_1.o}

And i don't know how fix this.

incorrect timestamps when keyFrameInterval is larger than frameRate

In general I've noticed that playing around with the key frame intervals and frame rates will cause the resulting video to have a different length (all other things being equal). I'm encoding the video with the endPush(timestamp) method (not encoding everything frame by frame). Curiously, the larger the two parameters are, the smaller the error is.

For example, if the key frame interval is 64 , and the frame rate is say, 32, then the resulting video will be longer that it should be (about 20% longer in my case). If both parameters are set to the same value, the video encodes properly.

If needed, I can create a simple test case.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.