Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play (and replay) a sound on safari mobile

I need to play a sound when a new message appears on a website. It works fine on Chrome and Safari but I can't make it work on Safari mobile. I saw that the sound has to be initialised with a user action so I tried that:

var sound = new Audio('./path/to/my/sound.mp3');
var hasPlayed = false;

$('body').bind('click touchstart', function() {
  sound.load();
});    

sound.addEventListener('play', function() {
  hasPlayed = true;
});

var playSound = function() {
  if(hasPlayed) {
    sound.currentTime = 0;
  }
  sound.play();
}

Unfortunately, the sound still don't play. I also tried with the Buzz library, and the issue is the same.

So, the question is : how can I play a sound programmatically on mobile browsers ?

like image 744
TimPetricola Avatar asked Jun 08 '12 15:06

TimPetricola


1 Answers

First of all: HTML5 audio support in Mobile Safari on iOS (5.01, 5.1) is rather limited. But I have managed to get some small 'event type' sounds working in my iPad 2 web apps. Since you are talking about only one sound file for your app, you don't have to fall back on audio sprites tricks (i.e. merging multiple MP3's into one MP3 file and changing the play position within the merged file depending on the sound you want to be played).

As you have noticed, you cannot play audio automatically in Mobile Safari, i.e. without the user clicking on some element. Technically speaking, the audio must be played (not loaded) in the same call stack as a click event. But you will probably experience a 0,5 second delay then, when Mobile Safari creates the audio object. Here is a solution to this 'problem':

  • At the start of your app (while loading/initializing), add a click handler to the HTML document that starts playing your audio file as soon as the user clicks/taps anywhere in the app. This will force Safari to start loading the audio.
  • Listen for the 'play' event that is triggered when the audio is ready to be played, and immediately pause.
  • Now start playing the audio (without delay) again when you need it.

Here is some quick JavaScript code:

function initAudio() {
    var audio = new Audio('./path/to/my/sound.mp3');
    audio.addEventListener('play', function () {
        // When the audio is ready to play, immediately pause.
        audio.pause();
        audio.removeEventListener('play', arguments.callee, false);
    }, false);
    document.addEventListener('click', function () {
        // Start playing audio when the user clicks anywhere on the page,
        // to force Mobile Safari to load the audio.
        document.removeEventListener('click', arguments.callee, false);
        audio.play();
    }, false);
}
like image 181
Jeroen Avatar answered Sep 29 '22 00:09

Jeroen