带有 fetch 的 WebAudio 流:DOMException:无法解码音频数据

juj*_*ule 3 audio streaming google-chrome fetch web-audio-api

我正在尝试使用 Chrome 51 播放来自 fetch API 的无限流。(网络摄像头音频流为 Microsoft PCM,16 位,单声道 11025 Hz)

该代码对 mp3 文件几乎可以正常工作,除了一些小故障,但由于某种原因,它对 wav 文件根本不起作用,我得到“DOMException:无法解码音频数据”

该代码改编自此答案断断续续/听不清播放,通过 Web Audio API 使用分块音频

知道是否可以使其与 WAV 流一起使用吗?

function play(url) {
  var context = new (window.AudioContext || window.webkitAudioContext)();
  var audioStack = [];
  var nextTime = 0;

  fetch(url).then(function(response) {
    var reader = response.body.getReader();
    function read() {
      return reader.read().then(({ value, done })=> {
        context.decodeAudioData(value.buffer, function(buffer) {
          audioStack.push(buffer);
          if (audioStack.length) {
              scheduleBuffers();
          }
        }, function(err) {
          console.log("err(decodeAudioData): "+err);
        });
        if (done) {
          console.log('done');
          return;
        }
        read()
      });
    }
    read();
  })

  function scheduleBuffers() {
      while ( audioStack.length) {
          var buffer    = audioStack.shift();
          var source    = context.createBufferSource();
          source.buffer = buffer;
          source.connect(context.destination);
          if (nextTime == 0)
              nextTime = context.currentTime + 0.01;  /// add 50ms latency to work well across systems - tune this if you like
          source.start(nextTime);
          nextTime += source.buffer.duration; // Make the next buffer wait the length of the last buffer before being played
      };
  }
}
Run Code Online (Sandbox Code Playgroud)

只需使用 play('/path/to/mp3') 来测试代码。(服务器需要启用 CORS,或者在您运行脚本的同一个域中)

cwi*_*lso 5

AudioContext.decodeAudioData 并非旨在解码部分文件;它适用于“短”(但完整)的文件。由于 MP3 的分块设计,它有时适用于 MP3 流,但不适用于 WAV 文件。在这种情况下,您需要实现自己的解码器。

  • 或者在调用“decodeAudioData”之前在每个 PCM 数据块中添加一个 WAV 标头。WAV 标头非常简单。 (4认同)