Fallback HTML5 audio tags for a simple MP3 podcast are harder than you'd think
I've been spending the evenings and weekends lately redesigning the blog and the Hanselminutes podcast site. I hadn't realized how cheesy looking the podcast site was all these years. I'd like to get the show expanded to a wider audience as I feel that listenership has kind of flattened lately. I am in the process of adding faces for ALL 360+ shows going back 6 years.
A big thanks to Lynsey Smith from Portland Girl Geek Dinners, by the way, for her hard work in finding pics for me!
I also wanted a nicer in-browser audio experience so I assumed I'd just drop in the audio tag and be done, right?
The HTML5 Audio tag is wonderful, right? Just works. This is the dream:
<audio id="audioplayer" preload="metadata" type="audio/mp3" >
<source src="http://s3.amazonaws.com/hanselminutes/hanselminutes_0363.mp3" type="audio/mp3"/>
Your browser doesn't support the HTML audio tag. Be sad.
</audio>
You can try that live at http://jsfiddle.net/CdxbX/ if you like.
Except it's not nearly that easy.
Here's what you'll see on IE9+:
Here's Chrome:
Here's Firefox, version 19:
Ya, Firefox currently doesn't support MP3 audio so it just flashes once then disappears. Firefox will support MP3s in audio soon though by using the underlying operating system to play the stream rather than its own embedded code.
In Firefox 20 (the beta channel) on Windows 7 and above, you can test MP3 Audio support by turning on the preference media.windows-media-foundation.enabled
in about:config.
The part I was disappointed in was more of an HTML5 specification issue. Notice that while I have fallback text present, I don't see it in Firefox. That's because fallback elements are only used if your browser doesn't support the audio tag at all.
It doesn't do what I would expect at all. What I want is "Can you support any of these audio sources? No? Fallback." This seems intuitive to me.
I talked to Chris Double via Christian Heilmann at Mozilla and he said "You'd need to raise the issue with WHATWG/W3C. It's been debated before in the past. " Indeed it has. From Oct 2009, more people saying that it's not intuitive to fall back in this way:
I expected (incorrectly, in this case) that if I only produced one source element (an MP4), Firefox would drop down to use the fallback content, as it does if I include an object element for a format not supported (for example, if I include a QuickTime object and QT is not installed, the user sees fallback content). As far as I can see, the only option in this situation is to rely on Javascript and the video element's canPlayType() function. - Kit Grose
This lack of an intuitive fallback means that I can't make an audio player that works everywhere using just HTML. I have to use JavaScript, which is a bummer for such a fundamental scenario.
Getting HTML5 audio to fall back correctly in all browsers
Instead you have to make an audio tag dynamically, then interrogate the tag. This applies to both audio and video tags. I ended up using some code from my friend Matt Coneybeare.
<audio id="audioplayer" preload controls loop>
<source src="audio.mp3">
</audio>
<script type="text/javascript">
var audioTag = document.createElement('audio');
if (!(!!(audioTag.canPlayType) && ("no" != audioTag.canPlayType("audio/mpeg")) && ("" != audioTag.canPlayType("audio/mpeg")))) {
AudioPlayer.embed("audioplayer", {soundFile: "audio.mp3"});
}
</script>
The AudioPlayer.embed at the end there is the WordPress AudioPlayer in standalone form. This way on Firefox I get the flash player since it answered false to canPlayType.
A Responsive and Touch-Friendly Audio Player in HTML5
However, the default audio player made by the <audio> tag is kind of lame, and I'd like it to better support touch, look great on tablets, etc. For this, I'll turn to Osvaldas Valutis's AudioPlayer. It's a nice little jQuery plugin that replaces the <audio> element with a lovely chunk of HTML. Since you can't actually style the HTML5 <audio> element, people just hide it, recreate it, then broker calls over to the hidden-but-still-working audio element.
This plugin, along with a little CSS styling of its default colors gives me a nice audio player that looks the same and works everywhere. Except Firefox 19/20 until the next version Firefox answers true to "canPlayType" and then it should just start working! Until then, it's the Flash fallback player, which works nicely as well.
The other problem is the QuickTime plugin that most Firefox users have installed. When styling with the Osvaldas' AudioPlayer, the JavaScript interrogation would cause Firefox will prompt folks to install it in some cases if it's not there, and it still doesn't work if it is installed.
I ended up modifying Matt's detection a little to work with this Osvaldas' styling. I realize the code could be more dynamic with less elements, but this was easier for me to read.
- First, try the audio tag. Works? Great, style it with audioPlayer();
- Can't do MP3 audio? Dynamically make a Flash player with that P. Hide the audio player (likely not needed.)
Unfortunately for readability, there's the ".audioPlayer" jQuery plugin that styles the HTML and there's the "AudioPlayer" flash embed. They are different but named the same. I didn't change them. ;)
<audio id="audioplayer" preload="auto" controls style="width:100%;" >
<source src="your.mp3" type="audio/mp3">
Your browser doesn't support the HTML audio tag. You can still download the show, though!
</audio>
<p id="audioplayer_1"></p>
<script type="text/javascript">
var audioTag = document.createElement('audio');
/* Do we not support MP3 audio? If not, dynamically made a Flash SWF player. */
if (!(!!(audioTag.canPlayType) && ("no" != audioTag.canPlayType("audio/mpeg")) && ("" != audioTag.canPlayType("audio/mpeg")))) {
AudioPlayer.embed("audioplayer_1", {soundFile: "your.mp3", transparentpagebg: "yes"});
$( '#audioplayer').hide();
}
else /* Ok, we do support MP3 audio, style the audio tag into a touch-friendly player */
{
/* If we didn't do the "if mp3 supported" check above, this call would prompt Firefox install quicktime! */
$( '#audioplayer' ).audioPlayer();
}
</script>
All in all, it works pretty well so far.
ODD BUG: Chrome does seem to have some kind of hang where this audio player is getting blocked while the comments load on my site. Any JavaScript experts want to weight in? If you load a page - like this one - and hit play before the page is loaded, the audio doesn't play. This only happens in Chrome. Thoughts?
While you're here, check out the new http://hanselminutes.com and consider subscribing! It's "Fresh Air for Developers."
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
I'm building a content management system at the moment and I can't find a nice easy extensible html standards compliant editor.
Tiny MCE is probably one of the best but looking at the underlying code ... it's generating iframes !!! how 1990 is that!!!
I then found Aloha which looks good but is rather vague on details around how to extend / work with it and my current implementation has rather randomly added a slide out side bar panel full of hidden elements that actually i really like but i'm worried that if use it it'll probably break something else.
So any ideas on a decent html 5 editor that i can "switch on or off" with jquery easily?
sorry to hijack your post :)
Once again it looks like we're going to wind up with a bone-headed spec. Who on Earth made the decision that when content fails to load then the fallback should not be used because... uh, if the content did load then it wouldn't be needed? Do these people not realise that they're going to saddle us with a spec that, like the awful Javascript mess we have to wade through now, will last decades? Scott, your expectations of the fallback attribute were clearly correct, and this committee has grown too large and too religious for its own good. And why can't we style the audio tag element? WHY?! How arbitrary!
On an off-topic note, it blows me away that people continue to use Failfox. I know it's a religious argument, but damn that's a horrible browser. IE and Chrome are superior in every single way (except MAYBE plugins/addons, but honestly I only use 2 Chrome addons and could live without either).
I mean, it's not like still using IE6 in XP - you have to actively go out and download Firefox. You're running this junk intentionally? Come on, man.
Sorry for the rant, keep up the good work, Scott.
What's so bad about it? ... I constantly find the javascript engine in IE lacking and chrome often does stuff that no other browser does (like randomly positioning elements).
I find that firebug (a plugin for firefox) is probably the best tool I have in my arsenal when trying to debug client side code because both IE and chrome tools just feel clunky to me and firebug is a plugin that can further be extended in itself.
When they release firebug for IE i might like IE better but my biggest issue with it is corporate attitudes ... everything must work on IE 7+ ... WHY !!!!
If something doesn't work on chrome or firefox the attitude is always "oh you just need to update" but with IE its always "oh we can't update that it has to be rolled out by the systems team and app X that isn't completely ok with that so lets just stay with it".
That in my opinion is a lot worse than the worst experience you would ever have in Firefox.
Chrome looks nice but just doesn't feel polished enough yet from a development tooling point of view ... i can use it and often do but as soon as i get a problem i fire it up in firefox.
http://stackoverflow.com/questions/784929/what-is-the-not-not-operator-in-javascript
http://mediaelementjs.com/#devices
A quick note: I checked your ODD BUG on Chrome 25.0.1364.172 m and can't verify your issue.
Basically, the control wasn't very well optimised and it would re-calculate a lot of positioning every time the user did something (hit a key, moved mouse, etc). All browsers except of Chrome appear to have different threads for input and JS (so, even though the CPU usage went up, the user didn't notice any delay) whereas on Chrome the user would type "abc" and would see "a" then wait 0.5s then see "b", etc.
Not sure if it's related to your problem, but it sounds similar to me.
Try video !!! - well it's at least as hard to make as audio
take a look here The State Of HTML5 Video
Firefox of all modern browsers require its own special video format with its own special audio-track because, oh no, h264 MP4 with HighDef AAC isn't good enough. As a 'video producer' you need to re-encode your video in 2 formats just to satisfy all browsers :-(
And don't even think about providing Captions (text-track) to your video - it simply doesn't work out of the box eventhough every browser claim it supports it. Captions only work if you do magic tricks with Javascript - and iPad / iPhone / Android doesn't support HTML5 Captions, AT ALL...
HTML5 is far behind Silverlight and Flash, so it's no wonder that developers are hesitant to using HTML5-only - i dont blame them :-)
<audio>
<source src="whatever.mp3" type="audio/mp3" />
<source src="whatever.ogg" type="audio/ogg" />
Your browser doesn't support the HTML audio tag. Be sad.
</audio>
Again, this doesn't solve the problem and requires two different files (which might be a whole new set of problems), but a Flash/Javascript fallback is far from ideal IMHO.
Perhaps this solution has some drawbacks (apart from the obvious conversion hell), but I would yet have to see it.
Browser Plugins are there to solve problems that HTML can't. When HTML rises to the occasion, THEN we remove the hacks.
Perhaps I expressed it badly in the previous reply, but the OGG+MP3 HTML5 solution doesn't solve the root problem (there might be other HTML5 compliant browsers which do not support any of those formats). I just wanted to point out that it is another solution that should cover most of the browsers around and the double encoding trouble might be acceptable, depending on your situation. Of course, re-encoding the whole Hanselminutes archive is unfeasible. :)
So in my case I of course already have all the different formats hosted somewhere, anyway.
This might be the reason for why I felt it to be rather natural to just use the existing formats that are there in the open anyway instead of even thinking about fixing a non-intuitive fallback. Especially as the Firefox solution is just around the corner.
And btw, I did not call my solution elegant, but rather "far from being a hack" ;)
Tracking events in GA with javascript probably isn't too bad, but that wouldn't work for Flash unless the particular player that you're using supports it.
The people at W3C implementing HTML5 wanted to do their part to correct this, but since the mp3 file's popularity is still existent even to this day, despite the fact that there is no reason whatsoever, the "insight" (at that time) to further attempt to deprecate it as a standard mostly backfired.
I'm not sure what your current computer situation is now, but if you have a modern sound card (even integrated with newer Intel Chipsets) it would only take a day to convert 27,000 megs as you indicated. Then the resulting conversion should fit handily onto a 32 gig USB Flash Drive, if you head over to newegg they will ocassionaly have Toshiba(Good Brand) of these 32 GIGS on sale for less then 20$.
As a web designer, I would never recommend anyone to ever fallback to ecma/java script in this day and age.. In fact I highly recommend to any tech savvy friends I have to use the noscript/safescript plugin for their browser or simply turn it off altogether.
Comments are closed.
Strange, i've been battling with all sorts of random "client side page lifecycle" issues like this lately, it reminds of the days when I spent most of my time dealing with webforms (i'm lucky enough to have the wonder that is MVC day to day nowadays).
Possible suggestions you could try:
2. ajax load the comments after the initial page load (it'll take most people a few seconds to read that far down an average page of yours anyway Scott lol)
3. it might be some oddity around jquery, i've seen unusual things with minified versions so try testing it without (just the other day i had IE take over 1 minute to load a page until I gave it the un minified version of jquery), my jquery comes from nuget so not sure what that's about.
Google are always saying how their new js virtual machine is something new and special and faster than anything else then you see something like this: http://arstechnica.com/information-technology/2008/09/new-firefox-javascript-engine-is-faster-than-chromes-v8/
... maybe its a threading issue in the browser code or something?
Still at least IE is playing ball this time! (there's a first right?)