首页 > 解决方案 > 如何从 JavaScript AudioAPI 获取连续的样本流

问题描述

我想从音频 API 中获取 JavaScript 中的连续样本流。我发现获取样本的唯一方法是通过 JavaScript 音频 API 中的 MediaRecorder 对象。

我这样设置我的录音机:

var options = {
  mimeType: "audio/webm;codec=raw",
}
this.mediaRecorder = new MediaRecorder(stream, options);
this.mediaRecorder.ondataavailable = function (e) {
  this.decodeChunk(e.data);
}.bind(this);
this.mediaRecorder.start(/*timeslice=*/ 100 /*ms*/);

这给了我每秒 10 次新数据的回调。到目前为止一切都很好。

数据被编码,所以我使用 audioCtx.decodeAudioData 来处理它:

let fileReader = new FileReader();
fileReader.onloadend = () => {
  let encodedData = fileReader.result;
  // console.log("Encoded length: " + encodedData.byteLength);
  this.audioCtx.decodeAudioData(encodedData,
    (decodedSamples) => {
      let newSamples = decodedSamples.getChannelData(0)
        .slice(this.firstChunkSize, decodedSamples.length);
      // The callback which handles the decodedSamples goes here.  All good.
      if (this.firstChunkSize == 0) {
        this.firstChunkSize = decodedSamples.length;
      }
    });
};

这一切都很好。

为文件阅读器设置数据很奇怪:

let blob;
if (!this.firstChunk) {
  this.firstChunk = chunk;
  blob = new Blob([chunk], { 'type': chunk.type });
} else {
  blob = new Blob([this.firstChunk, chunk], { 'type': chunk.type });
}
fileReader.readAsArrayBuffer(blob);

第一个块工作得很好,但第二个和以后的块无法解码,除非我将它们与第一个块结合起来。我猜这里发生的事情是第一个块具有解码数据所需的标头。在第二次解码后,我从第一个块中删除了解码的样本。见this.firstChunkSize上文。

这一切都没有错误地执行,但是我返回的音频在 10Hz 处具有类似颤音的效果。几个假设:

  1. 我的“firstChunkSize”和“splice”逻辑中有一些简单的错误

  2. 第一个块有一些标题,导致剩余数据以一种奇怪的方式解释。

  3. 创建音频源时,与某些选项有一些奇怪的交互(降噪?)

标签: web-audio-api

解决方案


你想要codecs=,没有codec=

var options = {
  mimeType: "audio/webm;codecs=pcm",
}

虽然MediaRecorder.isSupported会返回 truecodec=只是因为这个参数被忽略了。例如:

MediaRecorder.isTypeSupported("audio/webm;codec=pcm")
true
MediaRecorder.isTypeSupported("audio/webm;codecs=pcm")
true
MediaRecorder.isTypeSupported("audio/webm;codecs=asdfasd")
false
MediaRecorder.isTypeSupported("audio/webm;codec=asdfasd")
true

asdfasd如果您指定而codec不是codecs.


推荐阅读