On the API page, as the description of the "setting" of currentLevel, it's stated that:
set: Trigger an immediate quality level switch to new quality level. This will pause the video if it was playing, flush the whole buffer, and fetch fragment matching with current position and requested quality level. Then resume the video if needed once fetched fragment will have been buffered.
My problem is the part where it says "This will pause the video if it was playing,", why is that?! Why does it pause the video?! That is undesirable sometimes, why not "just" flush the buffer, which would effectively pause the video, AND fire the HTML5 video's onwaiting event, which lets you show a loader or something, but when the video is paused before the buffer is flushed, then the onwaiting event is not fired at that point. So, why not just flush the buffer?!
Hi @AradAral,
My problem is the part where it says "This will pause the video if it was playing,", why is that?! Why does it pause the video?! That is undesirable sometimes, why not "just" flush the buffer, which would effectively pause the video, AND fire the HTML5 video's
onwaitingevent, which lets you show a loader or something, but when the video is paused before the buffer is flushed, then theonwaitingevent is not fired at that point. So, why not just flush the buffer?!
Setting hls.currentLevel clears the buffer completely before loading the new level. ~Video pauses as a result of the buffer being empty, not because we pause it.~
Setting nextLevelonly clears the buffer after the end of the currently playing fragment. Use this if you want to switch levels without a pause.
Setting loadLevel does not clear the buffer. This is what hls.js uses in ABR mode when it needs to switch down.
You can see this behavior in the demo page with the timeline and quality-levels tabs open:

@robwalch Well, it actually doesn't pause just as a result of the buffer being empty, if it was so, then the onpause event wouldn't get fired, and instead, the onwaiting event would. So, that's why I believe it's actually being paused programmatically by hls.js.
Normally, when a video pauses due to lack of enough data, the paused property is false. But in the case of hls.js, when you change currentLevel, and the buffer is flushed, the onpause event is fired, and the paused property is true, and the onwaiting event is NOT fired, which it should, now, that can ONLY happen as a result of a programmatic pause() call by hls.js.
Take a look at this fiddle I just created: https://jsfiddle.net/fcd2mz37/
Play the video, before the whole video buffering is complete, seek to a place in the video where it's not yet buffered, and thus needs to be paused momentarily for buffering, and now check out the console, you can see the following:

P.S: It's true that the onpause event gets called before onwaiting when you seek to the unbuffered area, but that happens as a result of seeking, not as a result of the need to buffer. To see proof of that, go to a buffered area of the video this time, and you can see that the onpause event would be fired even then.
Please let me know if I'm missing something, thanks.
It does pause programmatically.
@phillipseamore Thanks for that.
If you would like to remove the programmatic pause, please submit a pull request.
I agree that allowing playback to stall rather than forcing a pause is preferred.
@robwalch Thanks.
May I ask why it was put there in the first place? Is there a specific reason why a programmatic pause is needed at that point? I'm assuming there was a rationale behind it.
@AradAral,
It's been there for over 5 years, and I could not find a commit that explained why it was added. I would guess the idea was that if you set hls.currentLevel, you would not want that to result in a stall.
In v1, we can document the change and suggest that external calls to hls.currentLevel be accompanied by either video.pause() or video.playbackRate = 0 if the intention is to perform a manual quality selection for some period where buffering can be counted as loading rather than stalling.
I went ahead and created the PR to test it out, and looks good to me. I don't think we need the nudging in immediateLevelSwitchEnd, so I'm happy to remove some code and flags from the stream-controller. https://github.com/video-dev/hls.js/pull/3338
I went ahead and created the PR to test it out, and looks good to me. I don't think we need the nudging in immediateLevelSwitchEnd, so I'm happy to remove some code and flags from the stream-controller. #3338
Great. Thanks a lot!
Makes more sense now.