iPhone video streaming from Drupal's file system

It's well known the iPhone can play H.264 video. With tools like ffmpeg, hooking this up to Drupal ought to be simple, right? Here are a few snags I hit, and how to resolve them.

The server is not correctly configured.

This error means your server doesn't support byte range requests. Range requests allow a client to request just part of a file, with a header that looks something like this:

GET /system/files/sample.mp4 HTTP/1.1
Host: example.com
Range: bytes=1000-1999

The server should respond with "HTTP/1.1 206 Partial Content" followed by the requested chunk.

Now, I should confess that tossing an MP4 file in Drupal's filesystem perhaps isn't really "streaming". However with byte range requests a client can fake it pretty effectively.

So how can this marvelous feature be enabled on your server? It turns out this is the wrong question. The byterange filter is built-in to Apache's HTTP handling; I'm not even sure it can be easily turned off. However, when using private files the data is transferred by Drupal's file_download() function, which doesn't support range requests, and mod_php sends the entire document if it's greater than 8000 bytes.

The solution is to use X-Sendfile. While primarily designed as a performance enhancement, it has the nice side-effect of offloading the transfer to Apache, so range requests work again. (This relatively new Drupal module currently requires a core patch, but there's a patch to remove the patch.)

Cannot Play Movie - Movie could not be played.

Initially, this was caused by the lack of a voodoo UUID atom required by the iPhone. To fix this, use 'ffmpeg -f ipod' instead of 'ffmpeg -f mp4'.

Cannot Play Movie - Movie could not be played.

Wait – I just fixed that! This error will also occur if the wrong H.264 profile is used. libx264 defaults to the High Profile (HiP), while the iPhone demands the "Low-Complexity Baseline Profile". Use 'ffmpeg -vpre ipod640' or '-vpre ipod320' to resolve this error.

That should satisfy the iPhone's picky MediaPlayer.framework. You can link to the .mp4 file directly, or use <object> or <video> tags.

For desktop browsers, there are Flash widgets like Flowplayer (and now Flashy!). Personally, I wish the web would go back to direct embedding. It seems the Flash players are primarily necessitated by politics (witness the current format war within the W3C over the <video> tag), and DRM.

Filed under:

Comments

I can't wait for the video tag to be implemented. Apples lack of flash movies is just a lack of consumer support for which they can be 'difficult' at times.

I had the same "The server is not correctly configured." problem with Wordpress 3 with Multisite activated. Your X-Sendfile tip worked for me. I've only installed the module and put this on wp-config.php define('WPMU_SENDFILE', true);
Thanks for your post!

what's terrible is that the iPhone will make HTTP range requests EVEN WHEN the server does not have an Accept-Ranges header. This is really bad because ranges are an optional part of HTTP, so clients must not use it unless the server indicates that it supports it.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?