PCM16音频转WAV再转Base64遇解码错误,求解决方案
问题分析与解决方案
你的思路存在关键错误:decodeAudioData API是用来解码带格式头的编码音频数据(如WAV、MP3等),但你传入的是裸PCM16原始数据,没有文件头标识格式信息,浏览器无法识别,因此报错。
不需要绕AudioContext解码,直接将PCM16数据包装成AudioBuffer,再转WAV即可,具体实现如下:
正确代码示例
import toWav from 'audiobuffer-to-wav'; const audioPromise = sdk.getRecordedAudioPcm16Samples(); audioPromise.then((pcm16Audio) => { // 替换为SDK实际采集的参数:采样率、声道数(需和SDK一致) const sampleRate = 16000; // 示例:16kHz采样率 const channelCount = 1; // 示例:单声道 const audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate }); // 创建对应参数的AudioBuffer const audioBuffer = audioContext.createBuffer(channelCount, pcm16Audio.length, sampleRate); // 将Int16格式的PCM数据转为AudioBuffer所需的Float32格式 const channelData = audioBuffer.getChannelData(0); for (let i = 0; i < pcm16Audio.length; i++) { // 16位PCM范围是[-32768, 32767],转成AudioBuffer要求的[-1, 1]浮点值 channelData[i] = pcm16Audio[i] / 32768; } // 将AudioBuffer编码为WAV格式的ArrayBuffer const wavBuffer = toWav(audioBuffer); // 把WAV数据转为Base64字符串 const wavBlob = new Blob([wavBuffer], { type: 'audio/wav' }); const fileReader = new FileReader(); fileReader.onloadend = () => { // 移除data URI前缀,只保留Base64内容 const base64Str = fileReader.result.split(',')[1]; // 此处可将base64Str发送至API console.log(base64Str); }; fileReader.readAsDataURL(wavBlob); });
关键注意事项
- 参数一致性:采样率、声道数必须和SDK采集时的参数完全一致,否则生成的WAV会出现速度异常、杂音等问题。
- 格式转换逻辑:AudioBuffer使用Float32格式存储音频数据,因此需要将Int16的PCM值转换为[-1, 1]范围的浮点值。
- 替代方案:如果不想依赖第三方包,也可以手动拼接WAV文件头(包含采样率、声道数、位深等信息)+ PCM原始数据,实现裸PCM到WAV的转换,但使用
audiobuffer-to-wav更省心高效。
内容的提问来源于stack exchange,提问作者Chris Oppedal
相关产品推荐
相关产品推荐

