Simple Cross-Browser HTML5 video with a single H.264 file and fallback options

At first glance, the promise of HTML5 <video> seems awesome. Just a simple

<video src="myvideo.mp4" controls></video>

and you’re done right? Not quite. In reality there are all kinds of browser inconsistence that make this impossible. Here’s a run down of the problems:
1. Older browsers don’t support <video>
Only the most recent versions of the big five (Firefox, Chrome, Safari, IE, Opera) support <video>, so you have to have a fallback solution of some kind if you want to use <video> and still support your audience.
2. Newer browsers don’t support the same codecs
Sadly, different browsers support different codecs. H.264 works in Chrome, Safari, and IE9, while Firefox and Opera only support Ogg/Vorbis. All the major browser vendors have pledged support for Google’s recently released WebM format, but this will take some time for the browers and encoding software to catch up.
3. Fallback HTML requires multiple video files
The most common solution offered is to use nested HTML to allow browsers that don’t support <video> to fallback to flash. One of the best of these is called Video for Everybody and looks something like this:

<video>   <source src="myfile.mp4">   <source src="myfile.ogg">   <object src="flashplayer.swf?file=myfile.mp4">      <embed src="flashplayer.swf?file=myfile.mp4">   </object></video>

This works in all browsers, but it has a major problem: You must have two video files. If you attempt to use only MP4, Firefox on Opera will fail. If you remove the <source src=”myfile.ogg”>, Firefox and Opera will not fallback to the Flash <object>. They will just display a big, blank, black box with an X. The same goes if you only use OGG on browsers that don’t support OGG, or attempt to use WebM.
The HTML fallback mechanism only works if the browser doesn’t understand the <video> tag. It doesn’t work if it doesn’t understand the <source> file. So if you want to only use one file, then you must use JavaScript.
A Simple JavaScript Solution
Since I don’t want to maintain two versions of every video, I need a way to fallback to Flash for non-H.264 browsers. Here’s my simple solution using jQuery.

<video id="my-video">
   <source src="myfile.mp4" type="video/mp4">
</video>
<script>
(function() {
  var video = document.createElement("video");
  if ( typeof(video.canPlayType) == 'undefined' || // detect browsers with no <video> support
       video.canPlayType('video/mp4') == '') { // detect the ability to play H.264/MP4
       var video = $('#my-video');
       var videoUrl = video.find('source').attr('src');
       var flashUrl = '/flash/myplayer.swf';
       // create flash
       var flash = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +
				'	codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ' +
				'	width="' + video.width() + '" height="' + video.height() + '" id="fallbackplayer">' +
				'		<param name="allowfullscreen" value="true" /> ' +
				'		<param name="movie" value="' + flashUrl + '?mediaUrl=' + videoUrl + '" /> ' +
				'		<embed id="dtsplayer" width="' + video.width() + '" height="' + video.height() + '" allowfullscreen="true" allowscriptaccess="always" ' +
				'			quality="high" name="fallbackplayer" ' +				'			src="' + flashUrl + '?mediaUrl=' + videoUrl + '" ' +
				'			type="application/x-shockwave-flash" /> ' +
				'</object>';
        // insert flash and remove video
        video.before(flash);
        video.detach();
  }
})();
</script>

The code is fairly simple. It just checks if the browser understands the <video> tag by checking for the “canPlayType” function, then it uses canPlayType to determine if the browser can play an H.264/MP4. If not, it inserts Flash as a fallback.
Please note: This is a simplified script for example purposes only. It needs flash version detection, and it should be turned into a jQuery extension, but it should still be a nice guide for

8 thoughts on “Simple Cross-Browser HTML5 video with a single H.264 file and fallback options

  1. Thanks for posting this. Am I right in assuming that with this script Firefox will default to the Flash player since you are no longer uploading the .ogg file? I have been uploading both for now. But I haven’t done any really large videos, so encoding and uploading to Ogg Theora hasn’t been a big deal.

  2. hejo … I’ve got this running successfully with jquery 1.2(x) in a drupal cms with flac codec ogg files …. had to change the timeline.delegate to the old bind method and it works like a charm….
    Greetings and thanks for the great code.
    Mark

  3. Wow nice scripting… 🙂 Is it possible to loop the mp4 in Flash/IE ? I tried to add "autoRestart=true" parameter in mediaelement.js but i cant get it to work 🙁

  4. Hi
    It is not working for me with mozilla firefox. Could you please send me jquery script?
    with above script, it is showing black screen only.

  5. Hi,
    Sorry, but despite your dayjob is webdesign and mine is not, I urge to please revisit the content of your post:
    – your code wont work without the unneeded javascript
    – you should use explain using multiple source tags as fallback
    – the fallback object should be inside the video object!
    – your SWF embed code is invalid, and valid it would work better (codebase, classid do not exist, just like Adobe’s made-up embed tag in the pre HTML5 erra does NOT exist. Having valid Flash embedding works better (I’ve seen hunderds of browsers now). It’s because browser vendors follow W3C and not Adobe.
    – the detach function does not remove the element, so likely to waste CPU, and in some cases to play content double (the 2nd player being invisible). You better use .remove()
    – video.canPlayType() never returns 0 or 1 (but “”, “maybe”, “probably”), so let the player remove the fallback a.s.a. it’s clear it’s not needed anymore. For example onplay=”$(‘#fallb’).remove()”
    I have not done much HTML5 but already server millions of videos, and started to use the video tag before vimeo and youtube did it on their sites.
    Please have a look at the player at http://unicycle.tv/en/play.php?v=1419-utvteamvideo2013 for a better example, and modify your post, as that would be of better help to others. Thanks for the effort!

Comments are closed.