为什么没有为此 MediaStreamTrack 触发“结束”事件?

wpp*_*wpp 10 javascript webrtc mediastream

我想知道 aMediaStreamTrack的结束。根据MDN,一个ended事件是

在曲目播放结束时发送(当值readyState变为 时ended)。也可以使用onended事件处理程序属性。

所以我应该能够设置我的回调,如:

const [track] = stream.getVideoTracks();
track.addEventListener('ended', () => console.log('track ended'));
track.onended = () => console.log('track onended');
Run Code Online (Sandbox Code Playgroud)

一旦我通过以下方式停止跟踪,我希望这些被调用:

tracks.forEach(track => track.stop());
// for good measure? See
// https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/stop#Stopping_a_video_stream
videoElem.srcObject = null;
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是没有调用回调。我构建了以下JSFiddle,其中以 3 种不同方式创建了 3 个 MediaStream:

  1. getUserMedia
  2. getDisplayMedia
  3. getCaptureStream (画布元素)

我还有 3 个按钮可以停止相应MediaStream. 行为如下:

  • 所有 3 个流都是inactive,MediaStream 的oninactive回调被触发(在 Chrome 中,Firefox 似乎不支持这个)。
  • 所有轨道具有readyStateended停止后。
  • 如果我通过 Chrome 的 UI 停止屏幕流 (2. getDisplayMedia),则会调用轨道结束回调。

Chrome 的停止分享按钮

我知道您必须注意多个来源使用的曲目,但这里不应该是这种情况,对吧?我错过了一些明显的东西吗?

由于多个轨道可能使用相同的源(例如,如果两个选项卡正在使用设备的麦克风),源本身不一定会立即停止。相反,它与轨道解除关联并且轨道对象停止。一旦没有媒体轨道正在使用该源,该源实际上可能会完全停止。

jib*_*jib 13

为什么没有为此 MediaStreamTrack 触发“结束”事件?

因为当您自己调用track.stop()时,结束不会被明确触发。它仅在曲目因其他原因结束时触发。从规范:

被解雇时...

MediaStreamTrack 对象的源将不再提供任何数据,因为用户撤销了权限,或者因为源设备已被弹出,或者因为远程对等方永久停止发送数据。

这是设计使然。想法是当你自己停止事件时你不需要事件。要解决它,请执行以下操作:

track.stop();
track.dispatchEvent(new Event("ended"));
Run Code Online (Sandbox Code Playgroud)

MediaStream 的 oninactive 回调被触发(在 Chrome 中,Firefox 似乎不支持此功能)。

stream.oninactive并且该inactive事件已被弃用,并且不再出现在规范中。

作为解决方法,您可以在媒体元素上使用类似的结束事件:

video.srcObject = stream;
await new Promise(resolve => video.onloadedmetadata = resolve);
video.addEventListener("ended", () => console.log("inactive!")); 
Run Code Online (Sandbox Code Playgroud)

唉,这似乎还不能在 Chrome 中工作,但它可以在 Firefox 中工作