Unmute Web Audio Playback on iOS When Ringer is Muted
Published: 2024-02-13
iOS has odd behavior when you try to play audio using the Web Audio API with the ringer switch off (set to mute/on vibrate): for some reason, there will be no audible playback. But if you try to play a regular but of audio using the audio element it works. If you play both at the same time, you will hear both audio sources. So one way we can fix this is to play a blank bit of sound which will unblock playback. Below is a code snippet as example:
import { start } from "tone";
let hasUnblocked = false;
export function unblockPlayback() {
if (hasUnblocked) return;
hasUnblocked = true;
// unblock playback when iOS is set to silent
const audio = document.createElement("audio");
audio.setAttribute("x-webkit-airplay", "deny");
audio.preload = "auto";
audio.loop = true;
audio.src = emptyMp3FileSrc;
audio.play();
// have Tone.js unblock playback on interaction
start();
}
You’ll have to update emptyMp3FileSrc
to point to a blank audio file (it can be really short) and invoke the function on a user action like clicking a button for this to work. On Audapt we use Tone.js which also provides a start function that should be invoked on user action. You might not need it and can remove it.
You’ll also notice the x-webkit-airplay
attribute being set. This is to avoid the empty audio from showing up in AirPlay. As far as I know there is no way to hide the control center/lockscreen playback controls.
Hopefully this snippet helps in case you run into similar issues.