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);
[...] 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 [...]
Stream live WebM video to browser using Node.js and GStreamer « Devendra @ Work
April 26, 2011 at 4:10 pm
[...] 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 [...]
Extrawurst – Streaming (media) in NodeJs
June 19, 2012 at 1:24 pm