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

时间:2019-05-02 12:58:41

标签: javascript webrtc mediastream

我想知道MediaStreamTrack的结尾。根据{{​​3}},ended事件是

  

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

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

const [track] = stream.getVideoTracks();
track.addEventListener('ended', () => console.log('track ended'));
track.onended = () => console.log('track onended');

我希望一旦我通过以下方式停止跟踪,就会调用它们:

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;

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

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

我还有3个按钮,用于停止相应MediaStream的所有曲目。行为如下:

  • 所有3个流都为inactive,MediaStream的oninactive回调被触发(在Chrome浏览器中,getCaptureStream)。
  • 所有曲目在停止后的readyState中的ended为{}。
  • 如果我通过Chrome的UI停止屏幕流(2. getDisplayMedia),则会调用跟踪结束的回调。

seems like Firefox doesn't support this

我知道您必须提防多个来源正在使用的曲目,但是这里不应该是这样吗?我缺少明显的东西吗?

  

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

1 个答案:

答案 0 :(得分:2)

为什么没有为此MediaStreamTrack触发“终止”事件?

因为ended在您自己呼叫track.stop()时显式 被触发。仅在轨道由于其他原因而结束时才会触发。根据规格:

  

在...时触发

     

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

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

track.stop();
track.dispatchEvent(new Event("ended"));

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

stream.oninactiveinactive事件已弃用,不再属于规范。

为此,您可以在媒体元素上使用类似的ended事件:

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

A,看来在Chrome中尚不能使用,但works in Firefox