Record 5 seconds segments of audio using MediaRecorder and then upload to the server

You have to understand how media files are built.
It is not only some raw data that can be converted to either audio or video directly.

It will depend on the format chosen, but the basic case is that you have what is called metadata which are like a dictionary describing how the file is structured.

These metadata are necessary for the software that will then read the file to know how it should parse the actual data that is contained in the file.

The MediaRecorder API is in a strange position here, since it must be able to at the same time write these metadata, and also add non-determined data (it is a live recorder).

So what happens is that browsers will put the main metadata at the beginning of the file, in a way that they’ll be able to simply push new data to the file, and still be a valid file (even though some info like duration will be missing).

Now, what you get in datavailableEvent.data is only a part of a whole file, that is being generated.
The first one will generally contain the metadata, and some other data, depending on when the event has been told to fire, but the next parts won’t necessarily contain any metadata.

So you can’t just grab these parts as standalone files, because the only file that is generated is the one that is made of all these parts, joined together in a single Blob.


So, to your problem, you have different possible approaches:

  • You could send to your server the latest slices you got from your recorder in an interval, and merge these server-side.

    const recorder = new MediaRecorder(stream);
    const chunks = [];
    recorder.ondataavailable = e => chunks.push(e.data);
    recorder.start(); // you don't need the timeslice argument
    setInterval(()=>{
      // here we both empty the 'chunks' array, and send its content to the server
      sendToServer(new Blob(chunks.splice(0,chunks.length)))
    }, 5000);
    

    And on your server-side, you would append the newly sent data to the being recorded file.

  • An other way would be to generate a lot of small standalone files, and to do this, you could simply generate a new MediaRecorder in an interval:

    function record_and_send(stream) {
       const recorder = new MediaRecorder(stream);
       const chunks = [];
       recorder.ondataavailable = e => chunks.push(e.data);
       recorder.onstop = e => sendToServer(new Blob(chunks));
       setTimeout(()=> recorder.stop(), 5000); // we'll have a 5s media file
       recorder.start();
    }
    // generate a new file every 5s
    setInterval(record_and_send, 5000);
    

    Doing so, each file will be standalone, with a duration of approximately 5 seconds, and you will be able to play these files one by one.
    Now if you wish to only store a single file on server, still using this method, you can very well merge these files together on server-side too, using e.g a tool like ffmpeg.

Leave a Comment