- From: Matías López via GitHub <sysbot+gh@w3.org>
- Date: Sun, 02 Apr 2023 21:50:31 +0000
- To: public-webrtc-logs@w3.org
This issue may be old, but nowadays it's "easy" to determine when a `MediaStream` has completely ended by using this "hack": ```js function addTrackListener(stream, track) { track.addEventListener('ended', () => { const allTracksEnd = stream.getTrackById(track.id) && stream.getTracks().every(trackX => trackX.readyState === 'ended'); if (stream.ended && !allTracksEnd) return; stream.ended = true; stream.dispatchEvent(new Event('ended')); }); } stream.addEventListener('addtrack', (event) => { addTrackListener(stream, event.track); }); stream.getTracks().forEach(track => { addTrackListener(stream, track); }); ``` However, this could be done natively when all tracks have ended, perhaps? The code above takes into account that each track needs to be attached to the `MediaStream`, and that the `readyState` is 'ended'. This simple verification of the 'ended' event in the `MediaStreamTrack` helps to avoid false positives for a `MediaStream` being 'ended' if the original MediaStreamTracks are removed using `MediaStream.removeTrack` and then stopped. Additionally, setting `stream.ended` to true helps avoid duplicate 'ended' events for each track. The issue arises when you obtain a `MediaStream` and then add a `MediaStreamTrack` using `addTrack`. This is when it becomes necessary to attach listeners to the new `MediaStreamTrack`. So, a comprehensive "polyfill" could be: ```js class MediaStreamPolyfill extends MediaStream { constructor(mediaStreamTracks) { super(mediaStreamTracks); this.getTracks().forEach(this.constructor.attachListeners.bind(this)); } addTrack(track) { super.addTrack(track); this.constructor.attachListeners.call(this, track); } removeTrack(track) { super.removeTrack(track); this.constructor.attachListeners.call(this, track); } static attachListeners(track) { track.addEventListener('ended', () => { const allTracksEnd = this.getTrackById(track.id) && this.getTracks().every(trackX => trackX.readyState === 'ended'); if (this.ended && !allTracksEnd) return; this.ended = true; this.dispatchEvent(new CustomEvent('ended')); }); } } ``` Although it is a hack, it is not bulletproof for all use cases; however, it is very useful in various situations. -- GitHub Notification of comment by matiaslopezd Please view or discuss this issue at https://github.com/w3c/mediacapture-main/issues/370#issuecomment-1493448156 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Sunday, 2 April 2023 21:50:32 UTC