Buffer-based ABR: BOLA подробно

Автор: Николай СапуновОбновлено: август 202617 мин чтения
Содержание статьи +

TL;DR

BOLA – это buffer-based ABR-алгоритм: при выборе следующего уровня качества видео он ориентируется не на измеренную пропускную способность сети, а на то, сколько секунд видео уже накоплено в буфере плеера. Идея заимствована из теории управления: каждое решение формулируется как онлайн-оптимизация по Ляпунову, которая доказуемо приближается к оптимальной утилитарной функции «больше качества, меньше ребуферизации» с погрешностью, обратно пропорциональной размеру буфера. С 2017 года BOLA интегрирован в dash.js как часть гибридной стратегии вместе с throughput-based-правилом и используется по умолчанию в плеерах Akamai, BBC, Orange, CBS и десятков других. Эта статья объясняет, откуда берётся формула BOLA, как её может понять практический инженер, чем отличаются BOLA-BASIC, BOLA-O и BOLA-U, где алгоритм работает особенно хорошо, а где – даёт сбой, и как настроить гибридный режим в dash.js, чтобы получить от BOLA максимум, избегая при этом типичных ловушек на старте.

Кому и зачем это нужно

Если вы выпускаете стриминговый продукт на DASH или HLS через MSE – а это почти любой веб-плеер, кроме нативного iOS Safari, – BOLA уже работает у вас под капотом, хотите вы того или нет. dash.js включает его по умолчанию начиная с версии 2.5; hls.js использует собственную версию buffer-based-логики, скопированную из семейства BOLA. Команды, которые «не выбирали ABR-алгоритм», на самом деле выбрали BOLA с параметрами по умолчанию. Это создаёт две основные проблемы. Первая – необъяснимое поведение плеера: «почему он переключился на более низкое качество, хотя сеть свободна?» – потому что уровень буфера опустился ниже установленного порога. Вторая – упущенные возможности настройки: BOLA имеет несколько параметров, позволяющих менять поведение от «агрессивного, ориентированного на качество» до «осторожного, минимизирующего ребуферизацию», и команды, не знающие об этих настройках, теряют 10–20% QoE.

Понимание BOLA отличает команду, способную улучшить метрики ABR уже на следующей неделе, от той, что годами полагается на дефолты. Продакт, аналитика и видеоинженеры – все зависят от этих параметров. Эта статья даёт ментальную модель, в которой формула BOLA становится понятной без математической подготовки, и объясняет, какие рычаги в dash.js настраивать и в каком направлении.

Идея одним абзацем

Представьте, что плеер – это водитель: он едет по шоссе и видит впереди указатель «АЗС через N километров». Если в баке много бензина (большой буфер) – водитель может ехать быстро, рискнуть, проскочить заправку и поехать дальше. Если бензина мало (буфер просел) – пора замедлиться и заправиться побыстрее, не до жиру. BOLA делает то же самое, только вместо бензина – секунды накопленного видео, а вместо скорости – битрейт следующего сегмента. Чем больше буфер, тем смелее можно брать высокую ступень; чем меньше – тем осторожнее. Никаких измерений сети не нужно: буфер – это интегральная картина того, как сеть вела себя за последнее время. Если буфер растёт, значит, сеть быстрее, чем мы скачиваем; если падает – медленнее. BOLA читает эту картину и переводит её в одно число: индекс качества, который надо взять следующим.

Это семейство алгоритмов называется buffer-based ABR, в отличие от throughput-based ABR, который напрямую измеряет скорость сети. Главное отличие в том, что BOLA доказуемо оптимален в определённом смысле: математически показано, что он со временем сходится к наилучшему возможному выбору, даже не зная заранее характеристик сети.

Откуда взялась BOLA

Алгоритм был опубликован в 2016 году Кеваном Спитери, Рамешем Ситараманом (Akamai, UMass Amherst) и Викрамом Сваминатаном в работе BOLA: Near-Optimal Bitrate Adaptation for Online Videos, представленной на конференции IEEE INFOCOM. 1 В 2019 году вышла полная журнальная версия в журнале IEEE/ACM Transactions on Networking. Авторы поставили задачу следующим образом: что, если ABR-алгоритм рассматривать как задачу онлайн-оптимизации, в которой плеер должен максимизировать долгосрочную «полезность» – взвешенную сумму качества выбранных сегментов за вычетом штрафа за ребуферизацию? И решить эту задачу не с помощью эвристик, а формально – с использованием метода Ляпунова, инструмента из теории стохастического управления, специально разработанного для онлайн-задач, в которых будущее неизвестно.

Техника Ляпунова – это математический приём, придуманный для задач вроде «как балансировать очередь сообщений в сети, не зная заранее, сколько их придёт». Она позволяет свести многомерную задачу «оптимизируй сумму действий на бесконечном горизонте» к одношаговому решению: «на каждом шаге максимизируй фиксированное выражение, зависящее только от текущего состояния». Для ABR это означает: на каждом сегменте плеер вычисляет одну простую формулу и сразу определяет, какой битрейт выбрать. Никакого прогнозирования состояния сети, никаких сложных оптимизационных циклов внутри плеера.

Авторы доказали два свойства. Во-первых, BOLA сходится к оптимальной утилите с погрешностью O(1/V), где V – параметр алгоритма, связанный с целевым размером буфера: удвоение V уменьшает разрыв с оптимумом вдвое, но ценой увеличения размера буфера. Во-вторых, при некоторых разумных условиях средняя ребуферизация ограничена сверху явной формулой, также зависящей от V. Такие гарантии редки для практических сетевых алгоритмов – наследники throughput-based подходов подобного не предлагают.

В 2017 году один из авторов работал с командой dash.js, и BOLA была интегрирована как стандартная стратегия в эталонный плеер DASH. С тех пор она доступна в продакшене у всех, кто использует dash.js – а это, по оценке самих разработчиков dash.js, около 80% MPEG-DASH-плееров в продакшене.

Формула BOLA читается за минуту

Концептуально BOLA на каждом сегменте выполняет одну операцию: для каждого уровня качества m в «лесенке» (1, 2, 3, …, M) вычисляет одно значение – «цену» этого уровня – и выбирает уровень с наибольшей ценой. Формула цены:

score(m) = (V × utility(m) + V × γ × p − buffer_level) / size(m)

Это выглядит пугающе – разберём по частям.

  • size(m) – размер сегмента уровня m в секундах видео, делённый на сжатый размер в байтах (или, проще говоря, битрейт уровня; возможны вариации формы). Знаменатель показывает, «сколько мы платим за полосу пропускания за этот выбор».
  • utility(m) – функция полезности уровня m, обычно log(bitrate_m / bitrate_min). Чем выше уровень, тем больше полезность, но рост логарифмический: переход с 1 Мбит/с на 2 Мбит/с зритель воспринимает сильнее, чем с 5 на 6 Мбит/с. Логарифм отражает закон Вебера–Фехнера.
  • V – основной параметр настройки. Большое значение V означает, что алгоритм больше ценит качество и готов рисковать уровнем буфера; малое V – алгоритм действует осторожнее, поддерживает высокий буфер и реже допускает ребуферизацию.
  • γ × p – штраф за «опасное состояние» (ребуферизацию); γ – вес штрафа, p – параметр модели.
  • buffer_level – текущий уровень буфера в секундах.

Главная интуиция: числитель показывает, «насколько сильно мы хотим выбрать этот уровень», а знаменатель – «сколько секунд буфера мы готовы потратить на него». Когда buffer_level большой, числитель уменьшается → даже высокий уровень получает низкий балл → алгоритм становится осторожным и склонен выбирать средний уровень, избегая рисков. Когда buffer_level мал, числитель растёт → высокие уровни получают очень высокий балл, и алгоритм выбирает максимум, чтобы быстро восстановить буфер.

Но «момент истины» – это обратная зависимость от buffer_level: чем больше буфер, тем меньше склонность выбирать высокие уровни. Это противоречит интуиции «много буфера = можно рисковать» и именно это удивляет инженеров, впервые сталкивающихся с BOLA. Почему так?

Потому что BOLA оптимизирует долгосрочную утилиту, а не текущий шаг. При полном буфере алгоритм может позволить себе пропустить пару высококачественных сегментов и выбрать средние – он знает, что времени достаточно, и за следующие 10 секунд сеть всё равно предоставит возможность повысить качество без риска ребуферизации. При низком уровне буфера стратегия «выбрать средний сегмент, играть в безопасность» ведёт к ребуферизации: такой выбор экономит биты, но почти не увеличивает запас времени. Парадоксально, но в режиме низкого буфера BOLA выбирает высокий уровень качества – чтобы быстро загрузить много секунд видео и восстановить буфер. Точнее: при медленной сети высокий уровень не удастся скачать быстрее, чем низкий, но если сеть быстрая, он загрузится за то же время, что и низкий, и при этом обеспечит лучшее качество – а при медленной сети низкий уровень заполнит буфер быстрее.

Полное доказательство того, что эта формула приближается к оптимуму, занимает в работе несколько страниц, посвящённых математике стохастического управления. На практике достаточно знать: BOLA – это «функция от уровня буфера», и весь её смысл заключается в том, как именно устроена эта зависимость.

Рисунок 1. Поведение BOLA в зависимости от уровня буфера. При буфере ниже минимального алгоритма выбирает высокий уровень – других вариантов восстановить буфер нет; при уровне выше целевого – осторожно выбирает средний, оптимизируя долгосрочное качество.

Три варианта BOLA: BASIC, FINITE, BOLA-O

В работе Спитери и соавторов 2016 года описано несколько вариантов BOLA, и важно понимать, что в dash.js и других плеерах используется не «чистый теоретический BOLA», а его адаптация.

BOLA-BASIC

Самая простая версия. Использует описанную выше формулу цены без модификаций. Доказуемые гарантии оптимальности – именно для этой версии. Однако у BASIC в практическом плеере есть два слабых места: при пустом буфере (при запуске или после seek) формула приводит к делению на малое число и склонна выбирать слишком высокую ступень; при пустом буфере и медленной сети это вызывает длительную загрузку первого сегмента и потенциальную ребуферизацию сразу после старта.

BOLA-FINITE

Расширяет BASIC, обеспечивая корректную работу с конечным размером буфера. В оригинальной формулировке BOLA предполагается бесконечный буфер – чисто теоретическое допущение. На практике плеер ограничивает его объёмом 30–60 секунд; FINITE вводит ограничение, предотвращающее ситуацию, когда алгоритм пытается загрузить сегмент, но буфер уже заполнен. Дополнительная сложность на практике – не запускать ABR-движок, а блокировать загрузку до освобождения места в буфере; FINITE интегрирует такую блокировку прямо в формулу принятия решения.

BOLA-Optimization (BOLA-O)

Самый практичный вариант, который используется в dash.js, – BOLA-O. Он добавляет к FINITE второе важное изменение: избегание переключений вниз с потерей буфера. Чистый BOLA может за один шаг перейти с уровня 5 на уровень 2 – зритель это видит как заметный провал качества, а чаще всего он и вовсе не нужен. BOLA-O проверяет: если снижение уровня требуется лишь из-за временного скачка буфера, лучше отложить его на один сегмент и проверить ситуацию снова. Такой подход сглаживает колебания и устраняет «вспышки» низкого качества при стабильном соединении.

В документации dash.js используется именно BOLA-O, и далее мы будем называть его просто «BOLA».

Три места, где BOLA сияет

Стабильные сети с большим буфером. Когда зритель подключён к обычной домашней Wi-Fi сети с буфером 20+ секунд, BOLA устойчиво удерживает самую высокую доступную ступень качества, которую поддерживает сеть, и почти никогда не опускается вниз. Throughput-ориентированный ABR в таких условиях может слабо колебаться около границы ступеней (например, между 1080p и 720p, когда сеть обеспечивает 5,2 Мбит/с при битрейтах 4 и 6 Мбит/с). BOLA, благодаря своей связи с уровнем буфера, остаётся на нижней из двух – ведь выбор верхней не приносит долгосрочной выгоды, а риск повторной буферизации возрастает.

VOD-контент с длинной сессией. На полнометражном кино с буфером 60+ секунд BOLA демонстрирует почти идеальное стационарное поведение: одна выбранная ступень, отсутствие переключений, полная отсутствие ребуферизации. Доказанные гарантии устойчивости по Ляпунову работают именно в таких условиях – при длинном горизонте и стабильном распределении скорости.

Сети с короткими провалами и быстрым восстановлением. Когда сеть на 2–3 секунды падает с 6 до 1 Мбит/с, а затем восстанавливается, throughput-ориентированный ABR может отреагировать «панически»: резко переключиться на 2–3 ступени ниже и затем 10 секунд медленно восстанавливаться. BOLA, благодаря буферу, спокойно переживает короткий сбой – ведь уровень буфера остаётся высоким, и алгоритм понимает, что один-два медленных сегмента не являются катастрофой.

Четыре места, где BOLA ломается

Старт и seek (низкий буфер). При пустом буфере BOLA теоретически должна агрессивно выбирать максимально возможное качество, однако на практике первые секунды работы алгоритма нестабильны. dash.js решает эту проблему с помощью гибридной стратегии (см. ниже): на старте используется throughput-ориентированный подход, а затем происходит переключение на BOLA.

Сильно нестабильные сети (мобильный 5G в движении). Когда сеть каждые 5 секунд скачкообразно меняется с 20 Мбит/с до 2 Мбит/с и обратно, сам буфер становится нестабильным, и BOLA реагирует медленнее, чем throughput-ориентированный ABR. Это не значит, что «BOLA плохой» – проблема в том, что BOLA работает на длинном временном горизонте, а сеть – короткопериодичная и шумная. В таких условиях throughput-ориентированный подход реагирует на каждый сегмент, BOLA фильтрует шум, но теряет в адаптивности.

Очень короткие сегменты в low-латентном стриминге. BOLA разрабатывался для сегментов продолжительностью 4–10 секунд, типичных для VOD-стриминга. В LL-HLS и LL-DASH сегменты составляют 200–500 миллисекунд, а буфер – 1–3 секунды. Математическая модель BOLA формально работает, но «единичные шаги» становятся настолько малыми, что практическая ценность каждого отдельного решения теряется на фоне шума. В low-латентных сценариях обычно применяются алгоритмы ABR, основанные на пропускной способности (throughput-based), или специализированные low-латентные решения (например, L2A, описанный в дополнительной литературе DASH-IF).

Битрейт-лесенка с большими «дырами». Если шаги лесенки слишком велики – например, 500 → 2500 → 6000 кбит/с – BOLA склонна задерживаться на средней ступени, даже когда сеть позволяет перейти на верхнюю. Это связано с тем, что utility-функция (логарифм битрейта) даёт небольшой прирост при переходе с большого на очень большой битрейт. Проблема решается использованием плотной лесенки (не менее 5 ступеней с шагом не более 50%).

Гибридная стратегия в dash.js: BOLA + Throughput

С 2018 года dash.js по умолчанию использует не «чистый BOLA», а гибридную стратегию, сочетающую BOLA с правилом на основе пропускной способности. Логика проста:

  • На старте, после seek или когда уровень буфера падает ниже порога – используется ThroughputRule (throughput-ориентированный, описан в статье 5.3).
  • Когда буфер достигает целевого размера (по умолчанию 12 секунд) – происходит переключение на BolaRule (BOLA-O).
  • Если уровень буфера снова опустится ниже порога – возвращается к ThroughputRule.

Этот гибрид сочетает сильные стороны обоих подходов: throughput-based быстро принимает решения при низком уровне буфера (что важно для старта и стабильности после перемещения), а BOLA обеспечивает оптимальное долгосрочное поведение при достаточном буфере. Стратегия называется abrDynamic в настройках dash.js и включена по умолчанию.

Концептуально гибрид работает следующим образом:

buffer_level (сек)
       ↑
   60 ─┤         ████████████  ← BOLA region
       │      ████
   30 ─┤   ███
       │
   12 ─┤── (threshold) ────────────────────
       │ ▒▒▒▒▒                            ← Throughput region
    0 ─┤▒▒▒▒
       └─────────────────────────────────→ время
        start    growing buf    steady

В точке пересечения линии 12 секунд dash.js переключает движок решений. Зритель ничего не замечает – плеер лишь немного меняет своё поведение.

Тюнинговые параметры в dash.js

dash.js предлагает несколько реализаций BOLA в MediaPlayer.setSettings(). Основные:

ПараметрДефолтЧто делает
streaming.abr.ABRStrategyabrDynamicabrThroughput (только throughput), abrBola (только BOLA), abrDynamic (гибрид).
streaming.buffer.stableBufferTime12Порог буфера для переключения с Throughput на BOLA (секунды).
streaming.buffer.bufferTimeAtTopQuality30Целевой буфер при максимальном качестве.
streaming.abr.bandwidthSafetyFactor0.9Запасной коэффициент throughput-правила; влияет на низкобуферный режим.
streaming.abr.usePixelRatioInLimitBitrateByPortalfalseУчитывать pixel-ratio экрана; ограничивает максимальную ступень для маленьких экранов.
streaming.abr.maxBitrate.audio/video−1Хард-кап битрейта.

Самый полезный параметр – stableBufferTime. Увеличение до 20 секунд делает поведение более «BOLA-доминированным» (стабильное качество, осторожный старт); уменьшение до 6 – более «throughput-доминированным» (быстрее реагирует на изменения в сети, чаще переключается).

// Пример: настройка гибридного ABR для VOD-плеера со стабильным контентом
player.updateSettings({
  streaming: {
    abr: {
      ABRStrategy: 'abrDynamic',
      bandwidthSafetyFactor: 0.85,
    },
    buffer: {
      stableBufferTime: 20,
      bufferTimeAtTopQuality: 60,
    },
  },
});

Числовой пример: BOLA на четырёх сегментах

Условия: лесенка 400, 750, 1500, 2500, 4000 кбит/с, длина сегмента – 4 секунды, целевой буфер – 30 секунд, V = 0,93 (типичное значение по умолчанию).

Сегмент 1. Старт. Буфер 0 секунд. dash.js использует ThroughputRule (BOLA в гибридном режиме не активен при нулевом буфере). Оценка пропускной способности по первому пробному запросу – 3,2 Мбит/с. Выбрана ступень 2500 кбит/с (максимальная при битрейте ≤ 0,9 × 3,2 = 2,88 Мбит/с). Загрузка заняла 1,25 секунды, буфер вырос до 2,75 секунды.

Сегмент 2. Буфер 2.75. Правило по-прежнему ThroughputRule. Оценка пропускной способности обновилась до 3.1 Мбит/с. Снова 2500 кбит/с. После загрузки буфер достиг 5.5.

Сегменты 3–4. Аналогично. После сегмента 4 буфер составляет 11 секунд – близко к порогу.

Сегмент 5. Буфер – 14 секунд (после загрузки сегмента 5). Превышен порог stableBufferTime = 12. dash.js переключается на BolaRule. Рассчитываем score для каждой ступени:

Для ступени m полезность равна log(bitrate_m / 400), а размер пропорционален битрейту. Рассмотрим упрощённую форму без γ × p:

score(m) ∝ (V × log(bitrate_m / 400) − buffer_level) / bitrate_m

При buffer = 14 и V = 0.93:

  • m = 1 (400): (0.93 × 0 − 14) / 400 = −0.035
  • m = 2 (750): (0.93 × log(1.875) − 14) / 750 = (0.585 − 14) / 750 = −0.0179
  • m = 3 (1500): (0.93 × log(3.75) − 14) / 1500 = (1.229 − 14) / 1500 = −0.00851
  • m = 4 (2500): (0.93 × log(6.25) − 14) / 2500 = (1.703 − 14) / 2500 = −0.00492
  • m = 5 (4000): (0.93 × log(10) − 14) / 4000 = (2.141 − 14) / 4000 = −0.00296

Максимум – m = 5 (4000 кбит/с). Но сеть обеспечивает всего 3,2 Мбит/с! BOLA выбирает 4000 кбит/с, скачивание невозможно – оно превысит 4-секундный бюджет, и буфер начнёт падать. После этой попытки буфер составит 14 − (5 − 4) = 13 секунд. На следующем шаге BOLA пересчитывает: теперь буфер ниже, и формула может выбрать m = 4. Однако реалистичный гибрид с FINITE-вариантом сразу блокирует скачок на две ступени и реализует промежуточный выбор m = 4.

Сегмент 6. При buffer = 12.5 BOLA выбирает m = 4 (2500 кбит/с), что соответствует решению, ограниченному пропускной способностью – алгоритм сходится к стационарному состоянию.

Через 20–30 сегментов стабильной игры BOLA устойчиво работает на 2500 кбит/с с буфером около 14 секунд, и переключений не происходит, пока сеть существенно не изменится.

Этот пример демонстрирует классический паттерн: BOLA на стадии стартапа сначала «переоценивает» свои возможности, но затем стабилизируется и работает на пол-уровня ниже throughput-ориентированного ABR, компенсируя это отсутствием осцилляций.

Рисунок 2. Симуляция гибридной стратегии dash.js на 8 сегментах. Цвета: серый – фаза пропускной способности, синий – фаза BOLA. Видно, как алгоритм переключается между режимами в зависимости от уровня буфера.

BOLA vs Throughput vs Buffer-Only

КритерийThroughput-basedBOLA (buffer-based)Гибрид (dash.js)
Главный сигналИзмеренная скорость сетиУровень буфераОба, в зависимости от состояния
Поведение на стартеБыстрая реакция, может ошибатьсяНестабильно при пустом буфереThroughput на старте, BOLA дальше
Стабильность качестваКолебания на границе ступенейОчень стабильно при высоком буфереСтабильно после старта
Реакция на короткий дропСразу переключается внизИгнорирует, пока буфер достаточенИгнорирует через BOLA
Реакция на длительный дропБыстро адаптируетсяМедленнее, но без осцилляцийАдекватно
Доказанные гарантииНетБлизок к оптимуму с погрешностью O(1/V)Не доказан (эвристический микс)
Подходит для low-latency (<3 сек)ДаНетЧерез lowLatencyMode
Подходит для VODХуже, чем BOLAЛучший выборХороший выбор
Используется по умолчанию вhls.js, нативный iOS(Чистый – нигде)dash.js, Bitmovin Player

Главный вывод: гибрид – практический победитель. BOLA сам по себе теоретически элегантен, но требует помощника по пропускной способности на сложных стартах. Сам по себе Throughput работает, но колеблется. Вместе они обеспечивают как устойчивое стационарное поведение, так и быстрый старт.

Пять подводных камней BOLA в продакшене

Камень 1: «BOLA выбирает низкое качество на быстрой сети». Это не ошибка – так задумано: алгоритм действует с осторожностью, когда буфер стабилен. Если зрителям визуально не хватает качества при явно достаточной скорости – увеличьте bandwidthSafetyFactor ближе к 1.0 (но не выше – это полностью снимет запас в фазе throughput) и увеличьте bufferTimeAtTopQuality, чтобы дать BOLA больше «пространства» для роста.

Камень 2: «BOLA не реагирует на сеть». При очень нестабильной сети (например, мобильной) BOLA действительно медленно реагирует на резкие скачки скорости. Если ваша аудитория в основном мобильная, рассмотрите ABRStrategy = abrThroughput – передайте контроль чисто throughput-правилу. Либо используйте hls.js, у которого логика на основе буфера проще и менее зависит от длинного горизонта.

Камень 3: «BOLA в LL-HLS/LL-DASH не работает». Действительно, в low-latency-стриминге с буфером 1–3 секунды формула BOLA становится численно нестабильной. В dash.js предусмотрен отдельный режим streaming.lowLatencyEnabled = true, в котором BOLA заменяется на специализированные low-latency ABR-алгоритмы, например L2A. Если вы реализуете low-latency-стриминг, обязательно включайте этот режим.

Камень 4: «Битрейт-лесенка с большими дырами». Если ваша лесенка 500/2000/8000 кбит/с, BOLA склонна «застревать» на 2000 даже при наличии 8 Мбит/с. Увеличение числа ступеней втрое – помогает: 500/750/1100/1700/2500/3800/5500/8000. Плотная лесенка даёт алгоритму больше вариантов выбора и больше пространства для манёвра.

Камень 5: «BOLA и DRM не дружат при низком CPU». На старых устройствах декодирование высоких битрейтов может быть ограничено производительностью процессора, и BOLA, не учитывая это, выбирает уровень, который декодер не справляется обработать. Используйте maxBitrate.video для жёсткого ограничения на устройствах с известным слабым CPU (Smart TV до 2020 года, low-end Android).

Где Фора Софт в этом поле

Мы разрабатываем стриминговые продукты с 2005 года и в более чем 30 проектах самостоятельно настраивали или дорабатывали ABR-движки – для OTT-платформ, e-learning-систем, телемедицинских live-связей и видеонаблюдения с архивной отдачей. Наиболее частая проблема в проектах с готовыми плеерами – стандартные параметры BOLA в dash.js не оптимизированы под тип контента. Например, для длинного VOD-кино мы обычно увеличиваем bufferTimeAtTopQuality до 90 секунд и stableBufferTime до 20 – это снижает коэффициент повторной буферизации в 2–4 раза при минимальной потере среднего битрейта. В случае live-стриминга с целевой задержкой 6 секунд, наоборот, держим stableBufferTime на уровне 5 и активно используем lowLatencyMode. Если вы запускаете стриминговый продукт и сталкиваетесь с непонятными показателями качества пользовательского опыта – мы за час проанализируем конфигурацию dash.js/hls.js и подскажем, какие три параметра стоит изменить.

Ключевые выводы

  • BOLA – ABR-алгоритм на основе буфера, доказуемо приближающийся к оптимальному решению с использованием метода Ляпунова.
  • Основным сигналом является уровень буфера, а не измеренная скорость сети.
  • По умолчанию используется в dash.js (~80% плееров MPEG-DASH) в рамках гибридной стратегии вместе с правилом на основе пропускной способности.
  • Хорошо работает на стабильных сетях, при длительном воспроизведении VOD и высоком уровне буфера; слабее проявляется на старте, в нестабильных сетях и в условиях низкой задержки.
  • Гибридная стратегия (BOLA + Throughput) – практический лидер: правило по пропускной способности на старте, BOLA – в стационарном режиме.
  • Основные параметры настройки в dash.js: stableBufferTime, bufferTimeAtTopQuality, bandwidthSafetyFactor, ABRStrategy.

Что читать дальше

Источники

  1. BOLA: Near-Optimal Bitrate Adaptation for Online Videos. K. Spiteri, R. Sitaraman, V. Swaminathan. IEEE INFOCOM 2016 + IEEE/ACM Transactions on Networking 2019. https://groups.cs.umass.edu/wp-content/uploads/sites/3/2019/12/BOLA-Near-optimal-bitrate-adaptation-for-online-videos.pdf
  2. From Theory to Practice: Improving Bitrate Adaptation in the DASH Reference Player. K. Spiteri, R. Urgaonkar, R. K. Sitaraman. ACM Transactions on Multimedia Computing 2019. https://dl.acm.org/doi/fullHtml/10.1145/3336497
  3. ABR Settings – dash.js documentation, DASH Industry Forum, 2025. https://dashif.org/dash.js/pages/usage/abr/settings.html
  4. BolaRule documentation – dash.js, DASH-IF. https://dashif.org/dash.js/pages/usage/abr/bola-rule.html
  5. BOLA status – Dash-Industry-Forum/dash.js GitHub Wiki. https://github.com/Dash-Industry-Forum/dash.js/wiki/BOLA-status
  6. Implementing BOLA-BASIC on Puffer. Stanford University, 2023. https://puffer.stanford.edu/bola/
  7. Stochastic Network Optimization with Application to Communication and Queueing Systems. M. J. Neely. Morgan & Claypool, 2010. (Основополагающая монография по Lyapunov-оптимизации для сетевых задач.)
  8. ABR Logic – Dash-Industry-Forum/dash.js GitHub Wiki, 2025. https://github.com/Dash-Industry-Forum/dash.js/wiki/ABR-Logic

Строите такую систему?

Подберём параметры кодирования под ваш контент и посчитаем стоимость доставки до старта разработки.