在JavaScript/Angular中实现音频倒放功能遇无声问题
问题分析与修复方案
你的代码存在两个核心问题,导致倒放时无声音:
1. 错误复用原Buffer,未使用反转后的Buffer
你已经创建了存储反转音频的reversedBuffer,但最后却通过copyFromChannel把单通道反转数据写回原bufferToPlay,这会导致:
- 污染原Buffer的原始数据,影响后续正常播放
- 仅处理了0号通道,多声道音频的其他通道数据未更新
- 本质上播放的还是被错误修改的原Buffer,而非完整的反转音频
修复代码:直接将反转后的Buffer赋值给bufferToPlay:
if (this.speechAudioBufferService.getModifyedBuffer && this.fastRewind) { const actualBuffer = this.speechAudioBufferService.getModifyedBuffer; const channels = actualBuffer.numberOfChannels; const length = actualBuffer.length; const reversedBuffer = this.aCtx.createBuffer(channels, length, actualBuffer.sampleRate); for (let channel = 0; channel < channels; channel++) { const originalData = actualBuffer.getChannelData(channel); const reversedData = reversedBuffer.getChannelData(channel); for (let i = 0; i < length; i++) { reversedData[i] = originalData[length - i - 1]; } } // 直接使用反转后的Buffer作为播放源 bufferToPlay = reversedBuffer; }
2. 播放起始位置不匹配反转逻辑
原currentPosition是基于正向音频的时间轴,反转Buffer的时间轴完全相反:
- 正向音频的
0秒对应反转音频的总时长位置 - 正向音频的
currentPosition对应反转音频的总时长 - currentPosition位置
如果直接用原位置播放反转Buffer,会导致从反转音频的后半段甚至超出范围的位置开始播放,自然无声音。
修复代码:计算反转后的起始位置:
let startOffset = this.positionAndDurationService.currentPosition; // 倒放时修正起始位置 if (this.fastRewind && bufferToPlay) { startOffset = bufferToPlay.duration - startOffset; } this.source.start(0, startOffset);
额外优化:用负播放速率实现高效倒放
Web Audio API支持直接设置playbackRate为负数实现倒放,无需创建反转Buffer,更适合按住按钮实时切换的场景:
if (this.fastRewind) { // 负速率实现倒放,-2代表2倍速倒放 this.source.playbackRate.value = -Math.abs(this.playRate()); bufferToPlay = this.speechAudioBufferService.getModifyedBuffer; } else { this.source.playbackRate.value = this.playRate(); } // 负速率下直接使用原currentPosition即可,API自动处理倒放逻辑 this.source.start(0, this.positionAndDurationService.currentPosition);
内容的提问来源于stack exchange,提问作者Amardeep Ahlawat
相关产品推荐
相关产品推荐

