一个旨在严格遵循标准的跨浏览器 Web Audio API 包装器。
这个包提供了 Web Audio API 的一个子集(尽管几乎是完整的),可以在每个支持的浏览器中以可靠和一致的方式工作。与其他流行的 polyfill 不同,standardized-audio-context 不会在全局作用域上修补或修改任何内容。换句话说,它不会造成任何副作用。因此,它可以在库中安全使用。这就是所谓的 ponyfill。
standardized-audio-context 的目标之一是只实现缺失的功能,并尽可能避免重写内置功能。请查看下面关于浏览器支持的段落以获取更多信息。
有些功能无法以使其像原生实现那样高效的方式模拟。其中最突出的是 AudioWorklet。请查看下面的所有支持方法列表以获取更详细的信息。
standardized-audio-context 可在 npm 上获得,可以按常规方式安装。
npm install standardized-audio-context
然后你可以这样导入 AudioContext 和 OfflineAudioContext:
import { AudioContext, OfflineAudioContext } from 'standardized-audio-context';
也可以使用 jspm 等服务加载 standardized-audio-context。此时上面的导入语句需要改为指向一个 URL。
import { AudioContext, OfflineAudioContext } from 'https://jspm.dev/standardized-audio-context';
一旦导入了 AudioContext 和/或 OfflineAudioContext,就可以像使用它们的原生对应物一样使用它们。例如,以下代码片段将产生一个干净(且烦人)的正弦波。
import { AudioContext } from 'standardized-audio-context'; const audioContext = new AudioContext(); const oscillatorNode = audioContext.createOscillator(); oscillatorNode.connect(audioContext.destination); oscillatorNode.start();
另一种方法是使用 AudioNode 构造函数(在本例中是 OscillatorNode 构造函数)而不是工厂方法。
import { AudioContext, OscillatorNode } from 'standardized-audio-context'; const audioContext = new AudioContext(); const oscillatorNode = new OscillatorNode(audioContext); oscillatorNode.connect(audioContext.destination); oscillatorNode.start();
这是 AudioContext 接口的几乎完整的实现。它只缺少 createScriptProcessor() 方法,而这个方法已经被废弃了。
⚠️ <!-- Bug #150 --> Safari 目前不支持设置 sampleRate。
⚠️ <!-- Bug #131 --> Safari 一次只允许运行 4 个 AudioContext。创建第五个 AudioContext 将抛出 UnknownError。
AudioContext 实现了以下 TypeScript 接口。
interface IAudioContext extends EventTarget { readonly audioWorklet?: IAudioWorklet; readonly baseLatency: number; readonly currentTime: number; readonly destination: IAudioDestinationNode<IAudioContext>; readonly listener: IAudioListener; onstatechange: null | TEventHandler<IAudioContext>; readonly sampleRate: number; readonly state: TAudioContextState; close(): Promise<void>; createAnalyser(): IAnalyserNode<IAudioContext>; createBiquadFilter(): IBiquadFilterNode<IAudioContext>; createBuffer(numberOfChannels: number, length: number, sampleRate: number): IAudioBuffer; createBufferSource(): IAudioBufferSourceNode<IAudioContext>; createChannelMerger(numberOfInputs?: number): IAudioNode<IAudioContext>; createChannelSplitter(numberOfOutputs?: number): IAudioNode<IAudioContext>; createConstantSource(): IConstantSourceNode<IAudioContext>; createConvolver(): IConvolverNode<IAudioContext>; createDelay(maxDelayTime?: number): IDelayNode<IAudioContext>; createDynamicsCompressor(): IDynamicsCompressorNode<IAudioContext>; createGain(): IGainNode<IAudioContext>; createIIRFilter(feedforward: number[], feedback: number[]): IIIRFilterNode<IAudioContext>; createMediaElementSource(mediaElement: HTMLMediaElement): IMediaElementAudioSourceNode<IAudioContext>; createMediaStreamDestination(): IMediaElementAudioDestinationNode<IAudioContext>; createMediaStreamSource(mediaStream: MediaStream): IMediaStreamAudioSourceNode<IAudioContext>; createMediaStreamTrackSource(mediaStreamTrack: MediaStreamTrack): IMediaStreamTrackAudioSourceNode<IAudioContext>; createOscillator(): IOscillatorNode<IAudioContext>; createPanner(): IPannerNode<IAudioContext>; createPeriodicWave(real: number[], imag: number[], constraints?: Partial<IPeriodicWaveConstraints>): IPeriodicWave; createStereoPanner(): IStereoPannerNode<IAudioContext>; createWaveShaper(): IWaveShaperNode<IAudioContext>; decodeAudioData( audioData: ArrayBuffer, successCallback?: TDecodeSuccessCallback, errorCallback?: TDecodeErrorCallback ): Promise<IAudioBuffer>; resume(): Promise<void>; suspend(): Promise<void>; }
下面将更详细地描述这些属性和方法。
这是 OfflineAudioContext 接口的几乎完整的实现。它只缺少 createScriptProcessor() 方法,而这个方法已经被废弃了。
⚠️ <!-- Bug #141 & #142 --> Safari 不支持创建超过 10 个通道或采样率低于 44100 Hz 的 OfflineAudioContext。
它实现了以下 TypeScript 接口。
interface IOfflineAudioContext extends EventTarget { readonly audioWorklet?: IAudioWorklet; readonly baseLatency: number; readonly currentTime: number; readonly destination: IAudioDestinationNode<IOfflineAudioContext>; readonly length: number; readonly listener: IAudioListener; onstatechange: null | TEventHandler<IOfflineAudioContext>; readonly sampleRate: number; readonly state: TAudioContextState; createAnalyser(): IAnalyserNode<IOfflineAudioContext>; createBiquadFilter(): IBiquadFilterNode<IOfflineAudioContext>; createBuffer(numberOfChannels: number, length: number, sampleRate: number): IAudioBuffer; createBufferSource(): IAudioBufferSourceNode<IOfflineAudioContext>; createChannelMerger(numberOfInputs?: number): IAudioNode<IOfflineAudioContext>; createChannelSplitter(numberOfOutputs?: number): IAudioNode<IOfflineAudioContext>; createConstantSource(): IConstantSourceNode<IOfflineAudioContext>; createConvolver(): IConvolverNode<IOfflineAudioContext>; createDelay(maxDelayTime?: number): IDelayNode<IOfflineAudioContext>; createDynamicsCompressor(): IDynamicsCompressorNode<IOfflineAudioContext>; createGain(): IGainNode<IOfflineAudioContext>; createIIRFilter(feedforward: number[], feedback: number[]): IIIRFilterNode<IOfflineAudioContext>; createOscillator(): IOscillatorNode<IOfflineAudioContext>; createPanner(): IPannerNode<IOfflineAudioContext>; createPeriodicWave(real: number[], imag: number[], constraints?: Partial<IPeriodicWaveConstraints>): IPeriodicWave; createStereoPanner(): IStereoPannerNode<IOfflineAudioContext>; createWaveShaper(): IWaveShaperNode<IOfflineAudioContext>; decodeAudioData( audioData: ArrayBuffer, successCallback?: TDecodeSuccessCallback, errorCallback?: TDecodeErrorCallback ): Promise<IAudioBuffer>; startRendering(): Promise<IAudioBuffer>; }
下面将更详细地描述这些属性和方法。
⚠️ <!-- Bug #59 --> AudioWorklet 可作为 AudioContext 或 OfflineAudioContext 的一个属性访问。它在 Safari 中内部使用 ScriptProcessorNode 来创建 AudioWorkletProcessor。这意味着它只会在 Chrome、Edge 和 Firefox 中提供你通常期望从使用 AudioWorklet 中获得的性能改进。
⚠️ <!-- Bug #59 --> 内部实现依赖于 ScriptProcessorNode 这一事实也意味着 channelCountMode 目前只能是 'explicit'。这也意味着所有输入的总通道数加上所有参数的数量不能超过六个。
⚠️ <!-- Bug #59 --> 另一点需要注意的是,fallback 将在全局作用域上评估 AudioWorkletProcessor。它以基本的方式被隔离以模仿 AudioWorkletGlobalScope,但这无法以使攻击者无法突破该沙箱的方式来完成。除非你从不受信任的来源加载 AudioWorklet,否则这应该不是问题。
⚠️ <!-- Bug #117 --> Firefox 和 Safari 14.0.1 及之前的版本不支持通过 AudioParams 修改监听器。因此,在 OfflineAudioContext 的监听器的 AudioParams 上调用任何调度函数都会抛出 NotSupportedError。
这是 createAnalyser() 工厂方法的实现。AnalyserNode 构造函数可以作为替代方案使用。
这是 createBiquadFilter() 工厂方法的实现。BiquadFilterNode 构造函数可以作为替代方案使用。
这是 createBuffer() 工厂方法的实现。也可以使用 AudioBuffer 构造函数作为替代。
⚠️ Safari 不支持采样率低于 22050 Hz 的 AudioBuffer。
这是 createBufferSource() 工厂方法的实现。也可以使用 AudioBufferSourceNode 构造函数作为替代。
⚠️ 目前尚未实现 detune AudioParam。
⚠️ Safari 14.0.1 及之前版本不支持将信号连接到 playbackRate AudioParam。因此,在这些版本的 Safari 中,尝试连接任何其他 AudioNode 到它将抛出 NotSupportedError。
这是 createChannelMerger() 工厂方法的实现。也可以使用 ChannelMergerNode 构造函数作为替代。
这是 createChannelSplitter() 工厂方法的实现。也可以使用 ChannelSplitterNode 构造函数作为替代。
这是 createConstantSource() 工厂方法的实现。也可以使用 ConstantSourceNode 构造函数作为替代。
这是 createConvolver() 工厂方法的实现。也可以使用 ConvolverNode 构造函数作为替代。
这是 createDelay() 工厂方法的实现。也可以使用 DelayNode 构造函数作为替代。
⚠️ 除 Firefox 外的所有浏览器中,delayTime AudioParam 无法设置为非常小的值。
这是 createDynamicsCompressor() 工厂方法的实现。也可以使用 DynamicsCompressorNode 构造函数作为替代。
这是 createGain() 工厂方法的实现。也可以使用 GainNode 构造函数作为替代。
这是 createIIRFilter() 工厂方法的实现。也可以使用 IIRFilterNode 构造函数作为替代。
⚠️ 在 Safari 中,它必须在内部使用 ScriptProcessorNode 模拟,这意味着它的性能不如其他原生支持的浏览器。
这是 createMediaElementSource() 工厂方法的实现。也可以使用 MediaElementAudioSourceNode 构造函数作为替代。
它只适用于 AudioContext,不适用于 OfflineAudioContext。
这是 createMediaStreamDestination() 工厂方法的实现。也可以使用 MediaStreamAudioDestinationNode 构造函数作为替代。
它只适用于 AudioContext,不适用于 OfflineAudioContext。
这是 createMediaStreamSource() 工厂方法的实现。也可以使用 MediaStreamAudioSourceNode 构造函数作为替代。
它只适用于 AudioContext,不适用于 OfflineAudioContext。
⚠️ 如果 MediaStreamAudioSourceNode 断开连接约两秒钟,Safari 会输出静音。
这是 createMediaStreamTrackSource() 工厂方法的实现。也可以使用 MediaStreamTrackAudioSourceNode 构造函数作为替代。
它只适用于 AudioContext,不适用于 OfflineAudioContext。
这是 createOscillator() 工厂方法的实现。也可以使用 OscillatorNode 构造函数作为替代。
这是 createPanner() 工厂方法的实现。也可以使用 PannerNode 构造函数作为替代。
这是 createPeriodicWave() 工厂方法的实 现。也可以使用 PeriodicWave 构造函数作为替代。
这是 createStereoPanner() 工厂方法的实现。也可以使用 StereoPannerNode 构造函数作为替代。
除非 Safari 提供原生实现,否则 channelCountMode 只能是 'explicit'。
这是 createWaveShaper() 工厂方法的实现。也可以使用 WaveShaperNode 构造函数作为替代。
这是 decodeAudioData() 方法的实现。下面还描述了一个具有类似接口的独立方法。
这是一个独立的包装器,可以以类似于同名实例方法的方式使用。最显著的区别是它需要一个使用此库创建的 (Offline)AudioContext 作为第一个参数。但它也可以处理原生的 (webkit)(Offline)AudioContext。另一个区别是它只返回一个 promise。它不会调用任何回调。
import { decodeAudioData } from 'standardized-audio-context'; // 假设你在 Safari 中运行这段代码 const nativeAudioContext = new webkitAudioContextContext(); const response = await fetch('/a-super-cool-audio-file'); const arrayBuffer = await response.arrayBuffer(); const audioBuffer = await decodeAudioData(nativeAudioContext, arrayBuffer);
这是一个实用函数,用于判断给定值是否为 AudioContext。它不区分由 standardized-audio-context 创建的 AudioContext 还是原生的 AudioContext。但对于 OfflineAudioContext,它将返回 false。
import { AudioContext, isAnyAudioContext } from 'standardized-audio-context'; // 这将创建一个来自 standardized-audio-context 的 AudioContext const audioContext = new AudioContext(); isAnyAudioContext(audioContext); // true // 这将创建一个原生的 AudioContext const nativeAudioContext = new window.AudioContext(); isAnyAudioContext(nativeAudioContext); // true
这是一个辅助函数,允许在不进行自定义 instanceof 或属性检查的情况下识别 AudioNode。如果给定值是 AudioNode,则返回 true,否则返回 false。无论给定值是否是使用 standardized-audio-context 创建的 AudioNode 都无关紧要。
import { OfflineAudioContext, isAnyAudioNode } from 'standardized-audio-context'; // 这将创建一个原生的 AudioContext const nativeAudioContext = new AudioContext(); isAnyAudioNode(nativeAudioContext.createGain()); // true // 这将创建一个来自 standardized-audio-context 的 OfflineAudioContext const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 }); isAnyAudioNode(offlineAudioContext.createGain()); // true
这是一个类似于 isAnyAudioNode() 的辅助函数,但用于 AudioParam。如果给定值是 AudioParam,则返回 true,否则返回 false。无论给定值是否是使用 standardized-audio-context 创建的 AudioParam 都无关紧要。
import { OfflineAudioContext, isAnyAudioParam } from 'standardized-audio-context'; // 这将创建一个原生的 AudioContext const nativeAudioContext = new AudioContext(); isAnyAudioParam(nativeAudioContext.createGain().gain); // true
// 这将创建一个来自 standardized-audio-context 的 OfflineAudioContext。 const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 });
isAnyAudioParam(offlineAudioContext.createGain().gain); // true
### isAnyOfflineAudioContext()
这是一个实用函数,用于判断给定值是否为 OfflineAudioContext。它不区分由 `standardized-audio-context` 创建的 OfflineAudioContext 和原生的 OfflineAudioContext。
```js
import { OfflineAudioContext, isAnyOfflineAudioContext } from 'standardized-audio-context';
// 这将创建一个来自 standardized-audio-context 的 OfflineAudioContext。
const offlineAudioContext = new OfflineAudioContext({ length: 10, sampleRate: 44100 });
isAnyOfflineAudioContext(offlineAudioContext); // true
// 这将创建一个原生的 OfflineAudioContext。
const nativeOfflineAudioContext = new window.OfflineAudioContext(1, 10, 44100);
isAnyOfflineAudioContext(nativeOfflineAudioContext); // true
standardized-audio-context 还导出了一个可通过调用 isSupported() 访问的 Promise。这个 Promise 解析为一个布尔值,表示当前使用的浏览器是否支持该功能。这不是规范的一部分。
import { isSupported } from 'standardized-audio-context'; isSupported().then((isSupported) => { if (isSupported) { // 太好了,一切都应该能正常工作 } else { // 哦不,这个浏览器似乎已经过时了 } });
这个包的目标是提供一个一致的 API。但同时,这个包不应无限增长直到在 IE 6 中一切都能正常工作。当每个受支持的浏览器都实现了之前需要 polyfill 才能正常工作的功能时,该 polyfill 就会从这个包中移除。希望在未来某个时候,这个包可以简化为一个只重新导出内置对象的文件。
但在那之前,我们会非常小心地避免任何不必要的膨胀。这意味着每当为某个特定浏览器添加一个解决方案时,都会附带一个测试来检查是否仍然需要这个特定的解决方案。我称这些测试为期望测试,因为它们测试浏览器是否按预期行为。期望测试的设计目的是在浏览器最终修复问题时失败。一旦发生这种情况,解决方案和相应的期望测试就会被移除。然而, 期望测试会被重新利用,作为调用 isSupported() 时执行的浏览器检查的一部分。
当前支持的浏览器列表包括 Chrome v81+、Edge v81+、Firefox v70+ 和 Safari v12.1+。请注意,测试仅在每个浏览器的当前版本和即将发布的版本中运行。
支持一个浏览器仅意味着在功能层面上支持它。完全有可能需要像 Babel 这样的转译器来在每个受支持的浏览器中使用这个包而不会遇到任何语法错误。
这个包不适用于 Node.js。
这个包是用 TypeScript 编写的,这意味着它可以无缝地用于任何 TypeScript 项目。但这完全是可选的。
与 TypeScript 开箱即用提供的 Web Audio API 类型相比,standardized-audio-context 导出的类型实际上与具体实现相匹配。TypeScript 从 Web Audio API 的 Web IDL 定义生成其类型,而这并不总是与实际可用的实现相匹配。
所有实现的方法都由大量测试覆盖,这些测试在上述所有浏览器中运行。非常感谢 BrowserStack 和 Sauce Labs 允许使用他们的服务测试这个模块。
要报告安全漏洞,请使用 Tidelift 安全联系方式。Tidelift 将协调修复和披露。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频


实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。


选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


最强AI数据分析助手
小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。


像人一样思考的AI智能体
imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号