Scott Hanselman

Fallback HTML5 audio tags for a simple MP3 podcast are harder than you'd think

March 26, '13 Comments [33] Posted in HTML5 | Javascript
Sponsored By

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+:

image

Here's Chrome:

image

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.

Flash audio player in Firefox

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.

image

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. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Tuesday, March 26, 2013 8:52:50 PM UTC

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?


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:

  • 1. render a "loading spinner" in place of the audio player until the page loading is done (you could call some "im done" type function).

  • 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?)
Tuesday, March 26, 2013 8:57:35 PM UTC
Oh yeh, off topic for this post but I was wondering ....

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 :)
Tuesday, March 26, 2013 9:14:40 PM UTC
It's a little disappointing that HTML5 is still so far from being "baked", even in so-called "modern" browsers. This is one of dozens of examples. I think the web at large has been too hasty in getting rid of plugins like Flash and Silverlight - in my opinion they're an imperfect solution to a problem, but no good solution is ready yet.

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.
Tuesday, March 26, 2013 9:25:54 PM UTC
Wonder if I'm the only person that get's thrown for a loop when I see "!!" when reading JS code. I still have no idea what's going on is it inverting an inverted value thus changing it right back to it's original value o_O
RandomCommenter
Tuesday, March 26, 2013 9:29:33 PM UTC
Wow Martin ... you really dont like firefox huh?

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.
Tuesday, March 26, 2013 9:51:38 PM UTC
RandomCommenter - Ya, it's weird. I read it as "bang bang, you're a boolean!" It's a way to "typecast" something that's not quite a boolean to a full boolean.

http://stackoverflow.com/questions/784929/what-is-the-not-not-operator-in-javascript
Tuesday, March 26, 2013 10:14:09 PM UTC
Have you looked into mediaelementjs?
Davin
Tuesday, March 26, 2013 10:16:48 PM UTC
Davin - Yes, but it's not very friendly with audio on mobile phones. It works great for video, not so much for podcasts. Do you know differently?
Tuesday, March 26, 2013 10:42:05 PM UTC
Thanks for the code. The fallback mechanisms are really a challenge in HTML5.
PRMan
Tuesday, March 26, 2013 10:55:39 PM UTC
I have used it for mp3 files ... on desktop and phone browsers. Not sure how it is unfriendly with mobile phones.

http://mediaelementjs.com/#devices
Davin
Tuesday, March 26, 2013 11:17:21 PM UTC
Davin - Hm, when I tried it last year I only got tiny audio layouts on retina iphones. I'll look again! Thanks for your comment!
Tuesday, March 26, 2013 11:30:41 PM UTC
Ah ... that might still be not sure ... don't have a retina iOS device.
Davin
Wednesday, March 27, 2013 7:18:59 AM UTC
Thanks, that was quite an interesting read.

A quick note: I checked your ODD BUG on Chrome 25.0.1364.172 m and can't verify your issue.
Frank Dumont
Wednesday, March 27, 2013 7:36:12 AM UTC
Regarding the Odd Chrome bug, I've encountered something somewhat similar a couple of years ago when using some custom Silverlight controls that translated to Javascript.

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.
Vlad
Wednesday, March 27, 2013 9:22:50 AM UTC
so you think that audio is hard ?
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 :-)
Wednesday, March 27, 2013 9:51:18 AM UTC
If we had our Silverlight back, this wouldn't be an issue. ;)
Wednesday, March 27, 2013 3:52:26 PM UTC
I think I may start using that thread you referenced as the canonical example for "Ivory Tower Design". The bit about achieving a universal codec underscores how out of touch W3C is. Talk about operating within a bubble.
Wednesday, March 27, 2013 6:31:16 PM UTC
This doesn't solve the underlying problem (in fact, it might be more of a hassle), but double encoding the original file to MP3 and OGG/Vorbis should cover more or less all browsers supporting the audio tag (including Firefox and Opera).

<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.
Friday, March 29, 2013 10:41:03 AM UTC
Lorenz: this is precisely what I did, too - far from not being a hack, but much nicer and cleaner than any Flash or Javascript fallback.

Perhaps this solution has some drawbacks (apart from the obvious conversion hell), but I would yet have to see it.
Ron Nanko
Friday, March 29, 2013 4:24:41 PM UTC
I'm really not understanding how you guys think a one-time and temporary flash hack for a browser that has *already* committed to MP3 support (it's in their nightlies) is BAD, but me converting 360+ existing podcasts shows to Ogg, taking up 27,000 megs of addition storage for 8% of the audience is an elegant solution.

Browser Plugins are there to solve problems that HTML can't. When HTML rises to the occasion, THEN we remove the hacks.
Friday, March 29, 2013 4:36:22 PM UTC
No, I fully agree with you Scott. Double encoding is incredibly inefficient in terms of storage and in terms of workflow impact: this is also true for YouTube double encoding everything in H.264 AND WebM which is even more absurd.

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. :)
Friday, March 29, 2013 4:39:19 PM UTC
Lorenz - Gotcha. :) I just wish that the authors of the original spec had really thought the multiple codec fallback through.
Friday, March 29, 2013 4:43:15 PM UTC
Scott, perhaps I should have elaborated a little bit more on my situation, then. Being a musician (ah, not really, I am a drummer :D) for two decades, I am dealing with literally thousands of sound snippets that are published to literally hundreds of online platforms/sites in literally dozen formats (mp3, ogg, wav and don't get me started on bitrates).

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" ;)

Ron Nanko
Monday, April 01, 2013 3:09:16 PM UTC
I've noticed that Chrome hangs in general now and have gone back to Firefox again. It would be nice if Chrome worked like it did when it was first created. Now, it seems, that FF is the browser that just works. I have looked at IE but I don't like how it renders (not as pretty).
jon
Thursday, April 04, 2013 10:40:11 AM UTC
Scott, maybe you can try to put the JavaScript for loading the comments into a 'setTimeout' with between 100 and 2000 ms timeout, just to see if this clears up any collisions.
Friday, April 05, 2013 8:19:39 PM UTC
This is related: Making HTML5 audio actually work on mobile http://pupunzi.open-lab.com/2013/03/13/making-html5-audio-actually-work-on-mobile/
Tuesday, April 09, 2013 2:42:36 AM UTC
Scott, do you currently track download statistics of your podcast? Especially with the varying sources and options for listening to a podcast, how would you suggest tracking downloads with either Google Analytics or some other tool?

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.
Tuesday, April 09, 2013 4:27:21 AM UTC
Scott - I use LibSyn and it uses Referrals + User Agents. It's pretty accurate.
Saturday, May 04, 2013 11:42:46 PM UTC
Scott, thank you for this simple solution. I just wanted something *simple*, not fancy or filled by advanced functionalities. That's just this: it plays cross-browser perfectly most of the time! (maybe every time! :)
Rudolfo Pacheco
Tuesday, July 23, 2013 2:41:04 AM UTC
For what it's worth, the audio widget was disappearing for me too, but it wasn't due to any problem in Firefox; some comment software on the blog was kicking in and hiding it. So giving the audio tag a CSS style of z-index:2 prevented it from disappearing and it works better -- though not for everyone!

Richard Chonak
Wednesday, August 21, 2013 9:26:33 PM UTC
DUDE - get an image that is NOT a blinking animated GIF for the Firefox screenshot - Damn !!
billy bob
Thursday, September 19, 2013 10:46:04 PM UTC
This is awesome Html5 Soundboard -> http://bit.ly/15878zW
teodora
Monday, September 23, 2013 6:10:12 PM UTC
I'm pretty late in finding this issue, but the most unfortunate truth with your problem is that even before your show started 7 or whatever years ago, the mp3 format was already deprecated; but since anyone in this millenium who can read at a 3rd grade level and has a computer can make their own blog, the use of MP3 files never stopped when it needed to.

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.
Jeff McClarty
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.