I am capturing a user's audio and video with the navigator.mediaDevices.getUserMedia()
and then using MediaRecorder
and its ondataavailable
to store that video and audio blob locally to upload later.
Now Im dealing with an issue where for some reason the ondataavailable
stops being called midway through the recording. I'm not sure why and I get no alerts that anything went wrong. So first, does anyone know why this might happen and how to catch the errors?
Second, I have tried to reproduce. By doing something like this.
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(camera) {
local_media_stream = camera;
camera.getVideoTracks()[0].onended = function() { console.log("VIDEO ENDED") }
camera.getAudioTracks()[0].onended = function() { console.log("Audio ENDED") }
camera.onended = function() { console.log("--- ENDED") }
camera.onremovetrack = (event) => { console.log(`${event.track.kind} track removed`); };
}).catch(function(error) {
alert('Unable to capture your camera. Please check logs.' + error);
console.error(error);
});
And recording the stream with
recorder = new MediaRecorder(local_media_stream, {
mimeType: encoding_options,
audioBitsPerSecond: 128000,
videoBitsPerSecond: bits_per_second,
});
recorder.ondataavailable = function(e) {
save_blob(e.data, blob_index)
blob_index++;
}
recorder.onstop = function(e) {
console.log("recorder stopped");
console.log(e)
}
recorder.onerror = function(error) {
console.log("recorder error");
alert(error)
throw error;
}
recorder.onstart = function() {
console.log('started');
};
recorder.onpause = function() {
console.log('paused');
};
recorder.onresume = function() {
console.log('resumed');
};
recorder.start(15000)
Then I try to kill the stream manually to hopefully reproduce whatever issue is occurring by doing
local_media_stream.getVideoTracks()[0].stop()
Now ondataavailable
is no longer called but none of the onended events were called. The recording is still going and the local_media_stream
is still active.
If I kill the audio too
local_media_stream.getAudioTracks()[0].stop()
Now the local_media_stream
is not active but still no event was called telling me the stream stopped and the recorder is still going but ondatavailable
is never being called.
What can I do? I want to know that the local stream is being recorded successfully and if not be alerted so I can at least inform the user that the recording is no longer saving.
Stopping both tracks should stop your recorder, it does for me in both FF and Chrome: https://jsfiddle.net/gpt51d6y/
But that's very improbable your users are calling
stop()
themselves.Most probably the problem isn't in the MediaRecorder, but before that in the MediaStream's tracks.
A MediaRecorder for which all its tracks are muted won't emit new dataavailable event, because from its perspective, there is still something that might be going on, the track may unmute at any time.
Think for instance of a microphone with an hardware push-to-talk feature, the track from this microphone would get muted every time the user releases such button, but the MediaRecorder, even though it won't record anything during this time, still has to increment its internal timing, so that the "gaps" don't get "glued" in the final media. However, since it had nothing passed to its graph, it won't either emit new dataavailable events, it will simply adjust the timestamp in the next chunk that will get emitted.
For your case of trying to find where the problem comes from, you can try to listen for the MediaRecorder's error event, it may fire in some cases.
But you should also definitely add events to every tracks of its stream, and don't forget the mute event: