Adaptive Bitrate (ABR) at the Player Level: Throughput, Buffer, and Hybrid
How players actually pick a rendition — throughput-based vs buffer-based (BOLA) vs hybrid ABR, segment switching, and how hls.js and dash.js decide.
A bitrate ladder is only potential energy. The thing that converts it into a
watchable stream is the ABR algorithm running inside the player, making a
fresh decision before nearly every segment: stay, climb, or drop. This article
goes a level deeper than the ABR overview —
into the mechanics of the decision loop, the three families of algorithms, and
how real players like hls.js and dash.js implement them. You can watch these
decisions unfold live in the play metrics tool.
The decision loop
ABR is a control loop that runs per segment. Roughly, for each upcoming segment the player:
- Estimates how much network throughput it expects to have.
- Reads how many seconds of media are currently buffered.
- Considers the cost of switching (a switch can mean discarding buffered data and re-fetching an init segment).
- Picks the variant that maximizes quality subject to "don't run the buffer dry."
Because the loop runs at segment granularity (every 2–6 seconds typically), the algorithm's job is to be both responsive to real change and stable against noise. Those two goals pull in opposite directions, which is why three distinct philosophies exist.
Throughput-based ABR
The classic approach: measure the download speed of recent segments, smooth it
(an exponentially weighted moving average, or a harmonic mean over the last few
segments), and pick the highest variant whose BANDWIDTH fits under that
estimate times a safety factor (often around 0.7–0.8).
- Strengths — reacts quickly to genuine bandwidth changes; intuitive; great at startup once a couple of segments have downloaded.
- Weaknesses — throughput estimates are noisy. On shared Wi-Fi or congested mobile, a single slow segment can trigger a needless downswitch. It also struggles with the "downward spiral": low quality → small segments → unreliable throughput measurement.
This is why a pure rate-based estimate is rarely used alone in modern players.
Buffer-based ABR
Buffer-based algorithms make the buffer occupancy the primary signal. The insight: the buffer is the integral of past throughput, so it is inherently smoother than instantaneous bandwidth. The player maps buffer level to a target quality — low buffer means play it safe, healthy buffer means it is safe to climb. BBA (Buffer-Based Algorithm) and Netflix's early buffer-based work popularized this.
- Strengths — robust to throughput noise; avoids the oscillation that plagues naive rate-based logic.
- Weaknesses — slow to react at startup when the buffer is nearly empty (it has no signal yet), so it usually needs a throughput-based startup phase.
BOLA
BOLA (Buffer Occupancy based Lyapunov Algorithm) is the best-known buffer-based
method and is built into dash.js and available in hls.js. It frames rendition
selection as a formal optimization — maximizing a utility (log of bitrate) minus
a rebuffering penalty — and solves it using only the current buffer level. In
practice BOLA leans toward higher, stable quality once the buffer is full and
gets more conservative as the buffer drains, with no explicit bandwidth estimate
required in steady state.
Hybrid ABR
Production players do not pick one philosophy; they blend them. A hybrid uses a throughput estimate to bound what is reachable, a buffer model to stay stable, and a switching penalty to suppress flapping. Approaches like MPC (Model Predictive Control) explicitly optimize over a short horizon of predicted future segments. The shared objective across all of them:
- Maximize delivered bitrate (quality).
- Minimize rebuffering (the single biggest QoE killer).
- Minimize the number and magnitude of switches (oscillation is visible and annoying).
Startup vs steady-state
ABR behaves differently in two phases:
- Startup — the buffer is empty and there is no throughput history. The player wants to start fast (low time-to-first-frame) without committing to a quality it cannot sustain. Common tactics: start on a conservative middle rung, or start low and aggressively probe upward as the first few segments confirm headroom. This is where buffer-based logic hands off to throughput-based logic.
- Steady-state — the buffer is full and the goal flips to maximizing quality while protecting the buffer. Here buffer-based and hybrid logic dominate, and switching penalties keep the picture stable.
The tension between a low startup time and a high startup quality is a real product decision, not just an algorithm tuning knob.
How hls.js and dash.js decide
- hls.js uses an
abrControllerwith an EWMA-based bandwidth estimator (separate fast and slow EWMAs for quick reaction plus stability). It picks the top level whose bitrate fits the estimate with a configurable factor (abrBandWidthFactor,abrBandWidthUpFactor), and it can abort and retry an in-flight segment at a lower quality if a download is clearly going to cause a stall. BOLA-style buffer logic is also available. - dash.js ships multiple switchable rules: a throughput rule, the BOLA buffer rule, and an "ABR Dynamic" mode that switches between them based on buffer state — BOLA in steady-state, throughput at startup and during low buffer. Shaka Player takes a comparably hybrid approach.
Both also cap upswitching to the viewport resolution and refuse variants whose
CODECS they cannot decode — decisions made directly from the master playlist
attributes covered in Key HLS Tags.
Helping the player decide: CMCD
ABR is a one-sided guess unless the player shares context. CMCD (Common Media Client Data) lets the player attach metrics — measured throughput, buffer length, requested object duration, and more — to each segment request so the CDN and origin can react. It does not change the algorithm, but it gives the delivery side the data to prefetch, steer, and diagnose. See it in action in the CMCD tool.
Tuning against real data
The only honest way to evaluate ABR is to measure the QoE you ship: startup time, rebuffer ratio, average bitrate, and switch frequency. A change that raises average bitrate but doubles rebuffering is a regression, not a win. Instrument playback with the play metrics tool, change one parameter at a time, and let the numbers — not a single test on your office Wi-Fi — tell you whether throughput, buffer, or hybrid serves your audience best. And remember: the best algorithm cannot rescue a poorly designed ladder.
Try it yourself
Reading about streaming is one thing — pull apart a real manifest, play a stream, and measure its QoE with the toolkit.
Browse all tools