Blog

iPhone video streaming from Drupal's file system

Written by Metal Toad Staff | Oct 13, 2009 12:00:00 AM
Filed under:

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.