Open kanongil opened 3 years ago
Did a test on the viability of the first hack, and it appears that it can actually work, and might be the best solution.
The main complexity will be to detect when the new level has buffered the data for the current playhead. Any ideas?
- Add a "crappy MSE mode", which won't allow a level switch until the new level has a future independent part (relative to the current playhead) – possibly excluding forced / emergency switches.
This would make a lot of sense. Seeking is disruptive to both application logic and UX often noticeable to the user so maybe the first hack could be implemented as application logic using hls.js events rather than built in?
"crappy MSE mode" (which I don't thing is crappy if it prevents appends over the playback position) would be difficult (require a lot of changes) to implement for any independent part, but might not be so bad if only on upcoming segment boundaries (first part only) since the logic to switch on fragments is there, it's just not adapted to work at the LL-HLS edge with fragmentHint
parts.
@robwalch Any update about this one? https://github.com/video-dev/hls.js/issues/5111 has been closed due this issue and I can not see any updates since 2021.
This comment sums it up https://github.com/video-dev/hls.js/issues/5111#issuecomment-1360416520
While the next release will include important fixes over v1.2.9, it will not prevent the player from switching at moments when future appends will be made behind the play head (currentTime).
That happens when the stream controller uses next auto level on idle tick without considering that the next independent part is not available ahead of currentTime. What we found was that this is much more likely to happen if your key-frame interval is not a multiple of part hold back. Smaller key frame intervals (or more independent parts) provide more opportunities to switch without having to write over the playhead.
The same thing can happen without low-latency and with VOD when doing a fast switch (setting 'nextLoadLevel').
v1.4.0 has some improvements, which result in fewer of these events, but it can still happen when the player either does not or cannot switch down in time to avoid this kind of unreported stall.
Currently the player only recognizes stalls where currentTime stops advancing. Since there can inevitably be video appends that overlap with the playhead and result in this kind of 'frozen frame' stall, the player should attempt to reckon these late appends with the error/latency/abr controllers penalty processes. The available actions would be to:
The second part is to look at switching timing for playlists with many parts per segment and fewer independent parts. Enforcing switching at the next independent part is not happening currently, forcing the player to pick independent parts that start before the playhead in some cases when a switch happens. The player should also warn if streams contain non-independent part sequences longer than PART-HOLDBACK as that would make smooth switching impossible over those part runs.
Switching starts in stream-controller's idle tick here based on the abr-controller's pick regardless of what segment of part might come next:
For Low-Latency, it might be a good idea to pick a part first, and only run the code above if the part is independent. The part would not be loaded if a switch is started. The assumption would be that the player hopes to find an aligned independent part in variant it is switching to. This would avoid switching until all non-independent parts are appended in the current selection.
There could still be some delay in fetching the new playlist if we wait until the last part of the old playlist is loaded before starting to load it. By the time we receive an update in the current level with an independent part at the end, ideally the player would have also completed the same update in the playlist we are trying to switch to, but there is no such mechanism to refresh multiple variants prior to switch yet.
It appears that Chrome does not recognise keyframes that are inserted before the current media playhead. With LL-HLS and the current buffer appending logic, this can cause a playback freeze until a new keyframe appears, as documented below.
The Chrome behaviour is not new, eg. #680, but requires specific circumstances to trigger (near playhead, non-independent segments and/or bad keyframe alignment across levels). However, with LL-HLS, it is likely to be triggered for normal playback, since the PART-HOLD-BACK is easily less than a segment duration.
Ideas to hack around the issue:
What version of Hls.js are you using?
1.0.0-rc4
What browser and OS are you using?
Chrome 88.0.4324.192 Big Sur 11.2.3 (arm)
Test stream:
https://stream.sob.m-dn.net/live/sb1-ll/index.m3u8
https://hls-js-bacd5e47-f895-4a6f-8b13-e8c02b5c6a71.netlify.app/demo/?src=https%3A%2F%2Fstream.sob.m-dn.net%2Flive%2Fsb1-ll%2Findex.m3u8&demoConfig=eyJlbmFibGVTdHJlYW1pbmciOnRydWUsImF1dG9SZWNvdmVyRXJyb3IiOnRydWUsInN0b3BPblN0YWxsIjpmYWxzZSwiZHVtcGZNUDQiOmZhbHNlLCJsZXZlbENhcHBpbmciOi0xLCJsaW1pdE1ldHJpY3MiOi0xfQ==
Checklist
Steps to reproduce
Expected behavior
Smooth transition - like in Firefox and Safari.
Actual behavior
Video freezes for several seconds.
Console output
Partial media-internals log: