我在MediaRecorder API上遇到了一个非常奇怪的问题,这两天我一直没能解决。
这个简化的样本工作得非常好,当我点击Chrome UI的 "停止分享 "按钮时,一切都适当地停止了。
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",
});
};
然而这并没有,它一直在录制(或者一些MediaTracks一直在运行,不完全确定)。
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",
});
};
第二个代码块的结果是chrome仍然显示这个红色的录制图标。我读过很多次,你需要在forEach循环中手动停止音轨,我是这么做的,但是从来没有达到这个目的,recorder.onstop函数似乎没有被调用。
下面是完整的提琴。https:/jsfiddle.netagctyxhb0c4o319。
重现的步骤。
好吧,经过非常非常多的调试,我发现当你点击 "停止分享 "按钮时,录音机其实并没有停止。这只是我由于措辞而做出的一个错误假设。
根据文档(https:/developer.mozilla.orgen-USdocsWebAPIMediaRecorderonstop。)时、正在录制的所有MediaStream停止时、或者手动停止录制机时,录制机都会停止。
"停止共享 "只停止屏幕流MediaTracks。根本没有发生任何onstop事件。第一个例子是可行的,因为这是唯一一个被捕获的流,所以停止它意味着onstop被自动调用。
在视觉上,这看起来像。
这个变通方法有点隐蔽,但效果很好。
只要添加一个事件监听器,当屏幕流轨道停止时, 然后手动停止语音流轨道,导致录音机不再捕捉任何东西, 这反过来意味着它完全停止。Yaaayy。
screenStream.getTracks().forEach((track) =>
track.addEventListener("ended", () => {
voiceStream.getAudioTracks().forEach((audio) => audio.stop());
if (recorder) recorder.stop();
recorder = null;
})
);