MediaRecorder 无法直接录制 WASM 音频,需通过 AudioWorklet 将 WASM 输出的 PCM 数据注入 AudioContext,再经 MediaStreamAudioDestinationNode 转为 MediaStream 后录制。

MediaRecorder 本身无法直接录制 WebAssembly(WASM)模块生成的音频数据,因为它只接受来自 MediaStream(如麦克风、AudioContext 的 MediaStreamAudioDestinationNode 输出)的轨道。WASM 通常运行在非 DOM 环境中(如线性内存),不直接产生媒体流。因此,关键在于:**将 WASM 输出的音频样本“桥接”进 Web Audio API 的音频图,再导出为 MediaStream,最后交由 MediaRecorder 处理**。
1. WASM 模块需输出标准 PCM 音频数据
确保你的 WASM 模块(例如用 Rust/C++ 编译而来)提供一个可被 JavaScript 调用的函数,用于获取一段音频样本(如 Float32Array,采样率 44100Hz,单/双声道)。常见模式:
- WASM 内部维护一个环形缓冲区或帧生成器
- JS 定期调用
getAudioFrame()或类似接口,返回当前音频帧(如 1024 个 float 样本) - 务必统一采样率(推荐 44100 或 48000)、位深(32-bit float)、声道数(如 stereo = 2)
2. 用 ScriptProcessorNode 或 AudioWorklet 将 WASM 数据注入 AudioContext
由于 ScriptProcessorNode 已废弃,**强烈推荐使用 AudioWorklet**(现代、低延迟、主线程无阻塞):
- 先注册 Worklet:
audioContext.audioWorklet.addModule('processor.js') - 在 processor.js 中,通过
port.postMessage()接收 JS 发送的 WASM 音频帧(注意:不能直接传 TypedArray,需用 transferable 或 copy) - 在
process()回调中,将收到的数据写入outputs[0](即音频输出) - 若 WASM 运行在 Worker 中,可通过
postMessage({type:'audio', data: frame}, [frame.buffer])高效传输
3. 创建 MediaStream 并连接到 MediaRecorder
利用 MediaStreamAudioDestinationNode 把 AudioContext 的输出转为 MediaStream:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
const dest = audioContext.createMediaStreamDestination()- 将 AudioWorkletNode 或其他音频源连接到
dest -
const mediaStream = dest.stream—— 此流包含实时合成的 WASM 音频 const mediaRecorder = new MediaRecorder(mediaStream, { mimeType: 'audio/webm; codecs=opus' })- 监听
dataavailable事件,收集 Blob 分片,合并为完整音频文件
4. 注意事项与优化建议
实际集成中易踩坑,需重点关注:
-
时序对齐:WASM 生成速率必须严格匹配 AudioContext 的渲染周期(如 128-sample 块),否则出现卡顿或爆音;可用
audioContext.currentTime控制生成节奏 - 内存管理:避免频繁创建/销毁 Float32Array;复用 ArrayBuffer + View,尤其在 Worker 中
- 跨线程通信开销:若 WASM 在 Worker 中运行,优先用 SharedArrayBuffer + Atomics 同步状态,减少 postMessage 频次
-
兼容性兜底:Safari 对 AudioWorklet 支持有限,可降级为
AudioBufferSourceNode+ 定时调度(但实时性略差)
整个链路本质是“WASM → JS → AudioWorklet → AudioContext → MediaStream → MediaRecorder”,核心不在 MediaRecorder 本身,而在于构建一条低延迟、零拷贝(尽可能)、时序可控的音频数据通路。只要音频能稳定流入 MediaStream,MediaRecorder 录制就水到渠成。


















