video-dev / hls.js

HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.
https://hlsjs.video-dev.org/demo
Other
14.76k stars 2.56k forks source link

How to achieve "Instant Quality switching" #5334

Closed Dustin-Digitar closed 1 year ago

Dustin-Digitar commented 1 year ago

What do you want to do with Hls.js?

I want to instantly switch the video quality when it detects high bandwidth. Currently, only the next segment quality is switched. So, the user won't see a quality increase until playback reaches the next segment.

What have you tried so far?

I tried using hls.currentLevel to set the quality. According to the documentation, this should instantly switch the quality, and clear the buffer, but for me it did nothing.

Along the same line, the readme says hls.js supports:

Adaptive streaming
    Manual & Auto Quality Switching
        3 Quality Switching modes are available (controllable through API means)
            Instant switching (immediate quality switch at current video position)
            Smooth switching (quality switch for next loaded fragment)
            Bandwidth conservative switching (quality switch change for next loaded fragment, without flushing the buffer)
          In Auto-Quality mode, emergency switch down in case bandwidth is suddenly dropping to minimize buffering.

How can I achieve "Instant Switching"?

robwalch commented 1 year ago

If you want the user to have a seamless experience, use smooth switching.

Setting currentQuality interrupts the experience because it must flush the buffer first as the new quality is loaded. The switch is started instantly or immediately, but the experience is not, as media still needs to be loaded, appended, and decoded.

Dustin-Digitar commented 1 year ago

My issue was that even setting currentQuality had no effect whatsoever.

I handled the issue in another way, so I no longer need this to be fixed.

robwalch commented 1 year ago

My issue was that even setting currentQuality had no effect whatsoever.

currentQuality is not a property or method on Hls instances. You can troubleshoot what happens when setting hls.currentLevel starting here:

https://github.com/video-dev/hls.js/blob/7782205b9ae955ee7e23194c1e74ce4743fcf2cb/src/hls.ts#L459-L467

Setting currentLevel will always run the steps above. In addition to flushing the main buffer to clear out all video (or audio for audio-only streams) in stream-controller immediateLevelSwitch, manualLevel is set on the level-controller which will either switch to auto select if the index is -1, or switch to manual selection finish by:

  1. returning early if the level index matches the current level index
  2. Trigger LEVEL_SWITCHING when calling set level on the level-controller to an index matching an available Level in hls.levels
  3. Trigger a LEVEL_SWITCH_ERROR if the index is out of range