Simon
Simon

Reputation: 881

Video-stream not working for iOS/Safari

I have a web-application that relies on a third-party object-store (SoftLayer) to serve video-files. When a user requests a video, my node.js-server fetches the file from the object-store and streams it to the client. I have code that works for browsers in Android & Firefox and Chrome on a desktop machine. Unfortunately, the video is not played in Safari/iOS.

A simplified version of the node.js-code (that streams a video from the w3c-website) looks like this:

router.get('/testFile', function (req, res) {
  var range = req.headers.range;
  var positions = range.replace(/bytes=/, "").split("-");
  var start = parseInt(positions[0], 10);

  var objectPath = "http://www.w3schools.com/html/mov_bbb.mp4"
    request.get({
      url: objectPath,
      headers: {},
      encoding: null
    }, function (err, data) {
      if (err) {
        console.log('error', err);
      }else {
        var total = data.body.length;
        var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
        var chunksize = (end - start) + 1;
        console.log("bytes " + start + "-" + end + "/" + total);
        res.writeHead(206, {
          "Content-Range": "bytes " + start + "-" + end + "/" + total,
          "Accept-Ranges" : "bytes",
          "Content-Length": chunksize
        });
        var bodyStream = new streambuffers.ReadableStreamBuffer({
          frequency: 1,
          chunksize: 256
        });
        bodyStream.pipe(res);
        bodyStream.put(data.body);
      }
    });
});

The '/testFile' is then used as the src of a HTML5 video player:

<!DOCTYPE html>
<html>
  <head>
    <title>Movie</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>Test video</h1>
    <video controls="true" preload="none">
      <source src="/testFile" type="video/mp4"/>
    </video>
  </body>
</html>

This simple project can be checked out here: https://bitbucket.org/Duffman/stream-video

To run it, just run "node bin/www" and surf to "http://localhost:3000/testVideo".

Upvotes: 1

Views: 4283

Answers (2)

Joost Baaij
Joost Baaij

Reputation: 7608

I would not try to re-create a streaming media server in node by yourself.

Server performance will bad

With the code you have, your application server will download the full file from SoftLayer first and then stream it to the client from RAM. This is not sustainable for either large number of files or clients.

Slow across the globe

If you server is in Brussels, every client on a different continent will see slow transfers. It's going to be especially painful on mobile networks, which is presumably where you'd want optimum performance.

Streaming media is hard

Use the best tool for the job. You're not going to create the best possible streaming media server in a few lines of node. Trust a dedicated HTTP server like NGINX to solve this for you. Furthermore, there can't be bugs in the code you didn't write.

Recommendation:

Use the SoftLayer CDN. It's built specifically to solve your problem. Note: I am not affiliated with them. If your content was on S3 I'd advise you to use CloudFront. The key here is to use a CDN for streaming video.

Upvotes: 0

Dave Anderson
Dave Anderson

Reputation: 12324

iOS is quite particular about the way the video is served.

Safari Web Content Guide - Configuring Your Server

HTTP servers hosting media files for iOS must support byte-range requests, which iOS uses to perform random access in media playback.

If you are not sure whether your media server supports byte-range requests, you can use the curl command-line tool to download a short segment from a file on the server:

curl --range 0-99 http://example.com/test.mov -o /dev/null

If the tool reports that it downloaded 100 bytes, the media server correctly handled the byte-range request.

Ensure that your HTTP server sends the correct MIME types for the movie filename extensions;

Extensions MIME type

  • .mov : video/quicktime
  • .mp4 : video/mp4
  • .m4v : video/x-m4v
  • .3gp : video/3gpp

Also see my answer for HTML5 video not working on iPad.

Upvotes: 2

Related Questions