Email Updates RSS Subscribe
Line

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.

Launch
Line

Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit www.byhook.com.

Line

HTML5 Video with Flash Fallback / Flash Video with Mobile Fallback*

Line
Posted on July 28th, 2010 by Michael
Line

*Due to popular demand on The Twitter, the name of this post was changed.
**Check out Norm’s new post for our easy to use javascript html5 video library and WordPress plugin.

We’ve recently been crafting a new site for our company (view it here) and fate bestowed upon me the task of developing the HTML version of the site.  (Actually, it was my poor performance in a finger pulling contest, but I like to think a higher power, The Lich King, was involved).

Since we are also developing a full flash version of the site, the goal of the HTML version was to rely mainly on Web Standards and the newly popular HTML5 video tag for showcasing moving pictures.

This was my first attempt at integrating HTML5 and I quickly learned that a number of quirks must be addressed when deploying video in this fashion.  There’s nothing groundbreaking about this post; however, I’m hoping it serves to be a comprehensive summary of how to integrate HTML5 with the following criteria:

- Compatibility with all current browser implementations of HTML5 (H.264 and Theora)
- Flash fallback for older gen browsers
- Platform detection
- Mobile device support

The final result of my efforts can be viewed here by a Desktop PC or iOS / Android device: http://labs.byhook.com/html5video/

The Code

With the plot set, let’s get started…  My first stop on the tour was:  http://camendesign.com/code-is-art/video_for_everybody.  While the author seems to have a visceral hatred for a certain 3rd party plugin, he does have a nice write up on HTML5 video with Flash fallback.  However, he seems to stop a bit short when it comes to platform detection and Android support.  With his code in hand, I started out with an already working model:

<video width="980" height="390" controls autobuffer>
 
	<!-- MP4 must be first for iPad! -->
	<!-- WebM videos can also be added here -->
	<source src="telematics_desktop.mp4" type="video/mp4" /> <!-- Webkit video -->
	<source src="telematics_desktop.ogv" type="video/ogg" /> <!-- Firefox / Opera -->
 
	<!-- Fallback to Flash. -->
	<!-- Add 24px to the height for the video player -->
	<object width="980" height="414" type="application/x-shockwave-flash" data="http://www.byhook.com/html/video/player.swf">
 
		<!-- Firefox uses the `data` attribute above, IE/Safari uses the param below -->
		<param name="movie" value="player.swf" />
		<param name="allowFullScreen" value="true" />
		<param name="flashvars" value="file=telematics_desktop.flv&image=telematics_desktop.jpg" />
 
		<!-- Fallback image. -->
		<img src="telematics_desktop.jpg" width="980" height="390" alt="telematics" title="No video playback capabilities." />
 
	</object>
 
</video>

**Note:  Any player can be used in the flash embed.  I used the free version of JW Player.  Also, I updated the flash code since the poster frame syntax wasn’t working and the full screen param was missing.

Next up was adding in some basic User Agent conditionals to steer visitors to the right content for their platform (mobile or desktop):

<script language="JavaScript" type="text/javascript">
<!-- Platform Detection -->
if( navigator.userAgent.match(/webOS/i) ||
	navigator.userAgent.match(/iPhone/i) ||
	navigator.userAgent.match(/iPod/i) ||
	navigator.userAgent.match(/iPad/i) ||
	navigator.userAgent.match(/Android/i)
	){
		document.write('<video width="480" height="192" controls autobuffer poster="telematics_mobile.jpg">');
 
			document.write('<source src="telematics_mobile.mp4" type="video/mp4" />'); <!-- Webkit video -->
 
			<!-- Fallback image. -->
			document.write('<img src="telematics_mobile.jpg" width="480" height="192" alt="telematics" title="No video playback capabilities." />');
 
		document.write('</video>');
	}
else
  	{	
		document.write('<video width="980" height="390" controls autobuffer>');
 
			<!-- WebM videos can also be added here -->
			document.write('<source src="telematics_desktop.mp4" type="video/mp4" />'); <!-- Webkit video -->
			document.write('<source src="telematics_desktop.ogv" type="video/ogg" />'); <!-- Firefox / Opera -->
 
			<!-- Fallback to Flash. -->
			<!-- Add 24px to the height for the video player -->
			document.write('<object width="980" height="414" type="application/x-shockwave-flash" data="player.swf">');
 
				<!-- Firefox uses the `data` attribute above, IE/Safari uses the param below -->
				document.write('<param name="movie" value="player.swf" />');
				document.write('<param name="allowFullScreen" value="true" />');
				document.write('<param name="flashvars" value="file=telematics_desktop.flv&image=telematics_desktop.jpg" />');
 
				<!-- Fallback image. -->
				document.write('<img src="telematics_desktop.jpg" width="980" height="390" alt="telematics" title="No video playback capabilities." />');
 
			document.write('</object>');
 
		document.write('</video>');
    }
</script>

Last on the list was making sure that the above code worked on all our target platforms.  In testing the system thus far, we came to find out that HTML5 video isn’t fully supported in the native Android browser.  Thankfully, I was able to find some info on how to resolve the problem: http://stackoverflow.com/questions/1711078/html5-video-element-on-android

When adding the Android handler into the batter, I ended up including some conditionals around the code since having it active for all browsers broke some functionality.  (i.e. the play button in Safari wouldn’t work):

<head>
 
<script language="JavaScript" type="text/javascript">
<!-- Android Event Handler -->
if( navigator.userAgent.match(/Android/i))
{
 
    function init() {
      enableVideoClicks();
    }
 
    function enableVideoClicks() {
      var videos = document.getElementsByTagName('video') || [];
      for (var i = 0; i < videos.length; i++) {
        // TODO: use attachEvent in IE
        videos[i].addEventListener('click', function(videoNode) {
          return function() {
            videoNode.play();
          };
        }(videos[i]));
      }
    }
 
}
 
</script>
 
</head>
 
<body>
 
<script language="JavaScript" type="text/javascript">
<!-- Android Event Handler -->
if( navigator.userAgent.match(/Android/i))
{
	window.onload = init;
}
</script>	
 
<script language="JavaScript" type="text/javascript">
<!-- Platform Detection -->
if( navigator.userAgent.match(/webOS/i) ||
	navigator.userAgent.match(/iPhone/i) ||
	navigator.userAgent.match(/iPod/i) ||
	navigator.userAgent.match(/iPad/i)
	){
		document.write('<video width="480" height="192" controls autobuffer poster="telematics_mobile.jpg">');
 
			document.write('<source src="telematics_mobile.mp4" type="video/mp4" />'); <!-- Webkit video -->
 
			<!-- Fallback image. -->
			document.write('<img src="telematics_mobile.jpg" width="480" height="192" alt="telematics" title="No video playback capabilities." />');
 
		document.write('</video>');
	}
else if( navigator.userAgent.match(/Android/i))
	{
	document.write('<video src="telematics_mobile.mp4" width="480" height="192" poster="telematics_mobile_play.jpg" controls onclick="this.play();"/>');
	document.write('</video>');
	}
else
  	{	
		document.write('<video width="980" height="390" controls autobuffer>');
 
			<!-- WebM videos can also be added here -->
			document.write('<source src="telematics_desktop.mp4" type="video/mp4" />'); <!-- Webkit video -->
			document.write('<source src="telematics_desktop.ogv" type="video/ogg" />'); <!-- Firefox / Opera -->
 
			<!-- Fallback to Flash. -->
			<!-- Add 24px to the height for the video player -->
			document.write('<object width="980" height="414" type="application/x-shockwave-flash" data="player.swf">');
 
				<!-- Firefox uses the `data` attribute above, IE/Safari uses the param below -->
				document.write('<param name="movie" value="player.swf" />');
				document.write('<param name="allowFullScreen" value="true" />');
				document.write('<param name="flashvars" value="file=telematics_desktop.flv&image=telematics_desktop.jpg" />');
 
				<!-- Fallback image. -->
				document.write('<img src="telematics_desktop.jpg" width="980" height="390" alt="telematics" title="No video playback capabilities." />');
 
			document.write('</object>');
 
		document.write('</video>');
    }
</script>
 
</body>

Now, that ends the code adventure part of the story.  However, if you are less a fan of HTML5 and wish to solely use it as a backup for non-flash and mobile users; you can simply integrate a little more conditional magic courtesy of the Adobe Detection Kit.

A demo of Flash Video with HTML5 Fallback can be seen here:  http://labs.byhook.com/html5video/flash.html

<head>
 
<script src="AC_OETags.js" language="javascript" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript">
		// Globals
		// Major version of Flash required
		var requiredMajorVersion = 8;
		// Minor version of Flash required
		var requiredMinorVersion = 0;
		// Minor version of Flash required
		var requiredRevision = 0;
</script>
 
<script language="JavaScript" type="text/javascript">
<!-- Android Event Handler -->
if( navigator.userAgent.match(/Android/i))
{
 
    function init() {
      enableVideoClicks();
    }
 
    function enableVideoClicks() {
      var videos = document.getElementsByTagName('video') || [];
      for (var i = 0; i < videos.length; i++) {
        // TODO: use attachEvent in IE
        videos[i].addEventListener('click', function(videoNode) {
          return function() {
            videoNode.play();
          };
        }(videos[i]));
      }
    }
 
}
 
</script>
 
</head>
 
<body>
 
<script language="JavaScript" type="text/javascript">
<!-- Android Event Handler -->
if( navigator.userAgent.match(/Android/i))
{
	window.onload = init;
}
</script>	
 
<script language="JavaScript" type="text/javascript">
<!-- Flash version check based upon the values entered above in "Globals" -->
var hasReqestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
 
<!-- Platform Detection -->
if( navigator.userAgent.match(/webOS/i) ||
	navigator.userAgent.match(/iPhone/i) ||
	navigator.userAgent.match(/iPod/i) ||
	navigator.userAgent.match(/iPad/i)
	){
		document.write('<video width="480" height="192" controls autobuffer poster="telematics_mobile.jpg">');
 
			document.write('<source src="telematics_mobile.mp4" type="video/mp4" />'); <!-- Webkit video -->
 
			<!-- Fallback image.  -->
			document.write('<img src="telematics_mobile.jpg" width="480" height="192" alt="telematics" title="No video playback capabilities." />');
 
		document.write('</video>');
	}
else if( navigator.userAgent.match(/Android/i))
	{
	document.write('<video src="telematics_mobile.mp4" width="480" height="192" poster="telematics_mobile_play.jpg" controls onclick="this.play();"/>');
	document.write('</video>');
	}
else if(hasReqestedVersion) {	
 
		<!-- Fallback to Flash. -->
		<!-- Add 24px to the height for the video player -->
		document.write('<object width="980" height="414" type="application/x-shockwave-flash" data="player.swf">');
 
			<!-- Firefox uses the `data` attribute above, IE/Safari uses the param below -->
			document.write('<param name="movie" value="player.swf" />');
			document.write('<param name="allowFullScreen" value="true" />');
			document.write('<param name="flashvars" value="file=telematics_desktop.flv&image=telematics_desktop.jpg" />');
 
		document.write('</object>');
 
	} else {  // Flash is too old or we can't detect the plugin
 
		document.write('<video width="980" height="390" controls autobuffer>');
 
			<!-- WebM videos can also be added here -->
			document.write('<source src="telematics_desktop.mp4" type="video/mp4" />'); <!-- Webkit video -->
			document.write('<source src="telematics_desktop.ogv" type="video/ogg" />'); <!-- Firefox / Opera -->
 
			<!-- Fallback image. -->
			document.write('<img src="telematics_desktop.jpg" width="980" height="390" alt="telematics" title="No video playback capabilities." />');
 
		document.write('</video>'); 
	}
 
</script>
 
</body>

The Codecs

Encoding the videos is pretty straightforward; however, there is a bit of a battle going on as to what the standard should be, so multiple formats are required.  The following is a table of formats supported by current browsers.  Also, most browsers have announced WebM compatibility in future release builds.

Codecs/container IE Firefox Safari Chrome Opera iPhone Android
Theora+Vorbis+Ogg · 3.5+ · 5.0+ 10.5+ · ·
H.264+AAC+MP4 · · 3.0+ 5.0+ · 3.0+ 2.0+
WebM · · · · · · ·
**From: http://diveintohtml5.org/video.html

There are a lot of options for creating H264’s, but not many for Theora files.  Google-ing around brings up a few open source encoders, but the easiest one I found was MiroConverter: http://www.mirovideoconverter.com/ All you do is drop on your source file, pick the format and hit the button.  It also has some handy presets for mobile devices.

Miro

**Note:  I was unable to encode Theora videos wider than 960px in any of the open source encoders.

Also, if you’re running Apache on your web server, you’ll need to include a .htaccess file with the following code to get the server to properly detect the video formats.

AddType video/ogg  .ogv
AddType video/mp4  .mp4
AddType video/webm .webm

One Last Thing

When displaying the video on the HTML page, the iPhone overlays a nice play button graphic on top of the video to let the user know a video is present.  Android currently doesn’t do this, so a simple fix is to just add a graphic to the poster image:

Poster

The End

There you have it folks, all that fun just to avoid using flash.  A complete collection of all the code and videos I used can be downloaded here.

Additional Reading

- http://diveintohtml5.org/video.html
- http://html5doctor.com/the-video-element/
- http://camendesign.com/code/video_for_everybody
- http://developer.android.com/guide/appendix/media-formats.html
- http://mashable.com/2010/05/18/html5-video-tools/

Line
9 Responses to “HTML5 Video with Flash Fallback / Flash Video with Mobile Fallback*”
  1. GBC says:

    Doesnt work on:

    - Safari for Windows.
    - IE 9

    IE 6 – 8 (40 % Marketshare) Will fall back to FLV flash

    IE 9 needs compatibility mode meta

  2. Hey man this is really a nice post i like it very much….

  3. Ashe Dryden says:

    Used this on a project recently and it worked great. Had a few reports of choppiness/browser freezing in Firefox, but worked perfectly in IE6-8, Safari, Chrome, iPhone (3+), and Android.

  4. Трафик says:

    Многие из них…

    но можно было всё сделать иначе…

  5. [...] and Review | GadgetPaper.com …SuperDVD Player 5 Review10 Best mobile phones | DownloadsEdgeHTML5 Video with Flash Fallback / Flash Video with Mobile Fallback … Tags: audio images, daps, iriver clix, liquid crystal display, playback capabilities, portable [...]

  6. Laurent says:

    Code is translating so i put it again with dot

    $content = str_replace(“&.n.b.s.p;”, “”, $content);
    $content = str_replace(“&.l.a.q.u.o;”, “\”", $content);
    $content = str_replace(“&.r.a.q.u.o;”, “\”", $content);

  7. Laurent says:

    Hi,
    On my wordpress server test, I had some trouble with the html encode.
    So I had to add to make the plugin work :

    $content = str_replace(“ ”, “”, $content);
    $content = str_replace(“«”, “\”", $content);
    $content = str_replace(“»”, “\”", $content);

  8. [...] This post was mentioned on Twitter by Jesse Warden and TarasNovak, Mariano KIWO Carrizo. Mariano KIWO Carrizo said: HTML5 Video with Flash Fallback and Vice Versa http://icio.us/bc1uai [...]


Leave a Reply

*

Line
Line
Pony