I've got a very weird issue with the MediaRecorder API which I haven't been able to fix the last two days.
This simplified sample works perfectly fine, when I click the Chrome UI "Stop Sharing" button, everything stops appropriately:
desktopStream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true,
});
let rec = new MediaRecorder(desktopStream, {
mimeType: "video/webm; codecs=vp8,opus",
});
rec.onstop = async () => {
desktopStream.getTracks().forEach((s) => s.stop());
desktopStream = null;
//blobs.push(MediaRecorder.requestData());
blob = new Blob(blobs, {
type: "video/webm",
});
};
However this doesn't, it keeps recording (or some MediaTracks keep running, not entirely sure):
desktopStream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true,
});
voiceStream = await navigator.mediaDevices.getUserMedia({
video: false,
audio: true,
});
// this is the culprit, when commented everything works as expected
desktopStream.addTrack(voiceStream.getAudioTracks()[0]);
let rec = new MediaRecorder(desktopStream, {
mimeType: "video/webm; codecs=vp8,opus",
});
rec.onstop = async () => {
//explicitly stop tracks
desktopStream.getTracks().forEach((s) => s.stop();
voiceStream.getTracks().forEach((s) => s.stop());
desktopStream = null;
voiceStream = null;
//blobs.push(MediaRecorder.requestData());
blob = new Blob(blobs, {
type: "video/webm",
});
};
The second code block results in chrome still showing this red recording icon. I've read many times that you need to stop the tracks manually in a forEach loop, which I do, but it never gets to that, the recorder.onstop function doesn't seem to get called.
Here's the complete fiddle: https://jsfiddle.net/agcty/xhb0c4o3/19/
Steps to reproduce:
Ok, after very very extensive debugging I found out that when you click the "Stop Sharing" button, the recorder isn't actually stopped. That was just a wrong assumption I made due to the wording.
According to the documentation (https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/onstop) the recorder stops, when all MediaStreams that are being recorded stop, or when the recorder is stopped manually.
"Stop Sharing" only stops the screenStream MediaTracks. There is no onstop event happening whatsoever. The first example worked, because this was the only stream that was being captured, so stopping it meant that onstop was automatically called.
Visually this looks like:
The workaround is somewhat hidden but it works beautifully:
Just add an event listener to when the screenStream tracks are stopped, then manually stop the voiceStream tracks, resulting in the recorder not capturing anything anymore which in turn means it stops entirely. Yaaayy.
screenStream.getTracks().forEach((track) =>
track.addEventListener("ended", () => {
voiceStream.getAudioTracks().forEach((audio) => audio.stop());
if (recorder) recorder.stop();
recorder = null;
})
);
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