How I Got HTML Video Working Cross Browser

I have been researching HTML video for quite a while and I am trying to find a version that works well across all browsers, so hopefully this will help someone else. I have been using and literally testing this in almost every browser known to man. The solution I’ve got currently works in Opera, Chrome, Firefox 3.5+, IE8+, iPhone 3GS, iPhone 4, iPhone 4s, iPhone 5, iPhone 5s, iPad 1+, Android 2.3+, Windows Phone 8, and Blackberry Browser 9900.

Dynamically Changing Sources

Dynamically changing a HTML video <source> is very difficult, and with a Flash fallback you will have to remove the video from the DOM/page and re-add it so that Flash will update because Flash will not recognize dynamic updates to Flash vars. If you’re going to use JavaScript to change it dynamically, I would completely remove all <source> elements and just use canPlayType to set the src in JavaScript and break or return after the first supported video type and don’t forget to dynamically update the flash var mp4. Removing and adding video elements can slow down the browser because it continues buffering the removed video, but there’s a workaround. Also, some browsers won’t register that you changed the source unless you call video.load().

Cross-browser Support

As far as the actual cross-browser portion, I arrived at Video For Everybody as well. I already tried the MediaelementJS WordPress plugin, which turned out to cause a lot more issues than it resolved. I suspect the issues were due to the WordPress plug-in and not the actually library. I’m trying to find something that works without JavaScript, if possible. So far, what I’ve come up with is this plain HTML:

<video width="300" height="150" controls="controls" poster="" class="responsive">
    <source src="" type="video/ogg" />
    <source src="" type="video/mp4" />
    <source src="" type="video/webm" />
    <source src="" type="video/mp4" />
    <source src="" type="video/mp4" />
    <object type="application/x-shockwave-flash" data="" width="561" height="297">
        <param name="movie" value="" />
        <param name="allowFullScreen" value="true" />
        <param name="wmode" value="transparent" />
        <param name="flashVars" value="config={'playlist':['',{'url':'','autoPlay':false}]}" />
        <img alt="No Video" src="<?php echo $meta['video_poster']; ?>" width="561" height="297" title="No video playback capabilities, please download the video below" />
    <strong>Download video:</strong>  <a href="video.mp4">MP4 format</a> | <a href="video.ogv">Ogg format</a> | <a href="video.webm">WebM format</a>

Live example:

Important notes:

  • I ended up putting the ogg as the first <source> because Mac OS Firefox quits trying to play the video if it encounters an MP4 as the first <source> (doesn’t follow the spec).
  • The correct MIME types are important .ogv files should be video/ogg, not video/ogv
  • If you have HD video, the best transcoder I’ve found for HD quality OGG files is Firefogg
  • The .iphone.mp4 file is for iPhone 4+ which will only play videos that are MPEG-4 with H.264 Baseline 3 Video and AAC audio. The best transcoder I found for that format is Handbrake, using the iPhone & iPod Touch preset will work on iPhone 4+, but to get iPhone 3GS to work you need to use the iPod preset which has much lower resolution which I added as video.iphone3g.mp4.
  • In the future we will be able to use a media attribute on the <source> elements to target mobile devices with media queries, but right now the older Apple and Android devices don’t support it well enough.
  • If your video is on a page that could be loaded using HTTPS or HTTP, avoid specifying a protocol in your URLs. For instance,

    instead of

    is perfectly valid according to the RFC.