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 – а это почти любой web-плеер, кроме нативного 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 была интегрирована как штатная стратегия в reference-плеер DASH. С тех пор она доступна в production у каждого, кто использует 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). Чем выше уровень, тем больше utility, но рост логарифмический – переход с 1 Мбит/с на 2 Мбит/с воспринимается зрителем сильнее, чем с 5 на 6 Мбит/с. Логарифм отражает закон Вебера-Фехнера.
  • V – главный тюнинговый параметр. Большой V – алгоритм больше ценит качество и готов рисковать буфером; малый V – алгоритм осторожнее, держится высокого буфера, реже ребуферизирует.
  • γ × p – штраф за «опасное состояние» (ребуферизация); γ – вес штрафа, p – параметр модели.
  • buffer_level – текущий уровень буфера в секундах.

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

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

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

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

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

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

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

BOLA-BASIC

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

BOLA-FINITE

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

BOLA-O (BOLA-Optimization)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Это гибрид комбинирует сильные стороны обоих: throughput-based быстро принимает решения при низком буфере (важно для старта и стабильности после seek), 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 в гибриде не активен при нулевом буфере). Throughput-оценка из первого пробного запроса – 3.2 Мбит/с. Выбрана ступень 2500 кбит/с (максимум при битрейте ≤ 0.9 × 3.2 = 2.88 Мбит/с). Скачано за 1.25 секунды, буфер вырос до 2.75 секунды.

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

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

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

Для ступени m utility = log(bitrate_m / 400), size – пропорционально битрейту. Возьмём упрощённую форму без γ × 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 пересчитывает: теперь buffer ниже, и формула может выбрать m=4. Но реалистично гибрид с FINITE-вариантом блокирует подъём сразу на две ступени и реализует промежуточный выбор m=4.

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

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

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

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

BOLA vs Throughput vs Buffer-Based-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-помощника на сложных стартах. Throughput сам по себе работает, но колеблется. Вместе они дают и устойчивое стационарное поведение, и быстрый старт.

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

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

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

Камень 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». На старых устройствах декодирование высоких ступеней может быть CPU-bound, и 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, что снижает rebuffering ratio в 2–4 раза при минимальной потере среднего битрейта. Для live-стриминга с целевой задержкой 6 секунд – наоборот, держим stableBufferTime на 5 и активно используем lowLatencyMode. Если вы запускаете стриминговый продукт и видите необъяснимые QoE-метрики – мы посмотрим dash.js/hls.js конфиг за час и скажем, какие три настройки изменить.

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

  • BOLA – buffer-based ABR-алгоритм, доказуемо приближающийся к оптимуму через технику Ляпунова.
  • Главный сигнал – уровень буфера, а не измеренная скорость сети.
  • Используется по умолчанию в dash.js (~80% MPEG-DASH-плееров) внутри гибридной стратегии с throughput-правилом.
  • Сияет на стабильных сетях, длинном VOD и при высоком буфере; слабее на старте, нестабильных сетях и в low-latency.
  • Гибридная стратегия (BOLA + Throughput) – практический победитель: 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

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

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