Monday, December 29, 2014

HTML5 video live streaming with ffmpeg and mediaelement.js, Round 2

Follow-up from this summer to the original post.

So, after not rolling out our HTML5 player last year, we've decided to give it a go again this year.
What we've learned: things have changed in Internet-land.

IE no longer requests or supports WMV anymore, which is weird but actually correct. It takes mp4 now as default.

Chrome was still ticking along happy.

Firefox was a big surprise: between version 19 and 20 they've reworked the HTTP engine, so it's a bit quirky now:
  • It fetches the first 8k for metadata in a request
  • It uses HTTP 206 Partial content requests now
  • If it doesn't get an X-Content-Duration, it'll send a new partial request for the end of the file. As it's transcoded on the fly, this is bad for us.
So, we need to give it:
  • HTTP 206 headers
  • Range headers
  • X-Content-Duration headers (in seconds)
This can be done with something like this:

$ua=$_SERVER['HTTP_USER_AGENT'];
$useragent='generic';
# match Firefox 1-19
if ( preg_match('/Gecko.20.*Firefox.(1){0,1}[0-9]\./', $ua) ) {
    $firefox19=true;
}
# match all Firefox
if ( preg_match('/Gecko\/.*Firefox.[1-9]/', $ua) ) {
    $firefox=true;
}
# if Firefox 20-
if ($firefox && !$firefox19) {
    $useragent='ff20';
}

# generic headers
if ($useragent=='generic') {
#header("HTTP/1.1 200 OK");
#header('Content-Disposition: attachment; filename=' . basename($file));
}

# firefox 20+ headers
#   firefox 20 wants partial content with code 206, and likes X-Content-Duration
if ($useragent=='ff20') {
header("HTTP/1.1 206 Partial Content");
header("Range: bytes=0-");
header("X-Content-Duration: $totduration");
}

I couldn't get the Flash fallback of mediaelement.js working and Silverlight was killed by Microsoft, so mediaelement.js was taken out from our setup, with a manual Flash fallback link.
We've also noticed A-V sync issues with ffmpeg, so deployment was pulled again, but we're making progress.

Thanks to Browserstack, for making life easier while testing.

No comments:

Post a Comment