MediaRecorder API 录制多个音轨时,无法调用 "停止"。

问题描述 投票:0回答:1

我在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。

重现的步骤。

  1. 点击 "开始录制"
  2. 选择屏幕
  3. 做任何事情都要有几秒钟的时间
  4. 点击Chrome浏览器的 "停止分享 "按钮,而不是摆弄中的按钮。
  5. 点击 "下载 "时,红色的录音图标仍会显示,无法下载录音。
  6. 点击 "停止录音"(提琴中的按钮),现在录音已经正确停止了。
  7. 现在注释 "desktopStream.addTrack(voiceStream.getAudioTracks()[0]); "这一行。
  8. 一切都正常了

enter image description here

javascript screen-capture web-mediarecorder
1个回答
0
投票

好吧,经过非常非常多的调试,我发现当你点击 "停止分享 "按钮时,录音机其实并没有停止。这只是我由于措辞而做出的一个错误假设。

根据文档(https:/developer.mozilla.orgen-USdocsWebAPIMediaRecorderonstop。)时、正在录制的所有MediaStream停止时、或者手动停止录制机时,录制机都会停止。

"停止共享 "只停止屏幕流MediaTracks。根本没有发生任何onstop事件。第一个例子是可行的,因为这是唯一一个被捕获的流,所以停止它意味着onstop被自动调用。

在视觉上,这看起来像。

enter image description here

这个变通方法有点隐蔽,但效果很好。

只要添加一个事件监听器,当屏幕流轨道停止时, 然后手动停止语音流轨道,导致录音机不再捕捉任何东西, 这反过来意味着它完全停止。Yaaayy。

screenStream.getTracks().forEach((track) =>
      track.addEventListener("ended", () => {
        voiceStream.getAudioTracks().forEach((audio) => audio.stop());
        if (recorder) recorder.stop();
        recorder = null;
      })
    ); 
© www.soinside.com 2019 - 2024. All rights reserved.