javascriptweb-audio-apimediarecorder

Javascript MediaRecorder audio recording corrupt


I am struggeling to get record audio in the browser and make it work properly on mobile as well as desktop.

I am using MediaRecorder to start the recording and I want to send it as a file to my Flask server through a form. However, what I receive is a corrupt file, that sometimes plays on my desktop, but not on my mobile phone. I think it is connected to different mimeTypes that are supported and how the blob gets converted.

Here is the JavaScript Code:

function record_audio(){
    if(state == "empty"){
    navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
      mediaRecorder = new MediaRecorder(stream); 
      mediaRecorder.start();

      state = "recording";
      document.getElementById('stop_btn').style.display = 'block'

      seconds_int = setInterval(
      function () {
        document.getElementById("record_btn").innerHTML = seconds_rec + " s";
        seconds_rec += 1;
    }, 1000);

      
      mediaRecorder.addEventListener("dataavailable", event => {
        
        audioChunks.push(event.data);
        if(mediaRecorder.state == 'inactive')  makeLink();
      });
  }
}

function makeLink(){
      const audioBlob = new Blob(audioChunks, {type: 'audio/mpeg'});
      
      const audioUrl = URL.createObjectURL(audioBlob);
      var sound      = document.createElement('audio');
      sound.id       = 'audio-player';
      sound.controls = 'controls';
      sound.src      = audioUrl;
      console.log(audioBlob)
      sound.type     = 'audio/mpeg';
      document.getElementById("audio-player-container").innerHTML = sound.outerHTML;
      
      let file = new File([audioBlob], "audio.mp3",{ type:"audio/mpeg",lastModifiedDate: new Date()});
      let container = new DataTransfer();
      container.items.add(file);
      document.getElementById("uploadedFile").files = container.files;

};

Thanks for your help!


Solution

  • The audio that you recorded is most likely not of type 'audio/mpeg'. No browser supports that out of the box.

    If you call new MediaRecorder(stream) without the optional second argument the browser will pick the codec it likes best. You can use the mimeType property to find out which codec is used by the browser. It can for example be used to construct the Blob.

    const audioBlob = new Blob(
        audioChunks,
        {
            type: mediaRecorder.mimeType
        }
    );
    

    You would also need to use it in a similar way when creating the File. And you probably also need to adapt your backend logic to handle files which aren't MP3s.