Play audio on demand in Safari on iOS

Play audio on demand in Safari on iOS
Photo by KAL VISUALS / Unsplash

SoundWheel started as a mobile first web app. As such it was essential that audio playback worked in the background. Also, of equal importance was to be able to play another audio track when the first one finishes. On iOS this has been no easy task but I got it done regardless. I will try to explain the series of quirks I used to accomplish this.

Play audio on user interaction

One annoying limitation of audio playback is that you cannot play audio whenever you want. It has to be as a result of a user interaction. This is however easy to get past. All you need is to find a good spot in your web app to "play" audio. By this I mean something along these lines:


const myGlobalAudio = new Audio();
myGlobalAudio.src = "";
button.addEventListener('click', () => {
  myGlobalAudio.play();
});

This will play no audio but it will whitelist this particular Audio element so it can play audio over and over. All you have to do is to keep the same instance while changing the src attribute when you need to play something else.

Always be playing

When audio playback ends, you may wish to play another sound, so you set src on your Audio and call play() but it doesn't work in the background. As soon as audio playback ends, the page is denied from playing anything onward.

As I said, when audio playback ends. So all you have to do is have two Audio elements. One that starts playing just before the main one ends. in SoundWheel, I use an empty sound and set the loop = true on it. As the main one starts playing the next track, I stop the fake one.

That's the secret to SoundWheel's background audio playback. Don't forget to play the overlap audio on user interaction too.

There is one downside though. Sometimes in Control Panel you will see the fake audio element progress instead of the real audio and sometimes it will prevent you from scrubbing. But if not for these hacks, background playback wouldn't be possible.