How can I add predefined length to audio recorded from MediaRecorder in Chrome?
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>
Media Recorder Save in WAV format across browsers
I built a package which should do exactly what you want. It's called extendable-media-recorder. It offers the same interface as the native MediaRecorder
but allows to "extend" it with custom codecs. The example codec is wav.
Here is how you could use it to record a stream coming from getUserMedia()
:
import { MediaRecorder, register } from 'extendable-media-recorder';
import { connect } from 'extendable-media-recorder-wav-encoder';
await register(await connect());
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecoder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
It will use the built-in MediaRecorder
to record pcm data in Chrome. In Firefox and Safari the Web Audio API is used to get the pcm data. Once the data has been retrieved it gets send to a worker which decodes it as wav.
Related Topics
How to Remove Only the Parent Element and Not Its Child Elements in JavaScript
Handle Url Fragment Identifier (Anchor) Change Event in JavaScript
What's the Difference Between JavaScript and Jscript
JavaScript Xmlhttprequest Using JSONp
How to Get a JavaScript Object Property Name That Starts with a Number
Testing If a Checkbox Is Checked with Jquery
JavaScript - Return String Between Square Brackets
Utf-8 Word Boundary Regex in JavaScript
Vuejs and Vue.Set(), Update Array
Normalizing Mousewheel Speed Across Browsers
How to Break/Exit from a Each() Function in Jquery
Sort an Array of Objects Based on Another Array of Ids
Internal/Modules/Cjs/Loader.Js:582 Throw Err
How to Get All Options of a Select Using Jquery
Convert Object Array to Hash Map, Indexed by an Attribute Value of the Object
Firebase Query Methods Startat() Taking Case Sensitive Parameters