Fun with HTML Video

These days, formulating a video playback experience is a complicated and broken process… especially when streaming. The ideal for us, in the specific case referenced in this article, is to deliver a stream over Real Time Messaging Protocol (RTMP) via Adobe Media Server into Strobe Media Player or some other Flash-based player for a robust, feature-rich video experience. On devices which do not support Flash Player, fall back to HTTP Live Streaming (HSL) using the HTML video tag for a simplified experience. For those older browsers which do not support the video tag and do not have Flash Player installed… provide a small message letting the user know why they cannot view the stream.

This should be simple and the approach we are taking is to set up a container div element which includes the video tag with fallback to a simple set of plain text compatibility messaging. If Flash Player is detected, we use the SWFObject JavaScript library to overwrite everything in our container element, embedding the Flash object for playback.

The main problem we had with this approach is that while many browsers do support the video tag for fallback from Flash Player – hardly any actually support streaming over the video tag using HLS. In fact, the only ones that do are basically OSX Safari (with certain additional requirements) and iOS Safari… that leaves a lot of browsers out of the mix. Sure, just about anything else can use Flash Player for a playback solution – but some people either have this disabled or just not installed (~2% at the university level, incidentally). One would expect that the fallback message would be displayed in this case as per the HTML5 specs, but not so.

Take Internet Explorer 9, for example. With Flash Player disabled, it picks up the video tag and even displays the specified poster frame correctly. We get the right-click video controls menu as well… but since HLS streaming is not supported in that browser – it will not play. What is worse – the fallback messaging never appears since the video tag is supported and actually renders a video container. The result of all this is a completely broken experience for users as it will appear as though the video loads (the poster does load!) but nothing useful ever happens.

To get around all this, there is a JavaScript method we can use to detect whether a stream type is supported and then react to that.

The first things we must do is get a video element for reference. Any video element will do but a simple way of just grabbing the first one is to invoke the following:

var video = document.getElementsByTagName("video")[0];

This will grab the first video element in the document and assign a reference to a variable. Next, we can see whether the video method canPlayType() is actually supported by testing against the following:

if (video.canPlayType) { }

So long as the  canPlayType()  method is available, we can get more specific and test against a certain stream or file type – depending upon our needs. I’m serving an HLS stream through .m3u8 so will test against the mime type of application/x-mpegURL as below:

if (video.canPlayType("application/x-mpegURL")) {
	//nothing;
} else {
	$("#MediaPlayer").append("<p class='failmsg'>This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.</p>");
}

If it is supported, I do nothing – but if it is not supported… I write out a message that is styled and positioned over the poster frame via CSS which lets the user know what’s up.

Of course, this is a lot simpler if we are just serving up simple files off of a local web server – but what fun is that?  :)

Here are the final bits of code:

<div id="MediaPlayer">
	<video id="HLSPlayer" width="320" height="240" poster="<cfoutput>#posterpath#</cfoutput>" src="<cfoutput>#htmlsource#</cfoutput>" controls>
        This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.
    </video>
    <script type="text/javascript">
		var w = $(document).width();
		var h = $(document).height();
		$("#HLSPlayer").width(w);
		$("#HLSPlayer").height(h);
		var video = document.getElementsByTagName("video")[0];
		if(video.canPlayType) {
			if (video.canPlayType("application/x-mpegURL")) {
				//nothing;
			} else {
				$("#MediaPlayer").append("<p class='failmsg'>This browser does not support Adobe Flash Player or the HTML video tag using HLS streaming. You will need to view this stream on a compatible device using either of these methods.</p>");
			}
		}
	</script>
</div>

2 thoughts on “Fun with HTML Video”

  1. That doesn’t sound like fun.

    :-)

    The canPlayType function doesn’t really guarantee a user will be able to view a video, either. But you can increase your chances by passing in both the video and audio codecs as additional parameters.

    Good luck.

Leave a Comment

Your email address will not be published. Required fields are marked *