HTML5 Audio Loops

One of the neatest things about HTML5 is support for the new <audio> tag. Like <video> it allows you to natively support media in good browsers like Chrome, FireFox, Opera and Safari. Add a touch of JavaScript and a new era of  media applications become possible.

Synthesizers, music trackers and games require seamless audio loops though so we need something a bit simpler for our first foray into HTML5 audio.

Oooh, how about a retro beatbox with individual track adjustments (start/stop/loop/volume) that could be used to build a unique soundscape from many separate instruments. Perfect!

Fantasy can only become reality through hard work so let’s get started with some tests first.

Loop Method 1

Uses the ‘loop’ property.

<audio id="audio_1" controls preload loop>
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.ogg">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.wav">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.mp3">
</audio>

Loop Method 2

Uses a JavaScript function to loop when an ‘ended’ event is called.

<audio id="audio_2" controls preload>
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.ogg">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.wav">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.mp3">
</audio>
document.getElementById('audio_2').addEventListener('ended', function(){
this.currentTime = 0;
}, false);

Loop Method 3


Uses two JavaScript functions and two audio elements with the same source to alternate playback duties.

<audio id="audio_3" controls preload>
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.ogg">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.wav">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.mp3">
</audio>
<audio id="audio_4" controls preload>
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.ogg">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.wav">
	<source src="/wp-content/uploads/2010/04/html5-audio-loop.mp3">
</audio>
document.getElementById('audio_3').addEventListener('ended', function(){
this.currentTime = 0;
this.pause();
document.getElementById('audio_4').play();
}, false);

document.getElementById('audio_4').addEventListener('ended', function(){
this.currentTime = 0;
this.pause();
document.getElementById('audio_3').play();
}, false);

Browser Support

Tests were done on Windows 7 with Chrome 5.0.342.9 beta, FireFox 3.6.3, Internet Explorer 9.0 Preview, Opera 10.51 and Safari 4.0.5.

Chrome seems to trigger loops before the current sound is completely finished leading to some odd jumpiness. All loop methods are affected.

FireFox doesn’t seem to like the ‘loop’ property of method 1, odd. Method 2 has the slightest of delays between loops and method 3 was actually perfect! I didn’t believe it until verification at the millisecond level with Audacity. Hooray Mozilla!

Internet Explorer 9 doesn’t support the audio tag yet. Hopefully it will before an official release.

Opera performs almost as well as FireFox although there is still a small delay even when using method 3.

Safari seems slow to start playback which is very easy to detect once you hear a loop. All loop methods affected.

Feedback on other browsers/OS compatibility would be very interesting so please feel free to discuss any findings in the comments below.

Final Thoughts

As of right now (April 11, 2010) only FireFox can do a perfect loop by cheating a bit and using two <audio> elements with JavaScript.

So yeah, it’s a bit too early for HTML5 audio loops but don’t let that stop you from creating sound boards, media players and other fun things.

Hopefully with some more optimizations audio support will continue to improve and a HTML5 beatbox fantasy can become reality.

Until then there are plenty of other fun things to play with.

Cheers!


  • Stephen G says:
    April 11, 2010 at 7:14 pm

    The issue with Chrome firing the ended before the true end is a Chromium bug, issue #30452.
    http://code.google.com/p/chromium/issues/detail?id=30452
    This will likely be resolved in an upcoming Chrome 5 release.

  • Daniel says:
    April 11, 2010 at 7:44 pm

    Very good to know. Thanks for the info.

  • Parr says:
    April 11, 2010 at 11:31 pm

    Looks like Firefox doesn’t currently respect the loop or preload attributes. Time to file a Bugzilla report?

  • Abraham says:
    May 3, 2010 at 10:55 am

    works well.

  • Abraham says:
    May 3, 2010 at 10:57 am

    onended=’this.play();’ may be another choice

  • Mrrix32 says:
    May 19, 2010 at 1:22 pm

    I’m getting a seconds delay for methods 2 and 3 in Firefox 3.6.3 on Ubuntu 10.04 64bit :(

    And no looping in Chrome at all :(

  • Daniel says:
    May 19, 2010 at 2:27 pm

    Aww, sorry to hear that.

    Seems that HTML5 media really needs to be baked more in all the browsers before we can use it reliably.

    Is Chrome on Ubuntu good overall? (besides the missing looping of course)

    I love it in Windows and just started using it on a Mac too so I’m curious about any differences between platforms.

  • mako says:
    May 22, 2010 at 4:53 pm

    Mac OS X 10.6
    Opera 10.54 is the best, a perfect loop, using both methods 1 and 2 (also method 3).

    Firefox 3.6 methods 2 and 3 are not too bad, but a small pause is audible.

    Safari 4.0.5 and Chrome 5.0.375 both have longer pause period.

  • bay says:
    June 1, 2010 at 8:12 pm

    why you have .ogg .mp3 and .wav

    do I need to have the 3 formats???

  • Daniel says:
    June 1, 2010 at 9:58 pm

    Yep, but only if you want to make sure you cover the widest audience. Firefox likes .ogg, Chrome/Safari likes .mp3 and Opera 10 likes .wav.

    If you are pressed for space I would say go with .ogg and .mp3. I’m sure Opera will add support for these in the future anyway.

    Emerging web standards are not always so standard? :D

  • Magnar says:
    June 13, 2010 at 5:12 am

    Excellent info, thanks! :)

  • davomoto says:
    July 2, 2010 at 6:40 pm

    all good cross browser :-) shame ff is buggy with loop tho. can still be done anyway :-)

    document.getElementById(‘video_2′).addEventListener(‘ended’, function(){
    this.currentTime = 0;
    }, false);

  • Stephen G says:
    July 8, 2010 at 2:17 pm

    Drat! Around mid-May they fixed how Chrome was firing Ended early … but unfortunately a few releases later Chrome now doesn’t fire Ended at all!
    http://code.google.com/p/chromium/issues/detail?id=45074
    (Please “star” the issue if it affects you.)

  • flow says:
    October 6, 2010 at 9:13 am

    awsome! it wasn’t only me who had problems with solution-1 i firefox. thanks~

  • Dan says:
    November 1, 2010 at 11:52 am

    Hi,
    by the way, this html5 audio player can loop ;)

  • ben says:
    December 14, 2010 at 6:06 pm

    I made an as3 mp3 player with loop and this was not clean (lag)… I check my wav : clean, but when I save as mp3 – a 50 ms blank was added at the beggining (I read this is for a iso norm) so I add a start at 50 ms in the play( ) function and this is perfect !

  • Flávio says:
    January 6, 2011 at 1:13 pm

    Really great info!
    I agree it’s too early to start claiming HTML5 functionality from browsers, because it’s not even a recommendation from w3c yet…
    Too said, though
    :’(

  • Hay says:
    May 4, 2011 at 1:45 pm

    I’ve reported bugs for both Firefox and Chrome here, using this page as a testcase:

    https://bugzilla.mozilla.org/show_bug.cgi?id=654787
    http://code.google.com/p/chromium/issues/detail?id=81569

    The missing ‘loop’ property in Firefox is a known bug:
    https://bugzilla.mozilla.org/show_bug.cgi?id=449157

  • Lenacus says:
    May 14, 2011 at 6:50 am

    This is an shortcut for Jquery (tested under Firefox 4.0.1) :

    $(function(){
    $(‘#bg_sound’).bind(‘ended’, function(){this.currentTime = 0;});
    }

  • Justin Streufert says:
    May 24, 2011 at 11:25 am

    Today, in Chrome 11.0.696.68 on OS X, all of these examples loop absolutely perfectly!! :)

  • Daniel says:
    May 24, 2011 at 12:35 pm

    Oooh wonderful. With perfect audio loops come mixers, trackers, games and a whole host of interesting HTML5 possibilities.

  • Christoph Micklon says:
    June 4, 2011 at 2:21 pm

    Im running in circles and been trying to overcome the lack of loop implementation in Firefox for hours. Here is a snippet works fine but no loop in FF4.01

    Your browser does not support the audio element.

    $(function(){
    $(‘#bg_sound’).bind(‘ended’, function() {this.currentTime = 0;});
    }

  • Matt Giuca says:
    June 22, 2011 at 11:55 pm

    @Christoph Micklon I think you need to add this.play() as well.

  • Matt Giuca says:
    June 23, 2011 at 12:09 am

    Thanks very much for writing this article, Daniel (which at this point seems to be the primary resource for looping in HTML5!)

    I read the discussion on Mozilla bug https://bugzilla.mozilla.org/show_bug.cgi?id=654787 (posted by @Hay who commented above). The conclusion I can draw from that discussion is that your Loop Method 1 would be great if browsers supported it (but FF still doesn’t to this day). Loop Methods 2 and 3 work, but *can never be* seamless.

    Basically, if Loop Method 1 was supported, then the browser implementor would be able to program it to loop seamlessly by buffering the data from the start of the track in advance and having it loop seamlessly (down to the sample level).

    With Methods 2 and 3 (where JavaScript is involved), at the very best you will have to wait until the audio buffer clears and start a new buffer. But it’s much worse than that, because what is going to happen when the audio ends is that it pushes a new event handler on the browser’s main event loop, waits for the event loop to pump again, executes some JavaScript code, which then starts up the audio system again. So the seamlessness of those approaches will vary from browser to browser and from system to system, but it will never actually be seamless. Also I wouldn’t expect there to be any real difference between Methods 2 and 3.

    So I’d stick with Method 2 for now (and not expect seamless playback), and go over to Method 1 when browsers are ready. One suggestion (http://stackoverflow.com/questions/3273552/html-5-audio-looping) is to check whether typeof new Audio().loop == ‘boolean’, which will tell you whether the browser supports Method 1. If so, use that. If not, fall back to Method 2.

  • Daniel says:
    June 24, 2011 at 3:05 am

    That makes me feel wonderful. :)

    Oh and lots of juicy information. Good read.

    Thanks!

  • joe says:
    August 11, 2011 at 6:09 am

    is it not working at all on safari (osx 10.6, safari 5.1)? weird.

  • Caine says:
    August 18, 2011 at 1:11 pm

    I’ve tried method 2 but it’s not looping in FF6 on Linux Mint 9. What gives?

  • Dave says:
    October 15, 2011 at 2:38 pm

    Method 2 loops fine for me in Firefox 7 on WinXP. The slight delay is almost unnoticeable.

    I also added ‘autoplay’ to the list of options after ‘controls’ and ‘preload’.

    Thanks for the examples!

    Of course none of this would be necessary if Firefox would support the loop option in HTML5.

  • Indra says:
    October 26, 2011 at 11:17 am

    Thanks for this superb example. I have a question thou, if I wanted to stop an audio element from looping (after setting the loop from addEventListener) how would I do that? I tried removeEventListener with no luck (the event listener does not get removed at all) (chrome 14/ firefox 7)…

  • Daniel says:
    October 26, 2011 at 2:51 pm

    Good question!

    From what I understand you can’t easily remove an EventListener that was defined with an anonymous function like in the example above. You can however do something like this (try it via the Chrome Inspector Console)…

    var bork = function() { alert(‘bork bork bork’) };
    document.getElementById(‘audio_3′).addEventListener(‘ended’, bork, false);

    Now play audio_3 and you’ll get a special message from the Swedish Chef.

    document.getElementById(‘audio_3′).removeEventListener(‘ended’, bork);

    Now play audio_3 again and no more Swedish Chef. *sniff*

    So as long as you create your EventLister non-anonymously you should be set. :)

    More info at http://www.quirksmode.org/js/events_advanced.html and http://stackoverflow.com/questions/4950115/removeeventlistener-on-anonymous-functions-in-javascript.

  • Gary Dauphin says:
    December 30, 2011 at 5:23 pm

    As a javascript noob, I could use some advice on this little script:

    document.getElementById(‘audio_2′).addEventListener(‘ended’, function(){
    2
    this.currentTime = 0;
    3
    }, false);

    I want to use this script to redirect the browser to another web page, after the music has played. Can someone kindly show me the specific way I would do this, if the target web page was “http://mypage.com/abc.html” ?

  • Daniel says:
    December 30, 2011 at 7:05 pm

    Gary, sure thing. Try out the example code at http://jsfiddle.net/ForestMist/jSJgV/ and let me know if you have any questions.

  • beatbutcher says:
    January 1, 2012 at 6:17 pm

    No audio playing on safari 5.1.2, why I don’t know. When I make version go’s but with a gap.
    Opera works smoooot all 3 methods.

  • Nadeem says:
    May 2, 2012 at 6:29 am

    Hi
    your page is working in IE. But when I create a sample code and try to run in IE that is not working. I am simply using the following code. Please help how it can work in IE.

  • Daniel says:
    May 2, 2012 at 6:42 am

    Nadeem, which version of IE are you testing with? Can you post a link to your test page? I’d be happy to take a look at it.

  • Simon says:
    May 31, 2012 at 2:55 pm

    Nice post, thanx Daniel =)

  • Szekeres Geza says:
    June 13, 2012 at 6:44 am

    Hi Daniel,

    Nice post! I tweeked around and made a timeout based version of your 2 player idea here:

    http://onoffline.hu/html5loop/

    Check it out plz, thanx.
    Geza

  • Codeless says:
    June 21, 2012 at 3:45 am

    Thanks for your tweaks, Geza! The demo works fine in FF 13!

  • Scott says:
    August 5, 2012 at 4:04 pm

    Does nobody find it incredibly ironic and frustrating that the age-old bgsound tag, while only an IE thing, works PERFECTLY for seamlessly looped audio. And our so called advancements in html and in browsers do nothing but make things that were easy 10 years ago, harder, and LESS perfect? It never ceases to amaze me how much new things get hyped even when they are clearly not improvements at all.

  • Matt says:
    August 10, 2012 at 11:08 am

    Cracking post. I like options!

    Method 2 doesn’t work in Chrome on a Mac though

  • mike says:
    August 17, 2012 at 3:50 am

    hey,

    just use flash and all your problems are gone!

  • Daniel says:
    August 17, 2012 at 4:10 am

    Choosing HTML5 audio instead of Flash means gaining access to mobile and tablet users. Totally worth any hassles to access iOS devices alone.

    Flash has always had trouble with lower power devices and Adobe continues to relegate Flash to the desktop.

    This recent Android news is especially topical. http://www.theverge.com/2012/8/14/3241727/flash-for-android-dies

  • Hivenfour says:
    September 1, 2012 at 9:19 am

    Hi, interesting methods, I made it using intervals, works on recent versions of Chrome, Firefox and Opera. (tested wav only).

    https://github.com/Hivenfour/SeamlessLoop

  • Ram says:
    September 10, 2012 at 7:52 pm

    Very good example. The above specified sample program works fine when ever we try to play series of audio files and those are available. But, if any one of the audio file is missed in middle, but, the audio execution is not skipping to the next audio file, other than that, it is stopping in middle. Pls let me know how to handle such kind of situations…

  • Martin Kirchgessner says:
    September 18, 2012 at 5:29 pm

    Géza, Daniel : very interesting idea !

    On my FF13, only Géza’s method worked. I added a workaround for the first playblack delay : https://github.com/martinkirch/kontroller/blob/d9579c95a329250425afc8cbd80d9ebc06e47ed8/_attachments/loop_player.js

  • Leave a Reply

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

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comments are moderated for spam. If you are a human, don't worry and check back later.