title: Streaming a video file to an html5 video player with Node.js so that the video controls continue to work?
body: <h2>Tl;Dr - The Question:</h2>
  
  <p><strong>What is the right way to handle streaming a video file to an html5 video player with Node.js <em>so that the video controls continue to work?</em></strong></p>
  
  <p>I <em>think</em> it has to do with the way that the headers are handled. Anyway, here's the background information. The code is a <em>little</em> lengthy, however, it's pretty straightforward.</p>
  
  <h2>Streaming small video files to HTML5 video with Node is easy</h2>
  
  <p><a href="http://blog.dojchinovski.mk/?p=41#comment-63769" rel="noreferrer">I learned how to stream small video files to an HTML5 video player very easily.</a> With this setup, the controls work without any work on my part, and the video streams flawlessly. A working copy of the fully working code with sample video is <a href="https://docs.google.com/uc?authuser=0&amp;id=0BxeQvF3BluZUMGhUUXVHTjlzelU&amp;export=download" rel="noreferrer">here, for download on Google Docs</a>.</p>
  
  <p><strong>Client:</strong></p>
  
  <pre><code>&lt;html&gt;
    &lt;title&gt;Welcome&lt;/title&gt;
      &lt;body&gt;
        &lt;video controls&gt;
          &lt;source src="movie.mp4" type="video/mp4"/&gt;
          &lt;source src="movie.webm" type="video/webm"/&gt;
          &lt;source src="movie.ogg" type="video/ogg"/&gt;
          &lt;!-- fallback --&gt;
          Your browser does not support the &lt;code&gt;video&lt;/code&gt; element.
      &lt;/video&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p><strong>Server:</strong></p>
  
  <pre><code>// Declare Vars &amp; Read Files
  
  var fs = require('fs'),
      http = require('http'),
      url = require('url'),
      path = require('path');
  var movie_webm, movie_mp4, movie_ogg;
  // ... [snip] ... (Read index page)
  fs.readFile(path.resolve(__dirname,"movie.mp4"), function (err, data) {
      if (err) {
          throw err;
      }
      movie_mp4 = data;
  });
  // ... [snip] ... (Read two other formats for the video)
  
  // Serve &amp; Stream Video
  
  http.createServer(function (req, res) {
      // ... [snip] ... (Serve client files)
      var total;
      if (reqResource == "/movie.mp4") {
          total = movie_mp4.length;
      }
      // ... [snip] ... handle two other formats for the video
      var range = req.headers.range;
      var positions = range.replace(/bytes=/, "").split("-");
      var start = parseInt(positions[0], 10);
      var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
      var chunksize = (end - start) + 1;
      if (reqResource == "/movie.mp4") {
          res.writeHead(206, {
              "Content-Range": "bytes " + start + "-" + end + "/" + total,
                  "Accept-Ranges": "bytes",
                  "Content-Length": chunksize,
                  "Content-Type": "video/mp4"
          });
          res.end(movie_mp4.slice(start, end + 1), "binary");
      }
      // ... [snip] ... handle two other formats for the video
  }).listen(8888);
  </code></pre>
  
  <p>But this method is limited to files &lt; 1GB in size. </p>
  
  
  
  <h2>Streaming (any size) video files with <code>fs.createReadStream</code></h2>
  
  <p>By utilizing <code>fs.createReadStream()</code>, the server can read the file in a stream rather than reading it all into memory at once. This sounds like the right way to do things, and the syntax is extremely simple:</p>
  
  <p><strong>Server Snippet:</strong></p>
  
  <pre><code>movieStream = fs.createReadStream(pathToFile);
  movieStream.on('open', function () {
      res.writeHead(206, {
          "Content-Range": "bytes " + start + "-" + end + "/" + total,
              "Accept-Ranges": "bytes",
              "Content-Length": chunksize,
              "Content-Type": "video/mp4"
      });
      // This just pipes the read stream to the response object (which goes 
      //to the client)
      movieStream.pipe(res);
  });
  
  movieStream.on('error', function (err) {
      res.end(err);
  });
  </code></pre>
  
  <p>This streams the video just fine! But the video controls no longer work. </p>