为什么恢复后状态在 Safari 中的 Web Audio 中会无效?
Why state can be invalid in Web Audio in Safari after resume?
我有一个代码可以播放从 S3 下载的音频文件。在页面上,用户会看到带有他应该发音的图片和单词的轮播,并会听到正确发音的音频。问题出在 Safari 中,它会阻止在 window 加载时自动播放音频文件。我知道 Safari 默认情况下会阻止自动播放,并且在设置 自动播放:启用有声停止媒体 时。当我转到该页面时,Safari 阻止自动播放音频文件 并且页面停止加载并且 'freez' 和 AudioContext 状态为 'suspended' 如果要 在任何用户操作上调用 resume() 例如单击文档,状态更改为 'running'、 但是如果我单击下一张幻灯片,下一个函数将调用source.stop() 如果正在播放音频,则停止播放音频,源是 bufferSource(AudioContext.createBufferSource())并抛出错误 'InvalidStateError'
screenshot with error
为什么会出现这个错误?如果状态处于 'running' 而不是 'suspended'。在 coursel 中还有 3 个按钮可以再次播放音频、录制音频和播放录制的音频,然后恢复所有工作,但是当停止功能调用时显示错误。
如果您在使用 AudioBufferSourceNodes
时在 Safari 中看到 "InvalidStateError: The object is in an invalid state
(或在其他具有不同消息的浏览器中),这很可能是因为您调用了 stop()
或 start()
在播放完毕的节点上。
引用from MDN:
An AudioBufferSourceNode can only be played once; after each call to start(), you have to create a new node if you want to play the same sound again. Fortunately, these nodes are very inexpensive to create, and the actual AudioBuffers can be reused for multiple plays of the sound. Indeed, you can use these nodes in a "fire and forget" manner: create the node, call start() to begin playing the sound, and don't even bother to hold a reference to it. It will automatically be garbage-collected at an appropriate time, which won't be until sometime after the sound has finished playing.
Safari 会因多种原因抛出该错误,包括以下原因:
- 正在对尚未开始播放的项目调用
stop()
。这可能是你的问题。
- 告诉它在无效时间停止,例如
stop(0)
而不是 stop(ctx.currentTime)
。
我看到这个错误发生在另一个奇怪的案例中。我们有一个测试框架,通过一个接一个地快速加载来测试我们的网页。每个页面动态加载其资源(图像、声音等),并在所有资源加载完成后向框架报告。我们一次最多同时加载 10 个资源。对于音频文件,它不仅检索文件,而且创建和初始化音频对象,以便播放。其中一些页面包含相同的音频文件。
看起来,即使在导航到另一个页面后,缓存的音频文件也可能处于某种状态,如果另一个页面过早地初始化该音频文件,它就会抛出这个错误。因此,看起来不仅音频文件被浏览器缓存,而且对象或状态也以某种方式被缓存/重用,或者在释放前一个页面的实例时以某种方式锁定文件。
我有一个代码可以播放从 S3 下载的音频文件。在页面上,用户会看到带有他应该发音的图片和单词的轮播,并会听到正确发音的音频。问题出在 Safari 中,它会阻止在 window 加载时自动播放音频文件。我知道 Safari 默认情况下会阻止自动播放,并且在设置 自动播放:启用有声停止媒体 时。当我转到该页面时,Safari 阻止自动播放音频文件 并且页面停止加载并且 'freez' 和 AudioContext 状态为 'suspended' 如果要 在任何用户操作上调用 resume() 例如单击文档,状态更改为 'running'、 但是如果我单击下一张幻灯片,下一个函数将调用source.stop() 如果正在播放音频,则停止播放音频,源是 bufferSource(AudioContext.createBufferSource())并抛出错误 'InvalidStateError' screenshot with error
为什么会出现这个错误?如果状态处于 'running' 而不是 'suspended'。在 coursel 中还有 3 个按钮可以再次播放音频、录制音频和播放录制的音频,然后恢复所有工作,但是当停止功能调用时显示错误。
如果您在使用 AudioBufferSourceNodes
时在 Safari 中看到 "InvalidStateError: The object is in an invalid state
(或在其他具有不同消息的浏览器中),这很可能是因为您调用了 stop()
或 start()
在播放完毕的节点上。
引用from MDN:
An AudioBufferSourceNode can only be played once; after each call to start(), you have to create a new node if you want to play the same sound again. Fortunately, these nodes are very inexpensive to create, and the actual AudioBuffers can be reused for multiple plays of the sound. Indeed, you can use these nodes in a "fire and forget" manner: create the node, call start() to begin playing the sound, and don't even bother to hold a reference to it. It will automatically be garbage-collected at an appropriate time, which won't be until sometime after the sound has finished playing.
Safari 会因多种原因抛出该错误,包括以下原因:
- 正在对尚未开始播放的项目调用
stop()
。这可能是你的问题。 - 告诉它在无效时间停止,例如
stop(0)
而不是stop(ctx.currentTime)
。
我看到这个错误发生在另一个奇怪的案例中。我们有一个测试框架,通过一个接一个地快速加载来测试我们的网页。每个页面动态加载其资源(图像、声音等),并在所有资源加载完成后向框架报告。我们一次最多同时加载 10 个资源。对于音频文件,它不仅检索文件,而且创建和初始化音频对象,以便播放。其中一些页面包含相同的音频文件。
看起来,即使在导航到另一个页面后,缓存的音频文件也可能处于某种状态,如果另一个页面过早地初始化该音频文件,它就会抛出这个错误。因此,看起来不仅音频文件被浏览器缓存,而且对象或状态也以某种方式被缓存/重用,或者在释放前一个页面的实例时以某种方式锁定文件。