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.

Try Audjust →
More blog entries →