Web Audio API 最佳实践
在编写创意代码时,并没有严格的对错之分。只要你考虑安全、性能和可访问性,就可以适应自己的风格。在本文中,我们将分享一些最佳实践——使用 Web Audio API 的指南、提示和技巧。
加载声音/文件
有四种主要方法可以使用 Web Audio API 加载声音,而且选择哪一种可能会有点令人困惑。
在处理文件时,你要么从HTMLMediaElement
(即<audio>
或<video>
元素)获取文件,要么获取文件并将其解码成缓冲区。这两种方法都是合法的,但是,当你处理完整长度的音轨时,使用前者更为常见,而当你处理较短、更类似样本的音轨时,使用后者更为常见。
媒体元素开箱即用地支持流式传输。当浏览器确定在播放结束前可以加载其余文件时,音频将开始播放。你可以在使用 Web Audio API 教程中看到如何使用 Web Audio API 的示例。
但是,如果你使用缓冲区节点,你将拥有更多控制权。你必须请求文件并等待其加载(我们高级文章的这一部分展示了一种很好的方法),然后你可以直接访问数据,这意味着更高的精度和更精确的操作。
如果你希望处理来自用户摄像头或麦克风的音频,可以通过媒体捕获和流 API和MediaStreamAudioSourceNode
接口访问它。这对于 WebRTC 和你可能想要录制或分析音频的情况非常有用。
最后一种方法是自己生成声音,这可以通过OscillatorNode
或创建缓冲区并用自己的数据填充它来实现。查看此处创建自己的乐器的教程,以获取有关使用振荡器和缓冲区创建声音的信息。
跨浏览器和旧版浏览器支持
Web Audio API 规范不断发展,就像 Web 上的大多数事物一样,它在不同浏览器之间一致工作方面也存在一些问题。在这里,我们将探讨解决跨浏览器问题的选项。
有一个standardized-audio-context
npm 包,它可以在不同浏览器之间一致地创建 API 功能,并在发现问题时进行填补。它处于持续开发中,并努力跟上当前规范。
还可以选择库,根据你的用例,有几个库可供选择。对于一个通用的库,howler.js是一个不错的选择。它支持跨浏览器,并提供了一组有用的功能。虽然它没有利用 Web Audio API 附带的全部滤波器和其他效果,但你可以完成大多数想要完成的操作。
如果你正在寻找声音创建或更多基于乐器的选项,tone.js是一个很棒的库。它提供了高级调度功能、合成器和效果,以及构建在 Web Audio API 之上的直观的音乐抽象。
R-audio,来自BBC 的研究与开发部门,是一个 React 组件库,旨在提供“更直观、声明式的 Web Audio 接口”。如果你习惯于编写 JSX,那么可能值得一看。
自动播放策略
浏览器已开始实施自动播放策略,总的来说,可以将其概括为
“在用户手势内创建或恢复上下文”。
但在实践中这意味着什么?用户手势被解释为用户发起的事件,通常是click
事件。浏览器供应商决定 Web Audio 上下文不应该被允许自动播放音频;而应该由用户启动。这是因为自动播放音频可能非常烦人和令人反感。但是我们如何处理这个问题呢?
当你创建音频上下文(脱机或联机)时,它会使用state
创建,该state
可以是suspended
、running
或closed
。
在使用AudioContext
时,如果你从click
事件内部创建音频上下文,则状态应自动设置为running
。以下是在click
事件内部创建上下文的简单示例
const button = document.querySelector("button");
button.addEventListener(
"click",
() => {
const audioCtx = new AudioContext();
// Do something with the audio context
},
false,
);
但是,如果你在用户手势之外创建上下文,则其状态将设置为suspended
,并且需要在用户交互后启动。我们可以在此处使用相同的 click 事件示例,测试上下文的 state 并使用resume()
方法启动它(如果它已暂停)。
const audioCtx = new AudioContext();
const button = document.querySelector("button");
button.addEventListener(
"click",
() => {
// check if context is in suspended state (autoplay policy)
if (audioCtx.state === "suspended") {
audioCtx.resume();
}
},
false,
);
你可能正在使用OfflineAudioContext
,在这种情况下,你可以使用startRendering()
方法恢复已暂停的音频上下文。
用户控制
如果你的网站或应用程序包含声音,你应该允许用户控制它,否则,它会再次变得烦人。这可以通过播放/停止和音量/静音控件来实现。使用 Web Audio API教程介绍了如何做到这一点。
如果你的按钮用于切换音频的打开和关闭,则在这些按钮上使用 ARIA role="switch"
属性是向辅助技术发出信号以了解按钮的确切用途,从而使应用程序更易于访问的不错选择。此处有一个如何使用它的演示。
在使用 Web Audio API 时,你会处理很多变化的值,并且希望为用户提供对这些值的控制,因此<input type="range">
通常是使用的不错控件选择。这是一个不错的选择,因为你可以设置最小值和最大值,以及使用step
属性进行增量。
设置 AudioParam 值
有两种方法可以操作AudioNode
值,这些值本身是AudioParam
接口类型的对象。第一种方法是通过属性直接设置值。例如,如果我们想更改GainNode
的gain
值,我们将这样做
gainNode.gain.value = 0.5;
这会将我们的音量设置为一半。但是,如果你使用任何AudioParam
的定义方法来设置这些值,它们将优先于上述属性设置。例如,如果你希望gain
值在 2 秒内升至 1,你可以这样做
gainNode.gain.setValueAtTime(1, audioCtx.currentTime + 2);
它将覆盖前面的示例(应该如此),即使它出现在代码的后面。
请记住这一点,如果你的网站或应用程序需要计时和调度,最好坚持使用AudioParam
方法来设置值。如果你确定不需要,则可以使用value
属性设置它。