为什么没有为此 MediaStreamTrack 触发 'ended' 事件?
Why is the 'ended' event not firing for this MediaStreamTrack?
我想知道 MediaStreamTrack
的结局。根据 MDN 一个 ended
事件是
Sent when playback of the track ends (when the value readyState
changes to ended
).
Also available using the onended
event handler property.
所以我应该能够像这样设置我的回调:
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;
我遇到的问题是没有调用回调。我构建了以下 JSFiddle,其中以 3 种不同的方式创建了 3 个 MediaStreams:
getUserMedia
getDisplayMedia
getCaptureStream
(canvas 元素)
我还有 3 个按钮可以停止相应 MediaStream
的所有曲目。行为如下:
- 所有3个流都是
inactive
,MediaStream的oninactive
回调被触发(在Chrome,seems like Firefox doesn't support this)。
- 所有曲目在停止后的
readyState
为 ended
。
- 如果我通过 Chrome 的 UI 停止屏幕流 (2.getDisplayMedia),将调用轨道结束回调。
我知道您必须注意多个来源正在使用的曲目,但这里不应该是这种情况,对吧?我是否漏掉了一些明显的东西?
Since multiple tracks may use the same source (for example, if two tabs are using the device's microphone), the source itself isn't necessarily immediately stopped. It is instead disassociated from the track and the track object is stopped. Once no media tracks are using the source, the source may actually be completely stopped.
为什么没有为此 MediaStreamTrack 触发 'ended' 事件?
因为ended is explicitly not fired when you call track.stop()你自己。它仅在轨道因其他原因结束时触发。来自规范:
Fired when...
The MediaStreamTrack object's source will no longer provide any data, either because the user revoked the permissions, or because the source device has been ejected, or because the remote peer permanently stopped sending data.
这是设计使然。当时的想法是,当您自己停止事件时,您就不需要事件了。要解决此问题,请执行以下操作:
track.stop();
track.dispatchEvent(new Event("ended"));
MediaStream 的 oninactive 回调被触发(在 Chrome 中,Firefox 似乎不支持此功能)。
stream.oninactive
和 inactive
事件已弃用,不再包含在规范中。
作为解决方法,您可以在媒体元素上使用类似的 ended 事件:
video.srcObject = stream;
await new Promise(resolve => video.onloadedmetadata = resolve);
video.addEventListener("ended", () => console.log("inactive!"));
唉,这似乎在 Chrome 中不起作用,但它 works in Firefox。
我想知道 MediaStreamTrack
的结局。根据 MDN 一个 ended
事件是
Sent when playback of the track ends (when the value
readyState
changes toended
). Also available using theonended
event handler property.
所以我应该能够像这样设置我的回调:
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;
我遇到的问题是没有调用回调。我构建了以下 JSFiddle,其中以 3 种不同的方式创建了 3 个 MediaStreams:
getUserMedia
getDisplayMedia
getCaptureStream
(canvas 元素)
我还有 3 个按钮可以停止相应 MediaStream
的所有曲目。行为如下:
- 所有3个流都是
inactive
,MediaStream的oninactive
回调被触发(在Chrome,seems like Firefox doesn't support this)。 - 所有曲目在停止后的
readyState
为ended
。 - 如果我通过 Chrome 的 UI 停止屏幕流 (2.getDisplayMedia),将调用轨道结束回调。
我知道您必须注意多个来源正在使用的曲目,但这里不应该是这种情况,对吧?我是否漏掉了一些明显的东西?
Since multiple tracks may use the same source (for example, if two tabs are using the device's microphone), the source itself isn't necessarily immediately stopped. It is instead disassociated from the track and the track object is stopped. Once no media tracks are using the source, the source may actually be completely stopped.
为什么没有为此 MediaStreamTrack 触发 'ended' 事件?
因为ended is explicitly not fired when you call track.stop()你自己。它仅在轨道因其他原因结束时触发。来自规范:
Fired when...
The MediaStreamTrack object's source will no longer provide any data, either because the user revoked the permissions, or because the source device has been ejected, or because the remote peer permanently stopped sending data.
这是设计使然。当时的想法是,当您自己停止事件时,您就不需要事件了。要解决此问题,请执行以下操作:
track.stop();
track.dispatchEvent(new Event("ended"));
MediaStream 的 oninactive 回调被触发(在 Chrome 中,Firefox 似乎不支持此功能)。
stream.oninactive
和 inactive
事件已弃用,不再包含在规范中。
作为解决方法,您可以在媒体元素上使用类似的 ended 事件:
video.srcObject = stream;
await new Promise(resolve => video.onloadedmetadata = resolve);
video.addEventListener("ended", () => console.log("inactive!"));
唉,这似乎在 Chrome 中不起作用,但它 works in Firefox。