Chrome端AudioWorklet录制音频跨片段数据残留溢出问题解决方案咨询
问题根因
- 启停参数缺失导致缓冲区未按时刷新:主线程调用
stopRecorderWorklet和startRecorderWorklet时,没有向Worklet传递对应stopTime、startTime时间戳参数,Worklet初始化的_stopTime值为999999999,停止录制时的判断条件currentTime > this._stopTime永远无法触发,导致录制结束后Worklet内部未满的缓冲区数据不会被flush,残留的约0.5秒音频数据一直保存在Worklet的内存中。 - Worklet内部缓冲区未主动清空:下一次录制启动时,旧的残留数据没有被清理,新数据写入后缓冲区满触发flush时,会把上一段的残留数据一起发送到主线程,导致上一段末尾内容出现在新录音开头。
- 浏览器底层行为差异:Safari断开音频节点连接时会自动清空Worklet的输入缓存和内部状态,Chrome则会保留AudioWorkletProcessor的实例内存,因此该问题仅在Chrome上复现。
- 连接逻辑笔误:补充说明里贴的启停连接逻辑写反,停止录制时执行connect属于无效操作,重复连接还会导致音频上下文冗余挂载。
修复方案
1. 修复主线程启停参数传递
修改stopRecorderWorklet和startRecorderWorklet方法,传递对齐音频上下文时间线的时间戳:
stopRecorderWorklet() { this.recorderNode.port.postMessage({ eventType: "stopRecording", // 新增:传递当前音频上下文时间作为停止时间 stopTime: this.audioContext.currentTime }); }, startRecorderWorklet() { // 先确保已断开旧连接,避免重复连接 try { this.micSource.disconnect(this.recorderNode); this.recorderNode.disconnect(this.audioContext.destination); } catch (e) {} this.micSource.connect(this.recorderNode); this.recorderNode.connect(this.audioContext.destination); console.log("start Recorder Worklet()"); this.recorderNode.port.postMessage({ eventType: "startRecording", // 新增:传递当前音频上下文时间作为开始时间 startTime: this.audioContext.currentTime }); },
2. 增加Worklet内部缓冲区主动清空逻辑
在Worklet的startRecording事件处理中,新增缓冲区初始化操作,清理上一次的残留数据:
// AudioWorkletProcessor的port.onmessage逻辑内 if (data.eventType == "startRecording") { this._startTime = data.startTime; this._stopRecording = false; // 新增:启动录制前清空内部残留缓冲区 this._initBuffer(); this._initBuffers(1); }
3. 优化停止录制的flush逻辑(可选)
修改Worklet的process方法,停止录制时只要缓冲区非空就强制flush,避免时间判断误差导致数据残留:
if (this._stopRecording && !this._isBufferEmpty()) { // 移除时间判断,直接flush残留数据 this._flush(); this._recordingStopped(); } else if (!this._stopRecording && currentTime > this._startTime) { this._pushToBuffers(inputs[0], 1); }
内容的提问来源于stack exchange,提问作者Anders Lunde
相关产品推荐
相关产品推荐

