我遇到了一个问题,当尝试在 Safari 中播放音频时,在
resume
上调用 AudioContext
永远无法解决。我在页面加载时创建一个 AudioContext
,因此它以暂停状态启动。
根据此 chromium 问题,如果浏览器的自动播放策略阻止,调用
resume
将无法解决。我有一个绑定到 <button>
的点击事件,如果上下文被挂起,它将恢复上下文。这适用于 Firefox 和 Chrome,也适用于 Safari 如果我更改了网站的自动播放设置。
以下是我通常如何恢复上下文:
await context.resume();
对于 Safari,我尝试在不等待承诺解决的情况下调用resume,而是为
onstatechange
注册回调,然后将其包装在 Promise
:
if (window.webkitAudioContext) {
await new Promise((accept, reject) => {
this.context.onstatechange = async () => {
if ((await this.context.state) === "playing") {
accept();
} else {
reject();
}
};
this.context.resume();
});
}
但是,什么都没有改变:
Promise
永远不会解析,这意味着上下文状态没有改变。
我错过了什么吗?
我终于成功在 Safari 上播放音频了。
“修复”相当简单:我必须在绑定到用于启动播放的元素的事件处理程序中调用
resume
。在我的场景中,我将 Redux 与 React 结合使用,因此将进行调度,并稍后在另一个组件中恢复上下文。我猜测 Safari 并没有将其视为对用户交互事件的直接响应,因此它将上下文保持在挂起状态。
iOS 仅允许在 UI 事件处理程序的调用堆栈中运行时恢复 audioContext。在 Promise 中运行它会将调用移动到另一个调用堆栈。
此外,
audioContext.resume()
返回一个必须等待的承诺。
试试这个:
onPlayHandler() {
alert("State before: " + this.audioContext.state);
await this.audioContext.resume();
alert("State after: " + this.audioContext.state);
}
我看到了类似但不完全相同的问题。当前我的 AudioContext 陷入“中断”状态,我无法使用 audioContext.resume() 恢复它。
有人知道如何在设置中断后恢复吗?