网络音频常见问题解答

Boris Smus

在过去几个月里,WebKit Web Audio API 已成为 Web 上游戏和音频应用的理想平台。随着开发者逐渐熟悉该工具,我发现类似的问题会反复出现。此快速更新旨在解答一些常见问题,让您在使用 Web Audio API 时获得更愉快的体验。

问题:求助,我无法发出声音!

答:如果您刚开始接触 Web Audio API,请参阅使用入门教程,或 Eric 的根据用户互动播放音频方法。

问:我应该有多少个音频上下文?

答:通常,您应在每个网页中添加一个 AudioContext,并且单个音频上下文可以支持连接到它的多个节点。虽然您可以在单个网页上添加多个 AudioContext,但这可能会导致性能下降。

问题:我有一个 AudioBufferSourceNode,刚刚用 noteOn() 播放了,现在想再次播放,但 noteOn() 什么也不做!我需要帮助!

答:源节点播放完毕后,便无法再播放。如需再次播放底层缓冲区,您应创建新的 AudioBufferSourceNode 并调用 noteOn()

虽然重新创建源节点可能效率不高,但源节点针对此模式进行了大量优化。此外,如果您保留了对 AudioBuffer 的句柄,则无需再次向资源发出请求即可再次播放相同的声音。如果您发现自己需要重复此模式,请使用 playSound(buffer)简单的辅助函数封装播放操作。

问:在播放音频时,为什么需要每次都创建新的源节点?

答:此架构的理念是将音频资产与播放状态分离。以唱片机为例,缓冲区类似于唱片,而来源类似于播放头。由于许多应用都涉及同一缓冲区多个版本同时播放的情况,因此这种模式至关重要。

问:如何处理 audiovideo 标记中的声音?

答:MediaElementAudioSourceNode 正在开发中!该功能推出后,大致会如下所示(向通过音频标记播放的选段添加滤镜效果):

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

此功能在此 crbug 中进行跟踪。请注意,在此设置中,无需调用 mediaSourceNode.noteOn(),音频标记会控制播放。

问:我何时可以通过麦克风听到声音?

答:音频输入部分将使用 getUserMedia 作为 WebRTC 的一部分实现,并作为 Web Audio API 中的特殊源节点提供。它将与 createMediaElementSource 搭配使用。

问:如何检查 AudioSourceNode 何时播放完毕?

答:由于 Web Audio API 不支持此功能,因此您目前必须使用 JavaScript 计时器。“Web Audio API 使用入门”教程中的以下代码段就是一个很好的示例:

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

有一个未解决的 bug,会导致 Web Audio API 实现更准确的回调。

问题:加载提示音会导致整个界面线程锁定,并且界面无响应。求助!**

答:使用 decodeAudioData API 进行异步加载,以避免阻塞主线程。请参阅此示例

问题:Web Audio API 能否用于比实时更快地处理声音?

答:是的,我们正在努力寻找解决方案。请继续关注我们的行动!

问题:我开发了一个很棒的 Web Audio API 应用,但每当其所运行的标签页进入后台时,声音都会变得奇怪!

答:这可能是因为您使用的是 setTimeouts,如果网页处于后台运行,其行为会有所不同。未来,Web Audio API 将能够使用 Web Audio 的内部计时器(context.currentTime 属性)在特定时间回调。如需了解详情,请参阅此功能请求

一般来说,最好在应用进入后台时停止播放。您可以使用 Page Visibility API 检测网页何时进入后台。

问题:如何使用 Web Audio API 更改音调?

答:更改源节点上的 playbackRate

问:我可以更改音调而不更改速度吗?

答:Web Audio API 可以在音频上下文中包含 PitchNode,但很难实现。这是因为音频社区中没有简单的音高移调算法。已知的技术会产生伪影,尤其是在音高移调幅度较大的情况下。有两种方法可以解决此问题:

  • 时域算法,会导致重复的片段回声伪影。
  • 频域技术,会导致混响音效伪影。

虽然没有用于执行这些技术的原生节点,但您可以使用 JavaScriptAudioNode 执行这些技术。您可以参考以下代码段入手。

问题:如何以我选择的采样率创建 AudioContext?

答:目前不支持这种做法,但我们正在研究中。请参阅此功能请求

如果您还有其他问题,欢迎随时在 StackOverflow 上使用 web-audio 标签提问。