Safari AudioContext приостановлен даже при создании onclick

У меня возникают проблемы с созданием AudioContext в Safari (для настольных компьютеров и мобильных устройств). Кажется, что даже при создании при взаимодействии с пользователем он все еще приостановлен.

Мой код:

<button onclick="test()">Test</button>
const test = () => {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    audioContext = new AudioContext();
    console.log(audioContext.state); // Suspended
}

Это должен быть минимальный рабочий пример, верно? Что здесь не так?


person ffritz    schedule 26.06.2019    source источник


Ответы (1)


Я думаю, что Safari на самом деле ведет себя правильно (по крайней мере, частично) в этом случае. Спецификация веб-аудио говорит, что ...

Вновь созданный AudioContext всегда будет начинаться в приостановленном состоянии, и событие изменения состояния будет запускаться всякий раз, когда состояние изменяется на другое состояние.

https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-onstatechange

К сожалению, Safari не выполняет переход в состояние running самостоятельно. Вы должны явно попросить его сделать это.

audioContext.resume();
audioContext.onstatechange = () => console.log(audioContext.state);

Событие statechange должно сработать почти сразу. Если вы выполните это внутри обработчика кликов.

Приведенная выше функция будет выглядеть следующим образом:

const test = () => {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    audioContext = new AudioContext();
    console.log(audioContext.state); //suspended
    audioContext.resume();
    audioContext.onstatechange = () => console.log(audioContext.state); // running
}

Интересно, что Safari запускает событие statechange только в том случае, если вы сохраняете оператор console.log перед вызовом resume().

Однако есть еще один хак, который вы можете попробовать выкинуть из AudioContext. Просто создайте простой файл GainNode.

const test = () => {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    audioContext = new AudioContext();
    audioContext.createGain();
    console.log(audioContext.state); // running
}

Вы также можете попробовать standardized-audio-context, чтобы все браузеры вели себя одинаково в в этом отношении.

person chrisguttandin    schedule 26.06.2019
comment
Спасибо за ваш ответ. Что ж, похоже, это тоже не работает, событие изменения состояния вызывается только после двойного нажатия кнопки. Я попробовал вашу библиотеку и получил ошибку кодирования. Ну, думаю, я просто пропущу Сафари. - person ffritz; 26.06.2019
comment
Мне было любопытно, почему это не работает для вас, и кажется, что Safari нуждается в этом операторе журнала для запуска события statechange. Я обновил ответ выше, а также добавил еще один вариант. - person chrisguttandin; 26.06.2019
comment
Получение EncodingError при использовании стандартизированного аудиоконтекста с приведенным выше кодом звучит очень странно для меня. Такого точно не должно быть. Не возражаете ли вы зарегистрировать проблему на GitHub по этому поводу? - person chrisguttandin; 26.06.2019
comment
Я зарегистрирую проблему обязательно. Я ближе к тому, чтобы это заработало, я думаю, проблема, которую я считаю, заключается в audioContext.decodeAudioData(), которую, как мне кажется, сафари просто не выполняет. -- ОБНОВЛЕНИЕ: Это работает! Мой arrayBuffer был закодирован в Opus. Кто знал, что Safari его не поддерживает. - person ffritz; 26.06.2019
comment
Тогда EncodingError, вероятно, также был связан с тем, что мой аудиобуфер находился в Opus, и, таким образом, Safari выдавал EncodingError с вашей библиотекой. Предоставленное вами собственное решение работает на Safari Desktop, а не на iPhone. - person ffritz; 26.06.2019
comment
Да, в таком случае ожидается EncodingError. Safari не может декодировать файлы Opus, поэтому выдача ошибки является правильным поведением. Оба варианта не работают на iPhone (возобновление и создание GainNode)? - person chrisguttandin; 26.06.2019
comment
Давайте продолжим обсуждение в чате. - person ffritz; 26.06.2019