AudioWorkletProcessor 是 Web Audio API 中运行于独立音频线程、用于实时处理 PCM 音频数据的核心机制。需通过独立模块注册子类,process() 方法每块调用一次处理输入输出通道的 Float32Array;主线程通过 addModule 加载并创建 AudioWorkletNode,用 port.postMessage 实现异步参数通信;须避免内存分配、确保值域[-1,1]、适配固定采样率与多通道对齐。

AudioWorkletProcessor 是 Web Audio API 中处理底层 PCM 音频数据的核心机制,它运行在独立的音频渲染线程中,能以极低延迟访问每一块输入/输出音频帧(通常为 128 或 256 个样本),适合做实时音频分析、合成、效果器等。要真正用好它,关键在于理解其生命周期、数据结构、通信方式和限制。
1. 创建并注册 AudioWorkletProcessor 子类
AudioWorkletProcessor 必须定义为一个独立的 JavaScript 模块(不能是内联脚本),并在主线程通过 audioContext.audioWorklet.addModule() 加载注册。
在处理器文件(例如 my-processor.js)中:
class MyProcessor extends AudioWorkletProcessor {
constructor() {
super();
// 可选:初始化状态,如缓冲区、计数器
this.sampleCount = 0;
}
<p>// 每次音频块被调度时调用(无参数,不返回值)
process(inputs, outputs, parameters) {
const input = inputs[0]; // 输入通道数组:inputs[0][channelIndex]
const output = outputs[0]; // 输出通道数组:outputs[0][channelIndex]</p><pre class="brush:php;toolbar:false;">if (input.length === 0) return;
const channelCount = input.length;
const blockSize = input[0].length; // 当前块样本数(如 128)
for (let channel = 0; channel <p>}
}</p><p>// 必须显式注册,名称需与后续 AudioWorkletNode 构造一致
registerProcessor('my-processor', MyProcessor);
</p>注意:process() 是唯一可访问原始 PCM 的入口;不能使用 console.log、setTimeout、DOM API 或任何主线程对象;所有变量必须在构造函数或 process 内部管理。
2. 在主线程加载模块并创建 AudioWorkletNode
确保 HTML 中已启用模块支持,并在 AudioContext 创建后加载处理器:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
<p>// 加载处理器模块(路径需同源或配置 CORS)
await audioContext.audioWorklet.addModule('my-processor.js');</p><p>// 创建节点,传入注册名和可选选项
const workletNode = new AudioWorkletNode(audioContext, 'my-processor', {
processorOptions: { sampleRate: audioContext.sampleRate } // 可传递初始化参数
});</p><p>// 连接到图(例如接扬声器)
workletNode.connect(audioContext.destination);</p><p>// 可选:连接上游音频源
const oscillator = audioContext.createOscillator();
oscillator.connect(workletNode);
oscillator.start();
</p>⚠️ 常见错误:模块未加载完成就创建节点 → 报错 “InvalidStateError”;模块路径 404 或跨域 → 静默失败或 Network Error。
3. 与主线程通信:使用 port.postMessage()
AudioWorkletProcessor 无法直接读写主线程变量,必须通过 port 双向通信:
- 在处理器中监听:
this.port.onmessage = (e) => { console.log(e.data); }; - 在处理器中发送:
this.port.postMessage({ type: 'status', count: this.sampleCount }); - 在主线程中监听:
workletNode.port.onmessage = (e) => { /* 处理 UI 更新等 */ }; - 在主线程中发送:
workletNode.port.postMessage({ command: 'setGain', value: 0.8 });
通信是异步且非实时的,仅适合控制参数(如增益、开关)、反馈状态(如峰值检测结果),**不能用于传输音频帧数据**(带宽和延迟不允许)。
4. 注意事项与性能要点
-
采样率固定:AudioWorkletProcessor 运行在音频硬件采样率下(如 44.1kHz),不可更改;
sampleRate由AudioContext决定,processorOptions仅用于传参,不改变采样行为 - 无浮点异常保护:若输出值超出 [-1.0, 1.0],会硬 clipping(削波),需自行限幅或归一化
-
无输入即静音:若
inputs[0]为空(如节点未连接上游),应跳过处理,否则可能读取 undefined 导致 NaN 扩散 -
避免分配内存:不要在
process()中创建新数组、对象或调用new;复用已有缓冲区或使用Float32Array.prototype.set() -
多通道对齐:
inputs[0][0]和outputs[0][0]是同一时刻的左/右/中等通道样本,时间严格同步
不复杂但容易忽略:一次 process() 调用对应一个“音频块”,不是一帧一个样本,也不是一秒钟一次——它是音频引擎调度的基本单位,稳定、确定、无丢帧。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










