I have a web app that plays audio samples successfully on all platforms except iOS.
Here's my minimal reproducible example, with additional context below.
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
async function loadAudioSample(url) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
return audioBuffer;
}
function playSample(audioBuffer) {
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start(0);
}
// make sure user interacts with document first
document.addEventListener('click', async () => {
let buf = await loadAudioSample('./sample.mp3');
if (audioContext.state === 'suspended') {audioContext.resume();}
// logging es up normal
console.log(audioContext.state, buf);
playSample(buf);
});
Additional notes:
- If I play
sample.mp3
from an audio element vianew Audio()
using.play()
it does work, so I don't think the file format is an issue. (But I need the Web Audio API for higher precision and synchronizability). - The audio file is hosted on my own domain, so it's not CORS
- Testing on iOS 16 devices, iPhone and iPad
- Edit: in case it was the encoding, I've also tried a 16 bit
.wav
file encoded at44.1kHz
and48kHz
. - Edit 2: I suspect the problem has to do with user interaction requirements on iOS not allowing the audio context to be initialized, because
audioContext.state
logs "running" right away on mac, but "suspended" for the first couple of presses on iOS -- but I'm having trouble pinning it down. Even when "running" on iOS, no sound.
What am I doing wrong?
I have a web app that plays audio samples successfully on all platforms except iOS.
Here's my minimal reproducible example, with additional context below.
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioContext = new AudioContext();
async function loadAudioSample(url) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
return audioBuffer;
}
function playSample(audioBuffer) {
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start(0);
}
// make sure user interacts with document first
document.addEventListener('click', async () => {
let buf = await loadAudioSample('./sample.mp3');
if (audioContext.state === 'suspended') {audioContext.resume();}
// logging es up normal
console.log(audioContext.state, buf);
playSample(buf);
});
Additional notes:
- If I play
sample.mp3
from an audio element vianew Audio()
using.play()
it does work, so I don't think the file format is an issue. (But I need the Web Audio API for higher precision and synchronizability). - The audio file is hosted on my own domain, so it's not CORS
- Testing on iOS 16 devices, iPhone and iPad
- Edit: in case it was the encoding, I've also tried a 16 bit
.wav
file encoded at44.1kHz
and48kHz
. - Edit 2: I suspect the problem has to do with user interaction requirements on iOS not allowing the audio context to be initialized, because
audioContext.state
logs "running" right away on mac, but "suspended" for the first couple of presses on iOS -- but I'm having trouble pinning it down. Even when "running" on iOS, no sound.
What am I doing wrong?
Share Improve this question edited May 20, 2023 at 22:07 ultraGentle asked May 19, 2023 at 17:47 ultraGentleultraGentle 6,3672 gold badges26 silver badges58 bronze badges2 Answers
Reset to default 7I can't believe I'm writing this, but the mute/silent switch was on. I checked the volume a million times, but it's apparently separate from the switch.
On the other hand, there are things I still don't understand: other websites like YouTube played audio during my testing; how? Maybe because those are HTML5 new Audio()
.play()
elements, instead of using the Web Audio API?
On iOS the webAudio (as opposed to media audio) is connected to the ringer settings. See: https://bugs.webkit/show_bug.cgi?id=237322