Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing HTML5 Audio Object in Mobile Safari

I want to play a short (less than 1s) audio file in response to user input on my web app running in Mobile Safari on the iPad with minimum latency between event and audio playback. The playback can be triggered multiple times between page reloads, therefore I want to cache the audio file.

The following plays the file on the first click but after than nothing happens:

var audio = new Audio("ack.mp3");
$("#button").click(function(e) {
  e.preventDefault();
  audio.play();
}

If I add an event listener to the "ended" event which reloads the file I can get two playbacks from the same object and then silence:

var audio = new Audio("ack.mp3");
audio.addEventListener('ended', function() {
  audio.load();
}, false);
$("#button").click(function(e) {
  e.preventDefault();
  audio.play();
}

If I manually set the currentTime attribute to 0 like this:

var audio = new Audio("ack.mp3");
audio.addEventListener('ended', function() {
  audio.currentTime=0;
}, false);
$("#button").click(function(e) {
  e.preventDefault();
  audio.play();
}

I get the following error in the error console:

INDEX_SIZE_ERR: DOM Exception 1: Index or size was negative, or greater than the allowed value.

Any ideas on how to make this work? Thanks in advance

like image 756
derfred Avatar asked Jan 25 '11 22:01

derfred


2 Answers

set currentTime to 0.1 instead of zero, don't use load() otherwise it will break the ended event.

if you need to preload the media file use:

media.play(); //start loading
if(media.readyState !== 4){ //HAVE_ENOUGH_DATA
  media.addEventListener('canplaythrough', onCanPlay, false);
  media.addEventListener('load', onCanPlay, false); //add load event as well to avoid errors, sometimes 'canplaythrough' won't dispatch.
  setTimeout(function(){
    media.pause(); //block play so it buffers before playing
  }, 1); //it needs to be after a delay, otherwise it will block download and/or won't pause.
}else{
  onCanPlay();
}
like image 90
Miller Medeiros Avatar answered Sep 27 '22 17:09

Miller Medeiros


i had exactly the same problem. it's a dirty trick, but resetting the src on the sound object worked for me:

audio.src = audio.src;
audio.play();
like image 40
clamp Avatar answered Sep 27 '22 17:09

clamp