如何从 Blob 创建 AudioBuffer?

How to create an AudioBuffer from a Blob?

我有一个音频 file/blob 是使用 MediaRecorder api:

创建的
let recorder = new MediaRecorder(this.stream)
let data = [];
recorder.ondataavailable = event => data.push(event.data);

然后在录制完成后:

let superBlob = new Blob(data, { type: "video/webm" });

如何使用此 blob 创建 AudioBuffer?我需要:

任何关于如何实现这一目标的提示都将受到赞赏。干杯!

要将 Blob 对象转换为 ArrayBuffer,请使用 FileReader.readAsArrayBuffer

let fileReader = new FileReader();
let arrayBuffer;

fileReader.onloadend = () => {
    arrayBuffer = fileReader.result;
}

fileReader.readAsArrayBuffer(superBlob);

接受的答案很好,但只给出了一个不是音频缓冲区的数组缓冲区。您需要使用音频上下文将数组缓冲区转换为音频缓冲区。

const audioContext = AudioContext()
const fileReader = new FileReader()

// Set up file reader on loaded end event
fileReader.onloadend = () => {

    const arrayBuffer = fileReader.result as ArrayBuffer

    // Convert array buffer into audio buffer
    audioContext.decodeAudioData(arrayBuffer, (audioBuffer) => {

      // Do something with audioBuffer
      console.log(audioBuffer)

    })

}

//Load blob
fileReader.readAsArrayBuffer(blob)

我希望答案中包含一个使用 decodeAudioData 的示例。我不得不在其他地方找到它,我想既然这是 "Blob to Audio Buffer" 的热门搜索,我会为下一个掉进这个兔子洞的人添加一些有用的信息。

两个答案都是正确的,有一些小的变化。这是我最终使用的功能:

function convertBlobToAudioBuffer(myBlob) {

  const audioContext = new AudioContext();
  const fileReader = new FileReader();

  fileReader.onloadend = () => {

    let myArrayBuffer = fileReader.result;

    audioContext.decodeAudioData(myArrayBuffer, (audioBuffer) => {

      // Do something with audioBuffer

    });
  };

  //Load blob
  fileReader.readAsArrayBuffer(myBlob);
}

所有答案都是正确的。然而,在 Chrome 76 和 Firefox 69 等现代网络浏览器中,有一种更简单的方法:使用 Blob.arrayBuffer()

因为 Blob.arrayBuffer() returns 一个 Promise,你可以做任何一个

superBlob.arrayBuffer().then(arrayBuffer => {
  // Do something with arrayBuffer
});

async function doSomethingWithAudioBuffer(blob) {
  var arrayBuffer = await blob.arrayBuffer();
  // Do something with arrayBuffer;
}

使用异步函数的简化版本:

async function blobToAudioBuffer(audioContext, blob) {
  const arrayBuffer = await blob.arrayBuffer();
  return await audioContext.decodeAudioData(arrayBuffer);
}

我把 audioContext 作为参数,因为我建议重用实例。