javascriptblobweb-mediarecorder

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


I want to record user's microphone 5 seconds long segments and upload each to the server. I tried using MediaRecorder and I called start() and stop() methods at 5 seconds time interval, but when I concatenate these recordings there is a "drop" sound between. So I tried to record 5 seconds segments using timeslice parameter of start() method:

navigator.mediaDevices.getUserMedia({ audio: { channelCount: 2, volume: 1.0, echoCancellation: false, noiseSuppression: false } }).then(function(stream) {
  const Recorder = new MediaRecorder(stream, { audioBitsPerSecond: 128000, mimeType: "audio/ogg; codecs=opus" });
  Recorder.start(5000); 
  Recorder.addEventListener("dataavailable", function(event) {
    const audioBlob = new Blob([event.data], { type: 'audio/ogg' });
    upload(audioBlob);
  });
});

But only the first segment is playable. What can I do, or how can I make all blobs playable? I MUST record then upload each segment. I CAN'T make an array of blobs (because the user could record 24hours of data or even more and the data needs to be uploaded on the server while the user is recording - with a 5 seconds delay).

Thank you!


Solution

  • 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: