'How to create an AudioBuffer from a Blob?

I have an audio file/blob that has been created using the MediaRecorder api:

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

and then later when the recording is finished:

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

How can I use this blob to create an AudioBuffer? I need to either :

  • Transform the Blob object into an ArrayBuffer which I could use with AudioContext.decodeAudioData (returns an AudioBuffer) or
  • Transform the Blob object into an Float32Array, where I could copy it into the AudioBuffer with AudioBuffer.copyToChannel()

Any tips on how to achieve that are appreciated. Cheers!



Solution 1:[1]

The accepted answer is great but only gives an array buffer which is not an audio buffer. You need to use the audio context to convert the array buffer into an audio buffer.

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)

I wish the answer had included an example using decodeAudioData. I had to find it somewhere else and I thought since this is the top search for "Blob to Audio Buffer" I would add some helpful information for the next person that comes down this rabbit hole.

Solution 2:[2]

All the answers are true. However, in the modern web browsers like Chrome 76 and Firefox 69, there is a much simpler way: using Blob.arrayBuffer()

Since Blob.arrayBuffer() returns a Promise, you can do either

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

or

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

Solution 3:[3]

Both Answers are true, there are some minor changes. This is the function I finally used:

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);
}

Solution 4:[4]

A simplified version using an async function:

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

I put audioContext as a param, because I recommend reusing instances.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PAT-O-MATION
Solution 2
Solution 3 amitgur
Solution 4 Erik Hermansen