I am in the process of replacing RecordRTC with the built in MediaRecorder for recording audio in Chrome. The recorded audio is then played in the program with audio api. I am having trouble getting the audio.duration property to work. It says
If the video (audio) is streamed and has no predefined length, "Inf" (Infinity) is returned.
With RecordRTC, I had to use ffmpeg_asm.js to convert the audio from wav to ogg. My guess is somewhere in the process RecordRTC sets the predefined audio length. Is there any way to set the predefined length using MediaRecorder?
One of the best ways to record audio on a website is to use a Chrome Extension like Audio Capture. This tool can be easily installed on the browser, ready to use whenever you need to record audio on any tab. It also allows you to mute all other tabs to avoid accidently recording them as well.
This is a chrome bug.
FF does expose the duration of the recorded media, and if you do set the currentTime
of the recorded media to more than its actual duration
, then the property is available in chrome...
var recorder, chunks = [], ctx = new AudioContext(), aud = document.getElementById('aud'); function exportAudio() { var blob = new Blob(chunks); aud.src = URL.createObjectURL(new Blob(chunks)); aud.onloadedmetadata = function() { // it should already be available here log.textContent = ' duration: ' + aud.duration; // handle chrome's bug if (aud.duration === Infinity) { // set it to bigger than the actual duration aud.currentTime = 1e101; aud.ontimeupdate = function() { this.ontimeupdate = () => { return; } log.textContent += ' after workaround: ' + aud.duration; aud.currentTime = 0; } } } } function getData() { var request = new XMLHttpRequest(); request.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg', true); request.responseType = 'arraybuffer'; request.onload = decodeAudio; request.send(); } function decodeAudio(evt) { var audioData = this.response; ctx.decodeAudioData(audioData, startRecording); } function startRecording(buffer) { var source = ctx.createBufferSource(); source.buffer = buffer; var dest = ctx.createMediaStreamDestination(); source.connect(dest); recorder = new MediaRecorder(dest.stream); recorder.ondataavailable = saveChunks; recorder.onstop = exportAudio; source.start(0); recorder.start(); log.innerHTML = 'recording...' // record only 5 seconds setTimeout(function() { recorder.stop(); }, 5000); } function saveChunks(evt) { if (evt.data.size > 0) { chunks.push(evt.data); } } // we need user-activation document.getElementById('button').onclick = function(evt){ getData(); this.remove(); }
<button id="button">start</button> <audio id="aud" controls></audio><span id="log"></span>
So the advice here would be to star the bug report so that chromium's team takes some time to fix it, even if this workaround can do the trick...
Thanks to @Kaiido for identifying bug and offering the working fix.
I prepared an npm package called get-blob-duration that you can install to get a nice Promise-wrapped function to do the dirty work.
Usage is as follows:
// Returns Promise<Number> getBlobDuration(blob).then(function(duration) { console.log(duration + ' seconds'); });
Or ECMAScript 6:
// yada yada async const duration = await getBlobDuration(blob) console.log(duration + ' seconds')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With