While using RecordRTC to record HTML5 webcam video/audio in the browser, I was miffed to find no duration or length property available upon deep introspection of the various types involved (MediaStream, MediaStreamTrack, RecordRTC itself, Blob, File).
It turns out that the streams themselves don’t have finite durations, which sort of makes sense if you consider that you could infinitely record if you wanted (though arguably a stream should have a finite duration when the stream is stopped or paused). Once you have captured a Blob from your video or audio stream, you do have something with a duration—but the Blob type itself is just a container for abstract data, so it does not expose any particular interface to obtain duration of video or audio.
The only way to get the video or audio recording’s duration is through HTML5 <video> or <audio> elements. If you don’t already have your stream attached to such an element, you can create one on-the-fly solely for the purpose of invisibly retrieving the Blob duration:
1 2 3 4 5 6 7 8 9 |
var blob = ... // Your Blob capture from the stream var tempVideoEl = document.createElement('video'); tempVideoEl.addEventListener('loadedmetadata', function() { // duration is now available here -- store it somewhere as you like console.log(tempVideoEl.duration); }); tempVideoEl.src = window.URL.createObjectURL(blob); |
Along comes Chrome
Unfortunately, there is currently a Chromium bug that causes the duration not to be available under certain circumstances. In these conditions, you will see the video or audio duration as being Infinity (a vestige of the infinite stream concept, presumably).
Thankfully there is a fix in which you can set the element’s currentTime pointer long past the end of the clip, and the duration property will be updated appropriately. A pseudocode solution looks like this (thanks Kaiido):
1 2 3 4 5 6 7 8 9 10 |
tempVideoEl.addEventListener('loadedmetadata', function() { // Chromium bug condition if(tempVideoEl.duration === Infinity) { // ...set tempVideoEl.currentTime to a very large number // ...listen to "timeupdate" event // ...on "timeupdate", retrieve now-updated duration } else // ...retrieve duration as usual }); |
A neatly packaged solution
So you don’t have to suffer a copy-pasta codebase, I produced a small npm package get-blob-duration that you can easily install, import, and use with a fluent, simple Promise interface:
1 2 3 4 |
// Returns Promise<Number> getBlobDuration(blob).then(function(duration) { console.log(duration + ' seconds'); }); |
Or for ECMAScript 6:
1 2 3 |
// yada yada async const duration = await getBlobDuration(blob) console.log(duration + ' seconds') |
Enjoy.