Stream WebM file to Chrome using Node.js


Node.js can be used to stream arbitrary data to a browser, such as Chrome,  over HTTP. In this post we’ll use version 2.2.2 (latest) of the express middleware to stream a WebM file to the browser.

Install express

Execute the following npm command:

sudo npm install express@latest

For some reason, I have not yet investigated, npm installs express to a folder called node_modules. If that happens to you, you can copy the contents of that folder to ~/.node_modules.

Code

Create a a file called webm.js with the following code:

var sys = require('sys');
var fs = require('fs');
var util = require('util');

if (process.argv.length != 4) {
  sys.puts('Require the following command line arguments:' +
    ' http_port webm_file');
  sys.puts(' e.g. 9001 /home/foo/file.webm');
  process.exit();
}

var port = process.argv[2];
var file = process.argv[3];

var express = require('express')

var app = express.createServer();

app.get('/', function(req, res){
  sys.puts(util.inspect(req.headers, showHidden=false, depth=0));

  var stat = fs.statSync(file);
  if (!stat.isFile()) return;

  var start = 0;
  var end = 0;
  var range = req.header('Range');
  if (range != null) {
    start = parseInt(range.slice(range.indexOf('bytes=')+6,
      range.indexOf('-')));
    end = parseInt(range.slice(range.indexOf('-')+1,
      range.length));
  }
  if (isNaN(end) || end == 0) end = stat.size-1;

  if (start > end) return;

  sys.puts('Browser requested bytes from ' + start + ' to ' +
    end + ' of file ' + file);

  var date = new Date();

  res.writeHead(206, { // NOTE: a partial http response
    // 'Date':date.toUTCString(),
    'Connection':'close',
    // 'Cache-Control':'private',
    // 'Content-Type':'video/webm',
    // 'Content-Length':end - start,
    'Content-Range':'bytes '+start+'-'+end+'/'+stat.size,
    // 'Accept-Ranges':'bytes',
    // 'Server':'CustomStreamer/0.0.1',
    'Transfer-Encoding':'chunked'
    });

  var stream = fs.createReadStream(file,
    { flags: 'r', start: start, end: end});
  stream.pipe(res);
});

app.listen(port);

process.on('uncaughtException', function(err) {
  sys.puts(err);
});

The commented headers in the response may be used for additional control. The Transfer-Encoding header may also be ‘identity’, its default value, as long as the Connection response header is ‘close’. If Connection header is ‘keep-alive’, Transfer-Encoding has to be ‘chunked’. This behavior may be browser specific, I have only tested with Chrome. Chunking is taken care of by Node.js.

Running the code

To stream a WebM file called /home/user/file.webm invoke node like this:

node webm.js 9001 /home/user/file.webm

Then, point Chrome to http://host:9001/, the video should begin playing.

Doing it the easy way

Now that we have seen the hard way, express has a method on the response object to send a file. It basically is a replacement for all the code that exists in the app.get() callback above:

  res.sendfile(file);
About these ads
Posted in GStreamer, HTML, JavaScript, Linux
3 comments on “Stream WebM file to Chrome using Node.js
  1. [...] GStreamer 0.10.32 (latest). We’ll use Node.js with the express middleware. We have used that previously to do on-demand streaming of a WebM [...]

  2. [...] I finally got the right clue from a blog post5 describing streaming using the node express framework. But since I have written the rest of the [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 64 other followers

%d bloggers like this: