Interstitial asset player incorrectly signals "ended" event
What version of Hls.js are you using?
1.6.14
What browser (including version) are you using?
Chromium Version 142.0.7444.162 (Official Build) stable (64-bit)
What OS (including version) are you using?
Linux OpenSuse Tumbleweed
Test stream
No response
Configuration
const config = {
debug: true
};
Additional player setup steps
const player = new Hls(config); player.attachMedia(videoElement);
Checklist
- [x] The issue observed is not already reported by searching on Github under https://github.com/video-dev/hls.js/issues
- [x] The issue occurs in the stable client (latest release) on https://hlsjs.video-dev.org/demo and not just on my page
- [x] The issue occurs in the latest client (main branch) on https://hlsjs-dev.video-dev.org/demo and not just on my page
- [x] The stream has correct Access-Control-Allow-Origin headers (CORS)
- [x] There are no network errors such as 404s in the browser console when trying to play the stream
Steps to reproduce
- Add an event listener to the video element for "ended", e.g:
videoElement.addEventListener("ended", (ev) => { console.log("**** ENDED"); }); - Play a stream that has HLS Interstitial ads (VOD or live) and wait for a an interstitial break to finish with the stream still playing
- Check the log to see whether "ended" has been signalled with the stream still playing
Expected behaviour
ended should not be signalled at the end of an interstitial break if the stream is still playing. Presumably, because the interstitial player is attached to the video element, it signals ended once it has no more data. However, this does not conform to the spec.
The HTML5 spec states that ended should be sent when playback has ended, which is defined as "The current playback position is the end of the media resource":
https://html.spec.whatwg.org/multipage/media.html#ended-playback
Media resource is defined here:
https://www.w3.org/TR/2008/WD-html5-20080610/video.html#:~:text=The%20term%20media%20resource%20is,file%2C%20or%20complete%20audio%20file.
"The term media resource is used to refer to the complete set of media data, e.g. the complete video file, or complete audio file"
An interstitial ad break does not meet the definition of a media resource.
What actually happened?
The ended event gets called after the interstitial break when the stream is still playing.
Console output
Not applicable.
Chrome media internals output
I have a stream that can be used to reproduce this issue, but I cannot share it publicly. If an HlsJs developer contacts me, I can share the URL privately.
If the behaviour of ended is intended, is there at least a means to ascertain whether ended was signalled by the IS player so that it can be ignored?
Use HLS.js events rather than HTMLMediaElement events to keep track of interstitial schedule playback. MEDIA_ENDED will be emitted by the primary player when playback is complete.
Use HLS.js events rather than HTMLMediaElement events to keep track of interstitial schedule playback. MEDIA_ENDED will be emitted by the primary player when playback is complete.
We do use HLS.js events to keep track of interstitial playback. However, we support a number of different players using streams with and without interstitial adverts. Using the standard events emitted by the video element allows us to reuse code for handling basic playback (e.g., play, pause, seek, ended etc.) without having to have separate implementations for each player. It also allows us to keep our bundle size smaller, which is essential for some customers.
Could this be treated as a bug or feature request? It is important that we are able to use the HTML5 standard.
You should make an exception for HLS.js playback of Interstitials in this context. It is not going to change any time soon.
"ended" is emitted by the HTMLMediaElement, not HLS.js, when playback reaches the end of an item. Each asset of an interstitial that changes the playback timeline is played as an item, with the MediaSource reset between items. If "end-of-stream" were not signaled for each item, playback would stall rather than play to completion. HLS.js uses this "ended" event to advance the interstitial schedule's playback.
Currently, the only time that interstitials do not reset the MediaSource or emit "ended" is when they replace segmented media of the same duration in the primary timeline.
Some enhancements have already been filed to reduce MediaSource resets. Separating the responsibility of HLS streaming from HTMLMediaElement playback is a core principle of HLS.js that Interstitial timelines break. Changing HTMLMediaElement behavior is not a priority for these enhancements, as it is already required to use new interfaces to track timeline progression during Interstitial playback.
I met similar issue with you @Sigebriht , I think you could do something to prevent ended been emitted:
videoElment.addEventListener('ended', function handleVideoElementEndedEvent (event) {
// we don't want ended to be emitted
// e.g. ended came from interstitial asset player
if (mediaNotEnded) {
// prevent event propagation
}
}, true);