Stop hls.js from flapping between quality levels on cellular (with abrSwitchInterval)
TL;DR ABR "flapping" is when your player hops between quality levels every few seconds on a jittery network, and each hop is a visible lurch. We'll detect it from LEVEL_SWITCHED events, then fix it in layers: widen the bandwidth-estimator memory, make upswitches earn their place, and cap the switch rate with abrSwitchInterval (new in hls.js 1.7). Config + a detection snippet you can paste in…
Stop HLS.js from Flapping Between Quality Levels on Cellular Networks
ABR "flapping" is a phenomenon where your video player rapidly switches between quality levels every few seconds on a spiky cellular network, causing a visible and frustrating lurch for the viewer. To combat this, we can leverage the LEVEL_SWITCHED events in hls.js and implement a multi-layered solution.
First, we need to detect the flaps using a flap monitor. By tracking level switches per minute of playback, we can identify when the flapping occurs. A high number of switches per minute, along with reversals in the direction of switching, indicates the presence of flapping. The flap monitor should be integrated into the hls.js player, using the latest version (1.7.x) and modern browser or node 20+ tooling.
Next, we can apply the first layer of the solution by widening the bandwidth-estimation memory in hls.js. By increasing both the fast and slow half-lives of the exponentially weighted moving average, we can create a more stable estimate that reflects the last several seconds instead of just the last one. This will help smooth out the short spikes in bandwidth on cellular networks and reduce the frequency of flapping.
The second layer involves making upswitches (increasing quality levels) more difficult to achieve. While going down in quality to avoid stalls is urgent, going up is optional. By lowering the up-switch factor (abrBandWidthUpFactor), the player will demand sustained headroom before switching to a higher quality rendition. This will prevent the player from jumping to a level it can't hold and reduce the likelihood of flapping.
Finally, we can apply the third layer by rate-limiting the switches with the abrSwitchInterval. This new feature in hls.js 1.7 sets a minimum time between automatic ABR level changes. By increasing the abrSwitchInterval (for example, to 3.0 seconds), we limit the number of switches that can occur within a given timeframe. This way, even if the bandwidth estimator detects a spike in data, it will be prevented from switching immediately, giving the player time to adjust and stabilize the quality level.
With these three layers in place, the player will have a longer memory and slower reflexes, allowing it to handle the variable cellular network conditions more effectively. The fix is straightforward to implement, and you can find a code snippet to get started at github.com/USER/hlsjs-abr-tuning. Just replace the existing hls.js player in your application and you'll be on your way to a smoother viewing experience on cellular networks.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.