Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper onload for <audio>

I've been looking around and I'm starting to worry that this isn't possible.
Is there any way to make a standard <audio> tag with fallbacks...

<audio>
    <source src='song.ogg' type='audio/ogg'></source>
    <source src='song.mp3' type='audio/mp3'></source>
</audio>

...have an onload event. I've looked around and all I could find are some hacks that may or may not work (they don't for me on Chrome) and the canplaythrough event.
The reason I want this is because I am making a presentation that has lots of audio clips to play at certain points. I don't want the presentation to start until all of the audio is loaded (otherwise things could get out of sync). I want the clips to be loaded 1 at a time so that I can create a sort of loading bar. I really don't want to resort to using Flash sound because this is supposed to demonstrate pure web technologies.

So basically I've got this one loadAudio function that cycles through the array of audio files to be loaded audioQueue. loadAudio is called once and then it calls itself until all the files are loaded. Problem is I haven't found the correct event to trigger loading the next file.

loadAudio = function(index)
{
mer = audioQueue[index];
var ob = "<audio id='" + mer + "'><source src='resources/sounds/" + mer + ".ogg' type='audio/ogg'></source><source src='resources/sounds/" + mer + ".mp3' type='audio/mp3'></source></audio>";
$("#audios").append(ob);
$("#" + mer).get(0).addEventListener('A WORKING EVENT RIGHT HERE WOULD BE NICE', function() { alert("loaded"); 
     if (index + 1 < audioQueue) { loadAudio(index + 1); } }, false);
}

So. Any chance for a proper audio onload? I'm basically willing to do anything as long as it's still all HTML and Javascript.

like image 849
Pinpickle Avatar asked Jan 17 '23 05:01

Pinpickle


1 Answers

You can use the loadeddata-MediaEvent. For example you can put all of your audio files in an Array and do something like:

var files = ['a.mp3', 'b.mp3'];

$.each(files, function() {
    $(new Audio())
        .on('loadeddata', function() {
            var i = files.indexOf(this);
            files.splice(i, 1);
            if (!files.length) {
                alert('Preloading done!');
            }
        })
        .attr('src', this);
});

EDIT: this would a little more modern approach as of 2016:

var files = ['a.mp3','b.mp3'];

Promise
    .all(files.map(function(file) {
        return new Promise(function(resolve) {
            var tmp = new Audio();
            tmp.src = file;
            tmp.addEventListener('loadeddata', resolve);
        });
    })).then(function() {
        alert('Preloading done!');
    });
like image 70
m90 Avatar answered Jan 20 '23 15:01

m90