You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Web Codecs编码AudioBuffer报错:输入缓冲区与编解码器参数不兼容

解决Web Codecs编码时的"Input audio buffer is incompatible with codec parameters"错误

错误原因及修复方案

1. 编码器配置与AudioData参数不匹配

你给AudioEncoder固定配置了采样率44100,但创建AudioData时使用的是原音频的audioBuffer.sampleRate,如果原音频采样率(比如48000)与编码器配置不一致,就会触发参数不兼容错误。

修复:
要么统一使用原音频的参数配置编码器,要么将原音频重采样到编码器指定的采样率:

  • 方案一(统一参数):
encoder.configure({
  codec: 'opus',
  sampleRate: audioBuffer.sampleRate, // 对齐原音频采样率
  numberOfChannels: audioBuffer.numberOfChannels, // 对齐原音频声道数
  bitrate: 128_000,
});
  • 方案二(强制重采样):
async function resampleAudioBuffer(buffer: AudioBuffer, targetSampleRate: number): Promise<AudioBuffer> {
  if (buffer.sampleRate === targetSampleRate) return buffer;
  
  const offlineContext = new OfflineAudioContext(
    buffer.numberOfChannels,
    Math.floor(buffer.length * targetSampleRate / buffer.sampleRate),
    targetSampleRate
  );
  const source = offlineContext.createBufferSource();
  source.buffer = buffer;
  source.connect(offlineContext.destination);
  source.start();
  return await offlineContext.startRendering();
}

// 在encodeAudio中调用
const audioBuffer = await fetchAudioBuffer(url);
const resampledBuffer = await resampleAudioBuffer(audioBuffer, 44100);

2. 平面格式转换的偏移量错误

bufferToF32Planar函数中,offset = data.length的写法错误,会导致多声道数据互相覆盖,生成的平面数据格式完全不符合要求,这是触发错误的核心原因之一。

修复:

function bufferToF32Planar(input: AudioBuffer): Float32Array {
  const result = new Float32Array(input.length * input.numberOfChannels);

  let offset = 0;
  for (let i = 0; i < input.numberOfChannels; i++) {
    const data = input.getChannelData(i);
    result.set(data, offset);
    offset += data.length; // 改为累加偏移量
  }

  return result;
}

3. 缺少编码器的flush操作

调用encoder.encode(data)后,必须调用encoder.flush()通知编码器处理剩余数据并输出结果,否则编码器可能无法正常完成编码流程,甚至引发状态异常。

修复:

encoder.encode(data);
await encoder.flush();
encoder.close(); // 编码完成后关闭编码器

完整修复后的代码示例

/**
 * Encode an audio file using web codecs
 */
async function encodeAudio(url: string) {
  const audioBuffer = await fetchAudioBuffer(url);
  const signal = bufferToF32Planar(audioBuffer);

  const encoder = new AudioEncoder({
    output: (chunk) => {
      console.log('编码输出:', chunk);
      // 可在此处理编码后的Chunk,例如转为Blob保存
    },
    error: console.error,
  });

  encoder.configure({
    codec: 'opus',
    sampleRate: audioBuffer.sampleRate,
    numberOfChannels: audioBuffer.numberOfChannels,
    bitrate: 128_000,
  });

  const data = new AudioData({
    format: 'f32-planar',
    sampleRate: audioBuffer.sampleRate,
    numberOfChannels: audioBuffer.numberOfChannels,
    numberOfFrames: audioBuffer.length,
    timestamp: 0,
    data: signal,
  });

  encoder.encode(data);
  await encoder.flush();
  encoder.close();
}

/**
 * Convert an audio buffer into a planar float 32 array
 * @param input processed audio buffer
 * @returns Typed array
 */
function bufferToF32Planar(input: AudioBuffer): Float32Array {
  const result = new Float32Array(input.length * input.numberOfChannels);

  let offset = 0;
  for (let i = 0; i < input.numberOfChannels; i++) {
    const data = input.getChannelData(i);
    result.set(data, offset);
    offset += data.length;
  }

  return result;
}

/**
 * Fetch the audio file and convert it into
 * an audio buffer using an audio context
 */
async function fetchAudioBuffer(
  input: RequestInfo | URL,
  init?: RequestInit | undefined,
): Promise<AudioBuffer> {
  const context = new AudioContext();
  const res = await fetch(input, init);
  const buffer = await res.arrayBuffer();

  return await context.decodeAudioData(buffer);
}

await encodeAudio('/audio.mp3');

内容的提问来源于stack exchange,提问作者Konstantin Paulus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:57:43