Save the Duration from a Blob in a Browser [duplicate]
Asked Answered
C

3

11

I'm using window.MediaRecorder to record a wav audio file and then upload it to S3. I save chunks of data to an array and then create a Blob with them after recording is finished. This is working fine and I have no issues recording or playing the files. However, I can't for the life of me figure out how to set the duration of the resultant Blob file.

Whenever I download the file locally, or upload it to s3, there is no duration metadata anywhere. I am saving the duration of the audio as the user records, but have not been able to effectively attach this to the audio file. I feel like there should be a trivial solution, but I've just spent hours searching and can't seem to find anything on this. It has to be possible, so what am I missing?

Chateau answered 21/8, 2017 at 23:41 Comment(3)
You could parse the WAV header. It should contain all the information needed to calculate the duration of the aufio file accurately. The header description may be found here: soundfile.sapp.org/doc/WaveFormatRebutter
Record the start and stop moment and then calculate the seconds. Then add the seconds with a javascript library to the recorded blob. E.g. github.com/yusitnikov/fix-webm-duration - Or do the conversion on the server using ffmpeg that sets the length automatically.Dryclean
This might help: https://mcmap.net/q/261379/-how-can-i-add-predefined-length-to-audio-recorded-from-mediarecorder-in-chromeDryclean
A
7

Probably, you have already found a solution to this, but I am posting it for anyone else interested in this to see.

You could use MediaRecorder.onstart and onstop events.

  1. When MediaRecorder's onstart event is triggered you need to get the current date with something like Date.now().
  2. When onstop event is triggered, get the current date as well.
  3. You need to subtract those two dates to get the recorded audio's duration.

References:

Avail answered 11/11, 2017 at 15:17 Comment(4)
By the way, I am not very sure that .wav files are supported by default in Firefox and Chrome (not sure about others). Firefox could record .ogg files and Chrome .webm files. Hope it helps.Avail
How do you use the duration to set it onto the blob?Impostor
TBH I do not remember why I needed this at the time I have implemented this, however I assume that I wanted an easy way to keep the duration in my DB to make other steps of transformations more straightforward. So, you do not have to store the duration inside the blob, I have used a hidden input to store the duration and send it to the DB as a metadata for the audio.Avail
@CoreyCole, you can't set the duration in a webm/opus encoded file. The duration is derived by parsing the binary file after the fact.Bermuda
B
4

I've done a fair amount of research on this issue and the conclusion I've reached is that due to the way webm files are encoded, in order to get the duration, you'd have to parse the binary file and sum all the frames into a single duration. This is very complicated and tedious. If you're interested in doing this, read How to parse webm.

The route I went was a much simpler approach. Once the file has been recorded you should fetch it and attach it to a audio element. If you inspect the duration now, you'll still see that it's incorrect. What you need to do is wait for the loadedmetadata event. At that point you can run the following function:

checkForDuration(cb =()=> {}) {
  if(this.element.duration === Infinity) {
    this.element.currentTime = 1e101;
    this.element.ontimeupdate = function() {
      this.ontimeupdate = ()=> {return;};
      cb();
    };
  } else {
    cb();
  }
}

At the point that the callback is called, you can then inspect the audio element's duration property to get the correct duration. You can then store the duration in the DB for retrieval in the future.

Bermuda answered 26/7, 2020 at 13:5 Comment(1)
Could you share an example of what callback you pass to this?Mossy
I
1

There is a library that wraps around the browser's native MediaRecorder called RecordRTC. It exposes a function called getSeekableBlob().

Make sure to include the EBML.js CDN in your webpage, as getSeekableBlob() depends on it:

<script src="https://www.webrtc-experiment.com/EBML.js"></script>

You can see example usage here.

function stopRecordingCallback() {
    video.muted = false;
    video.volume = 1;
    video.src = video.srcObject = null;
    getSeekableBlob(recorder.getBlob(), function(seekableBlob) {
        video.src = URL.createObjectURL(seekableBlob);
        recorder.stream.stop();
        recorder.destroy();
        recorder = null;
        document.getElementById('btn-start-recording').disabled = false;
        invokeSaveAsDialog(seekableBlob, 'seekable-recordrtc.webm');
    });
}
Impostor answered 30/12, 2019 at 18:5 Comment(1)
Could you share a way to get the duration without saving the file?Mossy

© 2022 - 2024 — McMap. All rights reserved.