Why this matters

If you ship a DASH player, you probably ship BOLA. The dash.js reference player has shipped BOLA as one of its two default ABR rules since 2017, and most commercial DASH stacks either fork dash.js directly or borrow its rule structure. If you use Shaka Player, BOLA is one of the configurable algorithms. If you have ever asked an engineer why your player "feels smooth on bursty Wi-Fi but slow to ramp up at the start", you are asking about BOLA. Product, engineering, and finance all sit downstream of the algorithm's behaviour: BOLA's choices determine how often viewers see quality changes, how often they rebuffer, and how many bits per viewer your CDN bill carries. Understanding it is no longer optional for anyone shipping streaming video at scale.

What "buffer-based" actually means

Every video player keeps a queue of pre-loaded chunks ahead of the playhead. That queue is called the buffer, and its depth is measured in seconds — not bytes, not megabits, but seconds of video that have been downloaded and decoded but not yet shown to the viewer. A typical player keeps somewhere between 8 and 60 seconds in the buffer; the exact size depends on the protocol (low-latency HLS targets 1–3 seconds, classic HLS targets 30 seconds, DASH on-demand often targets 60 seconds).

A throughput-based ABR algorithm picks the next chunk's quality by measuring how fast the network has been delivering bytes. A buffer-based ABR algorithm picks the next chunk's quality by looking at how many seconds of buffer the player currently holds. The reasoning is mechanically simple: a deep buffer means the player can afford to download a heavier chunk because there are many seconds of pre-loaded video to absorb a network dip; a shallow buffer means the player must shrink the chunk size to keep playback from starving.

The throughput-based view trusts the recent past. The buffer-based view trusts the present state. When the recent past is a poor predictor — bursty Wi-Fi, mobile handoffs, satellite weather — the buffer-based view wins.

A tiny example before the math

Set up: a six-rung ladder of 300, 750, 1500, 2500, 4000, 6000 kbps, 4-second segments, a viewer whose player buffers up to 30 seconds. The viewer has just started watching. Buffer = 0 s.

A throughput-based algorithm has no measurements yet, so it picks a safe-ish middle rung — say 750 kbps — and starts downloading. A buffer-based algorithm looks at the buffer and says: buffer is empty, I am one bad chunk away from a rebuffer, so I pick the lowest rung, 300 kbps. The first chunk arrives fast on the 300 kbps rung; the buffer jumps to 4 s; the algorithm consults its rule again and now picks 750 kbps. The second chunk arrives; buffer is now 8 s; the rule picks 1500 kbps. By the time the buffer reaches 18 s, the rule picks 2500 kbps; at 25 s, it picks 4000 kbps; at the maximum buffer, it picks 6000 kbps.

The shape of that climb — from the bottom of the ladder to the top, paced by buffer depth, with each rung "unlocking" at its own threshold — is the entire essence of buffer-based ABR. Everything else in this article is detail.

Pipeline diagram showing the BOLA decision loop: measure buffer level, compute utility-minus-penalty, pick the rung that maximises the objective, download the chunk, repeat Figure 1. One decision per segment. BOLA reads the current buffer level, evaluates a utility-minus-penalty score for every rung, picks the rung with the highest score, downloads it.

Where BOLA fits in the family

Two papers from 2014 laid the conceptual ground for buffer-based ABR. BBA, the Buffer-Based Algorithm of Huang, Johari, McKeown, Trunnell, and Watson at Stanford and Netflix, introduced a simple piecewise-linear mapping from buffer level to bitrate: at buffer below 5 s, pick the lowest rung; at buffer above 25 s, pick the highest; in between, linearly interpolate. BBA was the first algorithm to show — with production Netflix data — that a buffer-only algorithm could beat a sophisticated throughput estimator on user-visible quality of experience.

BOLA arrived in 2016 with the same intuition but a mathematical backbone. Spiteri, Urgaonkar, and Sitaraman framed the bitrate selection problem as a utility-maximisation problem — the player wants to maximise the cumulative quality the viewer sees, subject to the constraint that the buffer cannot underflow (because underflow means rebuffer) and the player has only the current buffer state as its observable signal. They then applied Lyapunov optimization, a technique borrowed from queueing theory and stochastic network control, to convert that long-horizon optimisation into a simple per-segment decision rule. The result is the only ABR algorithm to date that comes with a proof: BOLA's time-averaged utility is provably within an O(1/V) gap of the offline optimum, for a control parameter V that scales with the buffer size.

The paper went on to win the ACM SIGMETRICS test-of-time recognition in subsequent years and has been cited well over a thousand times. More important for an engineer, dash.js adopted it as the default buffer-based rule and shipped a follow-up paper, From Theory to Practice (ACM Transactions on Multimedia Computing, Communications, and Applications, 2019), describing the practical engineering corrections needed to make BOLA-BASIC behave well on the open internet.

The math, kept honest and small

Skip this section if you only need the engineering picture. Read it if you actually have to debug a BOLA implementation.

The utility function

For each rung m in the ladder, BOLA defines a utility v_m. The utility is a number that measures "how good is this rung from the viewer's perspective". The original paper uses v_m = ln(S_m / S_1) — the natural logarithm of the rung's segment size divided by the lowest rung's segment size. Because segment size scales with bitrate, this is equivalent to v_m = ln(b_m / b_1) where b_m is the rung's encoded bitrate.

Why logarithmic? Two reasons. First, the visible quality difference between 400 kbps and 800 kbps is much larger than the difference between 4,000 kbps and 4,400 kbps, even though both are a 400 kbps increment. A log function captures that diminishing return naturally. Second, log is what's known as a proportional-fair utility — it produces fair allocations across viewers competing for the same resource. The paper proves that any utility function nondecreasing in segment size works for BOLA's correctness, but log is the empirically pleasant choice.

Worked example. Ladder 300, 750, 1500, 2500, 4000, 6000 kbps. Utilities relative to the lowest rung:

  • Rung 1 (300): ln(300/300) = 0.00
  • Rung 2 (750): ln(750/300) = 0.916
  • Rung 3 (1500): ln(1500/300) = 1.609
  • Rung 4 (2500): ln(2500/300) = 2.120
  • Rung 5 (4000): ln(4000/300) = 2.590
  • Rung 6 (6000): ln(6000/300) = 2.996

Notice the curve flattens. Going from rung 1 to rung 2 buys 0.916 units of utility; going from rung 5 to rung 6 buys only 0.406. The viewer cares much more about the first half of the ladder than the second.

The per-segment decision rule

At each segment, BOLA picks the rung m that maximises:

score(m) = (V · v_m + γ · p) / S_m  −  Q / S_m

Where:

  • V is the Lyapunov control parameter — a single tuning constant that trades off utility against buffer occupancy. Higher V favours quality; lower V favours a fuller buffer. In dash.js, V is chosen to match the buffer size.
  • v_m is the rung's utility (from above).
  • p is a constant representing the cost of rebuffering, also called the "no-rebuffer reward".
  • γ (gamma) is a weight on p. The paper sets it to a value that makes the algorithm stable; dash.js fixes a value derived from the buffer target.
  • S_m is the size of rung m's chunk (bytes, or kilobits, or seconds — units cancel as long as the scaling is consistent).
  • Q is the current buffer level expressed in the same units as the size — typically seconds of video.

The whole thing reduces to a simple competition: at low buffer levels, the −Q/S_m term dominates, which favours small chunks (low rungs). At high buffer levels, the V·v_m / S_m term dominates, which favours high-utility chunks (high rungs). The transition between regimes happens at buffer thresholds determined by the ladder structure.

You can read off the buffer thresholds geometrically. Rung m becomes preferred over rung m−1 at a buffer level you can solve from setting score(m) = score(m−1). The result is a series of thresholds Q_2 < Q_3 < ... < Q_M: below Q_2 the algorithm picks rung 1; between Q_2 and Q_3 it picks rung 2; and so on. dash.js exposes these thresholds in its BolaRule settings; the official documentation shows an example with thresholds at 5 s and 10 s for a three-rung ladder.

The proof, in one sentence

Lyapunov optimization tells you that if you greedily maximise score(m) at each step, the time-averaged utility over a long horizon is within O(1/V) of the best possible offline policy. As V grows (which corresponds to a larger buffer), the gap shrinks. The cost of a larger V is more "drift" in the buffer — i.e., the buffer wanders further from its target before being corrected. This is the fundamental BOLA trade-off, and it is the only mathematically tight ABR trade-off you will find in print.

The four practical variants

The original BOLA paper specified the algorithm in the abstract. Real deployments needed engineering refinements, which produced a family of variants. dash.js's current production rule is closest to BOLA-FINITE, with elements of BOLA-O and BOLA-U merged in.

BOLA-BASIC

The paper's baseline. Optimises utility minus the rebuffer-penalty term using the Lyapunov rule above. Assumes infinite video length and infinite buffer. Useful for theory; underperforms in practice because finite videos end (the buffer empties on purpose at the end of playback), finite buffers cap out (the algorithm stops climbing when the buffer is full), and CDN throughput estimates can override the buffer signal during a chunk download.

BOLA-FINITE

Adapts BOLA-BASIC to the real world by introducing dynamic buffer size and download abandonment. Dynamic buffer size means the effective buffer cap changes as the video nears its end — the algorithm allows the buffer to drain toward zero in the final seconds instead of holding a full buffer for content that will not exist. Download abandonment means that if the network has slowed mid-chunk and continuing the download would rebuffer, the player aborts the chunk and re-requests a lower rung. BOLA-FINITE is the variant that dash.js most closely follows.

BOLA-O

The "O" stands for oscillation control. Plain BOLA can flip between two adjacent rungs when the buffer hovers exactly at a threshold. BOLA-O adds a small hysteresis term that prevents the algorithm from switching rungs unless the buffer has moved a meaningful distance past the threshold. The trade-off: slightly lower average quality, much smoother user experience.

BOLA-U

The "U" stands for the variant that occasionally picks one rung up from the bandwidth-justified pick when the buffer is healthy. BOLA-U targets the case where the network can deliver slightly more than the current rung's bitrate; without the upward bias, BOLA-BASIC will stay on the conservative rung indefinitely. BOLA-U produces higher average quality on stable networks at the cost of a small increase in switch rate.

dash.js's BolaRule blends BOLA-FINITE's abandonment, BOLA-O's hysteresis, and BOLA-U's upward bias in one practical algorithm. The 2019 From Theory to Practice paper is the canonical reference for what dash.js actually ships.

A worked example with numbers

Set up: same ladder as before (300, 750, 1500, 2500, 4000, 6000 kbps), 4-second segments, buffer capacity 30 s, V chosen by dash.js's default rule for this buffer size, thresholds derived to land approximately at Q_2 = 4 s, Q_3 = 10 s, Q_4 = 16 s, Q_5 = 22 s, Q_6 = 27 s.

Segment 1. Buffer = 0 s. Algorithm picks rung 1 (300 kbps). The 4-second segment is 300 × 4 / 8 = 150 KB. On a 3 Mbps line it arrives in 150 × 8 / 3000 = 0.4 s. Buffer after = 4 − 0.4 = 3.6 s.

Segment 2. Buffer = 3.6 s. Below Q_2 = 4. Algorithm picks rung 1 again. Chunk arrives in 0.4 s. Buffer = 3.6 + 4 − 0.4 = 7.2 s.

Segment 3. Buffer = 7.2 s. Between Q_2 = 4 and Q_3 = 10. Algorithm picks rung 2 (750 kbps). Chunk size = 750 × 4 / 8 = 375 KB. Download time = 375 × 8 / 3000 = 1.0 s. Buffer = 7.2 + 4 − 1.0 = 10.2 s.

Segment 4. Buffer = 10.2 s. Just above Q_3 = 10. Algorithm picks rung 3 (1500 kbps). Chunk = 1500 × 4 / 8 = 750 KB. Download = 750 × 8 / 3000 = 2.0 s. Buffer = 10.2 + 4 − 2.0 = 12.2 s.

Segment 5. Buffer = 12.2 s. Still between Q_3 and Q_4. Picks rung 3 again. Buffer = 12.2 + 4 − 2.0 = 14.2 s.

Segment 6. Buffer = 14.2 s. Still below Q_4 = 16. Picks rung 3. Buffer = 14.2 + 2 = 16.2 s.

Segment 7. Buffer = 16.2 s. Above Q_4. Picks rung 4 (2500 kbps). Chunk = 1250 KB. Download = 1250 × 8 / 3000 = 3.33 s. Buffer = 16.2 + 4 − 3.33 = 16.87 s. (Note: the algorithm just barely holds the new rung; if the network drops, the buffer-floor logic kicks in.)

The behaviour pattern is unmistakable: slow, deliberate climb up the ladder, paced by how full the buffer gets, with each rung holding until the buffer crosses the next threshold. The viewer sees the first 8 seconds at low quality, then a stepped improvement up to the target rung. The whole climb takes 20–30 seconds.

This is the BOLA signature. It is also why throughput-based ABR feels "snappier" at the start (it picks higher rungs immediately) and BOLA feels "smoother" once it gets going (it does not panic on network dips because the buffer absorbs them).

Where BOLA wins

Four deployment shapes match BOLA's strengths.

Shape 1 — Bursty networks. Home Wi-Fi, mobile data, satellite, public Wi-Fi. Networks where the throughput moment-to-moment can swing 5–10× in either direction. The buffer absorbs the swing; BOLA does not react to it. A throughput-based algorithm on the same network oscillates the rung visibly. The viewer-visible difference shows up in the switch rate metric — switches per minute — which a buffer-based algorithm holds well below 0.5/min where a throughput-based algorithm can climb past 2/min on the same trace.

Shape 2 — Long-form VoD. Movies, TV episodes, lectures. Content where the buffer has time to fill (30 seconds or more) and the algorithm has time to climb the ladder. The 20–30 second startup-to-peak path is invisible to the viewer because the algorithm has reached its peak rung by minute one and stays there. For 30-second product videos, BOLA is overkill; for 90-minute features, it is the right tool.

Shape 3 — Low-latency tolerance. Where the player can afford a deep buffer (more than 10 seconds) without sacrificing the use case. Most VoD and most "near-live" use cases qualify. Live conferencing and live sports — where the latency budget is 1–4 seconds — give the buffer no room to absorb anything and BOLA is forced into a too-shallow operating regime.

Shape 4 — When ladder design is good. BOLA's behaviour depends on the ladder shape. A ladder with too few rungs near the top makes the algorithm flip between the top two rungs on small network changes. A ladder with too many redundant rungs at the bottom wastes the climb. The per-title encoding ladders described in Building a Bitrate Ladder are well-suited to BOLA; a fixed 6-rung ladder for every title less so.

Where BOLA loses

Five failure modes account for almost every production complaint about BOLA. Each has a fix.

Failure 1 — Cold start. BOLA starts at the buffer floor and walks up. On a stable 100 Mbps line, a viewer waits 20+ seconds to reach the highest rung. That is unacceptable on short content and irritating on long content's opening. Fix: dash.js's combined algorithm hands the first 4–6 segments to its InsufficientBufferRule and ThroughputRule instead, letting the player ramp up faster, then switches to BolaRule once the buffer is full. The 2019 paper documents this hand-off in detail.

Failure 2 — Short videos. A 20-second clip ends before BOLA has reached the peak rung. The viewer sees the entire clip at low or middle quality. Fix: increase the bottom-rung quality (raise the floor of the ladder), or use BOLA-U to push the algorithm one rung above the buffer-justified pick when the buffer is healthy. For very short content, switching to a throughput-based or hybrid algorithm is the cleaner answer.

Failure 3 — CMAF chunked transfer and low-latency targets. With a 2-second target buffer (low-latency HLS, LL-DASH), BOLA's threshold structure forces it to live entirely in the bottom of the ladder. The fix is to switch algorithms — the LL-HLS Deep Dive and LL-DASH and CMAF Chunked articles describe alternative algorithms (L2A, LoL+) that dash.js ships for these scenarios.

Failure 4 — Bandwidth-capped networks. BOLA can pick a rung whose bitrate exceeds the actual available throughput, because it reads from the buffer, not from the network. The chunk takes longer to arrive, the buffer drains, the next iteration picks a smaller chunk. This self-corrects but produces an oscillation. Fix: dash.js's combined rule has the ThroughputRule veto BolaRule's pick when the rule reports throughput too low to deliver the chosen chunk on time.

Failure 5 — Manifest changes mid-session. If the ladder changes during a session (an ABR sidecar adjusts the ladder, or a live event re-encodes), BOLA's pre-computed thresholds become stale. Fix: recompute thresholds whenever the player consumes a new manifest. dash.js does this automatically; some forks do not.

Three-panel diagram showing the three deployment shapes where BOLA wins versus the three where it loses: bursty networks vs short content; long-form VoD vs low-latency live; ladder-fit content vs cold-start Figure 2. The three deployment shapes BOLA was designed for, and the three it stumbles in.

Tuning levers — the knobs that actually matter

If you ship a BOLA-based player and need to tune it, three knobs do most of the work.

Knob 1 — Buffer target. The dash.js setting streaming.buffer.bufferToKeep and the related target define how deep the buffer goes. A larger target gives BOLA more headroom and lets it climb higher; a smaller target shortens the climb but increases rebuffer risk. Default 30 s for VoD, 12 s for live. Below 8 s, BOLA stops behaving like itself.

Knob 2 — V (the Lyapunov parameter). Exposed in dash.js as part of the BolaRule internals, not directly as a setting. Higher V favours quality (algorithm climbs more aggressively); lower V favours buffer stability. dash.js derives V from the buffer target; rarely touch this directly unless you have run controlled A/B tests.

Knob 3 — Hysteresis. Whether the algorithm switches rungs at exactly the threshold or only after the buffer moves a meaningful distance past it. The BOLA-O variant ships a small hysteresis by default. Larger hysteresis reduces switches per minute; smaller hysteresis tracks the network more tightly.

The table below shows defaults for three common deployments.

DeploymentBuffer targetV regimeHysteresisCompanion rules
VoD on residential fibre30 sdash.js defaultsmallThroughputRule + InsufficientBufferRule
Live event, classic latency12 sdash.js default × 0.8mediumThroughputRule + AbandonRequestRule
Mobile-first OTT app20 sdash.js defaultmediumThroughputRule + Insufficient + Abandon
Below 8-second buffers, BOLA is the wrong algorithm and L2A or LoL+ should take over.

How BOLA compares with the other ABR families

Buffer-based is one of four ABR families. Their trade-offs in one table.

FamilyPrimary signalStrengthsWeaknessesWhere it ships
Throughput-basedRecent download rateSimple, fast start, predictableJittery on bursty networks, blind to buffer statehls.js, iOS native, older dash.js, most smart TVs
Buffer-based (BOLA)Buffer depth in secondsSmooth, robust to network jitter, mathematically groundedSlow cold start, blind to bandwidth, requires deep bufferdash.js (default since 2017), Shaka Player option
Hybrid (MPC, Festive)Both, plus utility functionBest aggregate user QoE in productionHard to debug, large parameter spaceNetflix, YouTube, premium streamers
Neural (Pensieve, Comyco)Learned policy from trainingBest in benchmarksHeavy to train, retrains needed, opaqueResearch, two or three top streamers
The pillar ABR Streaming Explained covers all four in context. The companion articles dig in: Throughput-Based ABR Algorithms, Hybrid ABR (MPC, Festive), and Neural ABR (Pensieve, Comyco).

Common mistakes when shipping a BOLA-based player

Pitfall 1 — Disabling the ThroughputRule. Some teams switch on BolaRule and turn off all other rules thinking "BOLA is enough". In dash.js, BolaRule was designed to coexist with ThroughputRule, InsufficientBufferRule, and AbandonRequestRule. The other rules veto BolaRule's pick when the network is obviously slower than the buffer signal suggests. Without them, BOLA can climb into a rebuffer on a steadily degrading line.
Pitfall 2 — Tuning V without understanding the ladder. Cranking V higher does not "make the algorithm pick higher rungs always". It widens the gap between buffer thresholds, which makes the climb slower at the bottom and the descent slower at the top. Test V changes with the actual ladder you ship, not with a textbook ladder.
Pitfall 3 — Confusing BOLA with BBA. BBA is a piecewise-linear buffer-to-bitrate map with hand-tuned breakpoints. BOLA is a utility-maximisation rule that derives the breakpoints from a Lyapunov objective. The two have similar shapes and similar names in the literature; do not assume a paper about "BBA" describes what dash.js ships.
Pitfall 4 — Ignoring BolaRule's placeholder buffer. dash.js implements a "placeholder buffer" that compensates for buffer depletion outside BolaRule's control (e.g., the player paused, or a track switch drained the buffer). The placeholder is not real video. If the algorithm makes choices that lead to rebuffer, InsufficientBufferRule cleans up. Removing or misunderstanding the placeholder is a frequent source of "the algorithm decided to pick the top rung with zero seconds of buffer" bug reports.
Pitfall 5 — Benchmarking BOLA on a 5-second clip. BOLA was designed for content where the buffer has time to fill. Short-form benchmarks make it look worse than it is. Benchmark on at least 5-minute clips, ideally with mixed network conditions, to see its real shape.

Where Fora Soft fits in

We have shipped video products since 2005, and we have inherited many DASH players where the team enabled BolaRule, disabled the other rules, and then spent a quarter wondering why mobile viewers rebuffered. In e-learning we keep BOLA as the default because lecture viewers have deep buffers and tolerate the slow climb at the start. In OTT we keep BOLA for the main viewing window and switch to L2A for trailers and short clips. In telemedicine we move off BOLA entirely — the latency budget makes the buffer too shallow for BOLA's geometry to work. The right algorithm depends on the use case's buffer headroom, not on what is currently popular in conference talks.

What to read next

CTA

  • Talk to a streaming engineer — book a 30-minute scoping call with our streaming team.
  • See our case studies — read how we built ABR for OTT, e-learning, telemedicine, and surveillance clients.
  • Download: BOLA Tuning & Pitfalls Sheet — a one-page reference for the three knobs, the four BOLA variants, and the five common failure modes. Download the tuning sheet.

References

  1. K. Spiteri, R. Urgaonkar, R. K. Sitaraman — BOLA: Near-Optimal Bitrate Adaptation for Online Videos, IEEE INFOCOM 2016 (extended journal version: IEEE/ACM Transactions on Networking, vol. 28, no. 4, pp. 1698–1711, 2020). The original BOLA paper. https://arxiv.org/abs/1601.06748
  2. K. Spiteri, R. Sitaraman, D. Sparacio — From Theory to Practice: Improving Bitrate Adaptation in the DASH Reference Player, ACM Transactions on Multimedia Computing, Communications, and Applications, 2019. The paper that documents what dash.js actually ships, including the BOLA + ThroughputRule hand-off, abandonment, and placeholder buffer. https://dl.acm.org/doi/10.1145/3336497
  3. T.-Y. Huang, R. Johari, N. McKeown, M. Trunnell, M. Watson — A Buffer-Based Approach to Rate Adaptation: Evidence from a Large Video Streaming Service, ACM SIGCOMM 2014. The Netflix BBA paper that founded the buffer-based family.
  4. ISO/IEC 23009-1:2022 — Information technology — Dynamic adaptive streaming over HTTP (DASH) — Part 1: Media presentation description and segment formats. Fifth edition. The controlling DASH standard the BOLA player consumes. https://www.iso.org/standard/83314.html
  5. IETF RFC 8216 — HTTP Live Streaming, R. Pantos and W. May, May 2017. The HLS spec; BOLA-style rules apply to HLS players too via hls.js extensions and Shaka Player. https://www.rfc-editor.org/rfc/rfc8216
  6. Apple — HTTP Live Streaming (HLS) Authoring Specification for Apple Devices, revision 2025-09. §2 (rendition ladder guidance) directly shapes how a BOLA-style algorithm climbs. https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices
  7. DASH Industry Forum — dash.js BolaRule documentation, 2024 revision. The reference for how BOLA is configured in production dash.js. https://dashif.org/dash.js/pages/usage/abr/bola-rule.html
  8. DASH Industry Forum — DASH-IF Implementation Guidelines: Restricted Timing Model (v5.x, 2024). The DASH-IF profile that clarifies ISO/IEC 23009-1's ambiguities on player adaptation. https://dashif.org/guidelines
  9. F. Y. Yan, H. Ayers, C. Zhu, S. Fouladi, J. Hong, K. Zhang, P. Levis, K. Winstein — Implementing BOLA-BASIC on Puffer: Lessons for the Use of SSIM in ABR Logic, Stanford Puffer report, 2020. https://puffer.stanford.edu/bola/
  10. ISO/IEC 23000-19:2024 — Information technology — Multimedia application format (MPEG-A) — Part 19: Common media application format (CMAF) for segmented media. Fourth edition. The CMAF chunked-transfer behaviour that shapes BOLA's low-latency limits. https://www.iso.org/standard/85623.html
  11. Bitmovin — Video Developer Report 2024. Survey data on algorithm-family deployment share. https://bitmovin.com/video-developer-report
  12. Conviva — State of Streaming Q4 2024. Industry benchmarks for rebuffer ratio and start-up time that BOLA drives directly. https://www.conviva.com/state-of-streaming