Streaming video using Node.js

In this post I am going to show you how you can set-up Node.js to stream video files to an HTML5 video tag.

First, lets create simple HTML client.

The client offers the same video in 3 formats: video/mp4, video/ogg and video/webm. Formatted video in mp4 should work fine in Safari and Chrome, ogg in Chrome and Firefox, while webm in Chrome and Firefox. For these reasons, it is recommended that you offer the same video in ogg, mp4 and webm formats.

The server should stream the video according the “partial content” requests sent by the client (browser).
An example of a HTTP request provided by Chrome and a response is presented in the
following code snippet.

The HTTP request header Range (line 10) indicates which part of the movie should be send. The first byte position and last byte position. If last byte position is not present then it is the last byte of the video file.
Following code snipped checks first and last byte position of the requested part (lines 1-4), calculates the chunk size (line 5), sets HTTP response headers Content-Ranges, Accept-Ranges, Content-Length and Content-Type (lines 9-12), and finally we “carve” the requested chunk data and we send the requested content (line 13).

Note that the response status code should be set to 206 Partial Content.
Streaming example using Node.js.


Your browser does not support the video element.

A running example can be downloaded from here.

This entry was posted in html5, Node.js, programming. Bookmark the permalink.

6 Responses to Streaming video using Node.js

  1. Kleyson Rios says:

    There is a problem to download running example. May you fix download link ?

    Regards.

  2. Niraja says:

    Hi,

    I am new bee to this. but I was trying to create my own server to share video files. I was trying to understand how things work. But surprisingly even if i rename server.js or delete it from directory, just index.html works. so how exactly your working example is working? can you shed some more light. I am missing something here?

  3. Jonathan Todd says:

    This works great for small video files, but fs can’t read anything over ~1.7gigs. The way to handle it is:

    var http = require(‘http’);
    var fs = require(‘fs’);

    http.createServer(function(req, res) {
    // The filename is simple the local directory and tacks on the requested url
    var filename = __dirname+req.url;

    // This line opens the file as a readable stream
    var readStream = fs.createReadStream(filename);

    // This will wait until we know the readable stream is actually valid before piping
    readStream.on(‘open’, function () {
    // This just pipes the read stream to the response object (which goes to the client)
    readStream.pipe(res);
    });

    // This catches any errors that happen while creating the readable stream (usually invalid names)
    readStream.on(‘error’, function(err) {
    res.end(err);
    });
    }).listen(8080);

    And that works perfectly EXCEPT the controls no longer work on the video. Could you post about this method?

  4. Jonathan Todd says:

    It’s also worth noting that 1) It can’t read anything over 1 gig by default, and besides, that takes up wayy to much RAM to be effective. I would love to see a post about using the readStream method.