Содержание статьи +
- TL;DR
- Почему это важно
- Что такое LL-DASH в одном абзаце
- История в трёх вехах
- Бюджет задержки – до и после
- Четыре механизма по одному
- Live LL-DASH MPD построчно
- ABR на chunked-transfer-ответе
- Где фактический пол задержки в 2026 году
- LL-DASH и LL-HLS вместе – унифицированный CMAF-стек
- Распространённые подводные камни
- Когда LL-DASH – правильный выбор, а когда нет
- Где здесь Фора Софт
- Ключевые выводы
- Что читать дальше
- CTA
Опубликовано: 2026-05-21 · Время чтения: 25 мин · Автор: Николай Сапунов, CEO Фора Софт
Последняя сверка: 2026-05-21 со стандартом ISO/IEC 23009-1:2022 (MPEG-DASH, пятая редакция, август 2022), ISO/IEC 23000-19:2024 (CMAF, третья редакция), DASH-IF Implementation Guidelines: Low-Latency Modes for DASH v1.2 (2024), DASH-IF Implementation Guidelines: Restricted Timing Model (post-community-review, 2025), IETF RFC 9112 (HTTP/1.1, июнь 2022), IETF RFC 9114 (HTTP/3, июнь 2022), исходниками референсного плеера dash.js v5 и Bitmovin Video Developer Report 2025/26.
TL;DR
Low-Latency DASH – LL-DASH – это профиль MPEG-Даш, сочетающий chunked-encoding CMAF-сегментов с передачей по HTTP с chunked transfer, чтобы снизить задержку от экрана до экрана с 20–30 секунд в обычном DASH до 2–4 секунд. Суть в том, что минимальная единица, которую может получить плеер, – это уже не целый сегмент, а отдельный CMAF chunk: фрагмент сегмента длительностью 200–500 миллисекунд, который packager публикует сразу после того, как энкодер его создал, а origin отдаёт плееру кадр за кадром через открытый HTTP-ответ, не закрывая соединение до конца сегмента. Четыре сигнала в MPD помогают плееру понять этот механизм: @availabilityTimeOffset указывает, насколько раньше завершения сегмента chunk становится доступен для скачивания; @availabilityTimeComplete="false" сообщает, что chunks генерируются постепенно, а не как единый атомарный файл; <ServiceDescription> задаёт целевую задержку; а URN профиля DASH-IF для low-latency (urn:mpeg:dash:profile:cmaf-extended:2018) подтверждает, что весь low-latency-контракт действует. В сочетании с HTTP/1.1 chunked transfer encoding, HTTP/2 stream framing или HTTP/3 stream framing – и при условии, что плеер выполняет ABR на основе частично полученных chunk’ов, а не завершённых сегментов, – LL-Даш достигает той же задержки в 2–4 секунды, что и LL-HLS, на всех браузерах и устройствах, кроме Apple. Стек производства 2026 года – это один набор CMAF-chunk’ов, который раздаётся как LL-HLS для iOS / Safari и как LL-Даш для Chrome / Edge / Firefox / Android с одного и того же origin.
Почему это важно
Если вы транслируете live-видео в Chromium-браузере, на Android-устройствах, Smart TV (кроме Apple TV) или на любом из полумиллиарда устройств с ExoPlayer или Shaka Player, то LL-DASH – это то, что вы фактически используете для низкой задержки. LL-HLS получил широкую известность, потому что Apple контролирует информационное поле, и почти каждая статья на тему «как реализовать низкую задержку» начинается с iOS. Однако реальность развёртывания в 2026 году такова: LL-HLS покрывает экосистему Apple, LL-DASH – всё остальное, а CMAF обеспечивает общий формат файлов под капотом. Механика здесь тонкая: chunked transfer и CMAF-chunk – не одно и то же; @availabilityTimeOffset не то же самое, что @suggestedPresentationDelay; ABR-алгоритм в плеере должен уметь оценивать пропускную способность по частично загруженному чанку – а режимы отказов в продакшене всегда возникают на стыках. Цель статьи – сделать каждую строку LL-DASH MPD понятной, сделать каждый узел цепочки chunked-CMAF видимым и превратить компромиссы между LL-DASH, LL-HLS и WebRTC в предмет обсуждения на основе цифр.
Что такое LL-DASH в одном абзаце
LL-HLS – это стандартный MPEG-DASH с тремя ключевыми изменениями. Во-первых, энкодер генерирует CMAF-чанки (фрагменты по 200–500 миллисекунд) вместо ожидания завершения полного сегмента длительностью 2–6 секунд. Во-вторых, origin-сервер передаёт эти чанки плееру через HTTP chunked transfer encoding (в HTTP/1.1) или stream framing (в HTTP/2 и HTTP/3) в рамках одного ответа, который остаётся открытым до тех пор, пока сегмент продолжает формироваться; плеер начинает обрабатывать данные по мере их поступления, не дожидаясь завершения ответа. В-третьих, в MPD присутствуют четыре сигнала – profile URN cmaf-extended, @availabilityTimeOffset на каждом SegmentTemplate, @availabilityTimeComplete="false" и блок <ServiceDescription> с указанной целевой задержкой, – которые в совокупности сообщают плееру: «вы смотрите поток с низкой задержкой; вот как планировать запросы, где находится live edge и сколько данных нужно буферизовать». Совместимый с DASH-IF плеер с поддержкой low-latency (например, dash.js с версии 3.0, Shaka Player с 3.2, ExoPlayer с 2.16, Bitmovin Player с 8.41, THEOplayer с 4.0) интерпретирует эти сигналы, рассчитывает первый запрос так, чтобы он пришёлся на момент появления следующего чанка, запускает ABR-алгоритм, ориентируясь на скорость в байтах в секунду, а не в чанках в секунду, и поддерживает заявленную в MPD целевую задержку. В результате достигается задержка 2–4 секунды при использовании той же CDN-инфраструктуры, формата файлов, packager’ов и DRM, что и в обычном DASH: не требуется новое серверное ПО, новый протокол инжеста или плеерный движок – достаточно новых сигналов в манифесте и настройки ABR.
История в трёх вехах
Low-latency DASH появился раньше LL-HLS, и это стандарт, из которого создатели LL-HLS явно черпали идеи. Три ключевые вехи определяют, как мы оказались в 2026 году.
Первая – публикация в 2017 году ISO/IEC 23000-19 – Common Media Application Format (CMAF). CMAF определяет формат фрагментированной упаковки MP4, в котором явно поддерживается chunk – фрагмент, являющийся наименьшей адресуемой медиаединицей. CMAF chunk представляет собой один или несколько кадров, упакованных внутри пары moof + mdat, которые можно разобрать и декодировать независимо от остальной части родительского сегмента. Стандарт зафиксировал то, что некоторые энкодеры уже начали применять в 2016 году (например, предложения Akamai по «low-latency HLS over CMAF» ещё до появления Apple-LL-HLS), и предоставил HLS и DASH общий строительный блок.
Вторая – публикация в 2019 году DASH-IF Low-Latency Modes for DASH на community review, формализованная как DASH-IF Implementation Guidelines в 2020 году и пересмотренная до версии v1.2 в 2024 году. Этот документ является фактической спецификацией LL-HLS, поскольку ISO/IEC 23009-1 определяет лишь сигналы на уровне манифеста; DASH-IF же задаёт, как собрать согласованный low-latency-профиль и как должен работать плеер. Релиз 2020 года совпал с выходом dash.js v3.0, в котором появилась первая референсная реализация low-latency-режима, а также с запуском первого коммерческого LL-HLS-решения на стороне origin от Akamai.
Третья – DASH-IF Restricted Timing Model 2025 года, закрывающая последний крупный разрыв в совместимости LL-HLS: как @availabilityTimeOffset, @suggestedPresentationDelay и оценка clock-skew в плеере вместе обеспечивают стабильную целевую задержку wall-clock у разнородных зрителей. Документ 2025 года определяет детерминированный алгоритм подстройки скорости воспроизведения (тот самый ±5%-ный «нудж», который компенсирует clock skew без заметного изменения тона аудио), и сейчас является эталоном для каждого production-развёртывания LL-HLS.
В 2026 году production-стек полностью зрелый. Сигналы MPD стали общепринятыми, dash.js и Shaka полностью совместимы со спецификацией. Основные пакетные решения (Akamai LL-CMAF, AWS MediaPackage v2, Bitmovin Live, Mux Live, Norsk, Unified Streaming, Wowza, Shaka Packager) корректно генерируют chunked-CMAF «из коробки», а ключевые CDN (Akamai, Cloudflare, Fastly, CloudFront) поддерживают настройку cache-ключа, необходимую для LL-DASH.
Бюджет задержки – до и после
Самый простой способ понять, что делает LL-DASH, – сравнить его с обычным DASH, добавив ограничение по задержке.
У типичного plain-DASH live-потока те же три источника задержки, что и у plain HLS, но выраженные в других единицах. Энкодер генерирует сегменты длительностью 2–6 секунд; для канонического сегмента в четыре секунды проходит четыре секунды реального времени до момента, когда первый байт сегмента N достигает origin-сервера. Задержка segment availability – это время ожидания, равное одной длительности сегмента, между завершением сегмента энкодером и моментом, когда плеер узнаёт о его доступности, поскольку плеер опрашивает MPD по расписанию, заданному @minimumUpdatePeriod. Playback buffer традиционно имеет глубину в три сегмента, чтобы плеер мог компенсировать джиттер – это добавляет ещё двенадцать секунд. К этому прибавляется около секунды на HTTP-оверхед – итого получается двадцать одна секунда glass-to-glass. В реальных production-развёртываниях измеряются задержки от восемнадцати до тридцати секунд.
LL-DASH переписывает каждую строку.
| Контрибьютор задержки | Plain DASH (4 с сегменты) | LL-DASH (4 с сегменты, 333 мс chunks) |
|---|---|---|
| Энкодер | 4.0 с (полный сегмент) | 0.33 с (один chunk) |
| Segment availability | 2.0 с (половина @minimumUpdatePeriod) | 0.0 с (template-адресация; перезагрузка MPD не нужна) |
| Playback buffer | 12.0 с (3 сегмента) | 1.0–2.0 с (3–6 chunks) |
| HTTP-оверхед | 1.0 с | 0.4 с (один открытый ответ) |
| Итого glass-to-glass | ~19 с | ~1.8–2.8 с |
Энкодерная строка сокращается с четырёх секунд до трети секунды, потому что packager публикует chunk сразу после его создания энкодером, а не дожидается завершения полного сегмента. Показатель доступности сегментов падает до нуля, поскольку LL-Дэш использует шаблонную адресацию (SegmentTemplate$Number$ или $Time$): плеер вычисляет URL следующего сегмента без обновления MPD и запрашивает его в момент, когда @availabilityTimeOffset указывает, что он должен стать доступен. Буфер воспроизведения сжимается с трёх сегментов до трёх–шести чанков, так как минимальная единица, которую плеер может буферизовать, теперь – чанк, а не сегмент. HTTP-оверхед уменьшается вдвое, поскольку плеер держит ответ с chunked-transfer открытым на весь сегмент, вместо того чтобы делать отдельный запрос на каждый сегмент.
Четыре механизма по одному
LL-DASH – это одна новая идея упаковки (CMAF chunk), одна новая идея транспорта (chunked transfer) и два новых сигнала в манифесте (@availabilityTimeOffset и <ServiceDescription>). Все четыре компонента приносят пользу только в совокупности. Пропустите любой из них – получите более медленную версию LL-DASH, которая всё ещё будет называться LL-DASH в конфигурационном файле.
Механизм 1 – CMAF chunk
CMAF chunk – наименьшая единица, которую можно независимо разобрать при парсинге CMAF-сегмента. Это одна пара moof + mdat, содержащая один или несколько видео- или аудиокадров, упакованных в тот же fragmented-MP4-контейнер, что и родительский сегмент. В четырёхсекундном сегменте с chunk-ами по 333 мс файл содержит двенадцать таких пар подряд moof/mdat. CMAF chunk соотносится с CMAF-сегментом так же, как moof с HLS-сегментом: та же единица на уровне передачи, но под другим именем #EXT-X-PART.
Для плеера важны два свойства. Первое: chunk можно разобрать и декодировать сразу после получения его байтов, не дожидаясь окончания сегмента. Бокс moof в начале chunk’а содержит информацию о времени воспроизведения и смещениях сэмплов; mdat – сами кадры; SourceBuffer.appendBuffer() плеер принимает их как валидный фрагмент. Второе: только некоторые chunk’и независимы – те, что начинаются с I-кадра (IDR-сэмпла в терминах H.264 / HEVC / AV1). Независимый chunk (P- или B-кадры) можно декодировать только после предыдущих chunk’ов. DASH-IF guidelines требуют наличия хотя бы одного независимого chunk’а на сегмент; в production-развёртываниях делают по одному такому chunk’у в секунду реального времени, чтобы обеспечить плееру частые возможности для ABR.
Длительность чанка – главный регулятор задержки. Чанк длительностью 200 мс сдвигает нижнюю границу задержки к 1,8 с, но ценой более частого moof-оверхеда и более агрессивного ABR-каданса. Чанк в 500 мс поднимает эту границу до 2,5 с и снижает накладные расходы на упаковку. DASH-IF рекомендует диапазон 200–500 мс; значение 333 мс стало стандартом по умолчанию в 2026 году, поскольку оно идеально соответствует 30 кадрам в секунду (10 кадров на чанк) и 60 кадрам в секунду (20 кадров на чанк).
Арифметика проста. Четырёхсекундный сегмент с чанками по 333 мс – это двенадцать чанков. Поток с пятью вариантами (multivariant) генерирует шестьдесят событий публикации чанков на сегмент, но плеер не выполняет шестьдесят запросов: он делает один запрос на сегмент и получает все двенадцать чанков через один открытый ответ с чанковой передачей (chunked transfer). Нагрузка на канал у плеера остаётся такой же, как при обычном DASH; нагрузка на packager и origin возрастает, поскольку им обоим приходится генерировать и транслировать контент в двенадцать раз чаще.
Механизм 2 – Передача данных по частям (chunked transfer)
Механика на уровне провода, обеспечивающая работу LL-DASH, – это HTTP chunked transfer encoding (HTTP/1.1, RFC 9112 §7.1) и её аналоги в HTTP/2 и HTTP/3. Благодаря chunked transfer сервер может начать передавать тело ответа, не зная его общей длины заранее: он отправляет каждый фрагмент по мере готовности, завершая его длиной в шестнадцатеричном формате, а окончание тела сигналает нулевой длиной.
Для LL-DASH запрос обычно выглядит так:
GET /video/720p/segment-42.m4s HTTP/1.1
Host: edge.example.comОтвет, однако, необычный: он начинает стримить ещё до того, как сегмент 42 полностью произведён.
HTTP/1.1 200 OK
Content-Type: video/mp4
Transfer-Encoding: chunked
10F0 <- длина первого CMAF chunk в hex
[moof + mdat chunk 1, ~4 КБ]
10C5 <- длина второго CMAF chunk
[moof + mdat chunk 2, ~4.3 КБ]
…
0 <- chunk нулевой длины: конец телаСервер продолжает отправлять данные по мере их поступления от энкодера; плеер потребляет байты по мере получения. Ключевое свойство: буфер приёма TCP плеера (или поток QUIC) ни разу не опустошается между чанками после начала ответа – не требуется round-trip запрос-ответ на каждый CMAF-чанк, не нужен TLS-рукопожатие на каждый чанк, не требуется DNS-разрешение на каждый чанк, не нужен поиск в кэше CDN на каждый чанк. Один запрос открывает один ответ, который длится столько, сколько длится один сегмент, и байты поступают через него по мере появления.
В HTTP/2 и HTTP/3 семантика идентична, а формат на проводе отличается: сервер открывает stream (DATA-фреймы) вместо Transfer-Encoding: chunked и отправляет фреймы по мере генерации chunk’ов энкодером. И HTTP/2, и HTTP/3 мультиплексируют несколько запросов через одно соединение – это большой плюс, когда плеер одновременно загружает видео, аудио и субтитры; HTTP/3 дополнительно устраняет head-of-line-блокировку на уровне QUIC, что важно для сетей с потерями, но редко критично на проводных или 5G-соединениях, где чаще всего потребляется low-latency-контент. Распределение в 2026 году – примерно 60% HTTP/1.1 с chunked transfer, 25% HTTP/2, 15% HTTP/3, причём HTTP/3 растёт быстрее всех, поскольку тот же QUIC-стек лежит в основе MoQ.
Важнее всего понять, что chunked transfer и CMAF chunk – независимые понятия, у которых случайно совпало одно слово. Chunked transfer – это механизм на уровне HTTP, предназначенный для потоковой передачи тела ответа. CMAF chunk – это единица на уровне медиа. LL-HLS использует оба подхода, и значение термина «chunk» в каждом случае определяется контекстом.
Механизм 3 – `@availabilityTimeOffset` и `@availabilityTimeComplete`
MPD должен сообщить плееру две важные вещи, которые обычный DASH не указывает: на сколько раньше окончания сегмента он становится доступен для скачивания и то, что сегменты генерируются постепенно, а не как отдельные атомарные файлы. Эти условия описываются двумя атрибутами на SegmentTemplate (или SegmentBase).
@availabilityTimeOffset – десятичное число секунд. Оно указывает, на сколько секунд раньше номинального времени доступности сегмента первый байт сегмента становится доступен с origin. Для четырёхсекундного сегмента с 333-мс чанками @availabilityTimeOffset="3.667" говорит: «ты можешь начать скачивать сегмент N в тот момент, когда энкодер закончил первый чанк – это на 3,667 секунды раньше номинального времени завершения сегмента N».
@availabilityTimeComplete="false" объявляет, что сегмент не доступен атомарно в указанный момент – он формируется в течение @availabilityTimeOffset секунд. Плеер, не поддерживающий @availabilityTimeComplete, воспринимает сегмент как обычный файл и ждёт его полной загрузки, тогда как совместимый с LL-DASH плеер планирует запрос на время ранней доступности (early-availability-time) и обрабатывает ответ с чанковой передачей данных.
В MPD это выглядит следующим образом:
<AdaptationSet mimeType="video/mp4" segmentAlignment="true" startWithSAP="1">
<SegmentTemplate
timescale="90000"
duration="360000"
media="$RepresentationID$/segment-$Number$.m4s"
initialization="$RepresentationID$/init.mp4"
startNumber="1"
availabilityTimeOffset="3.667"
availabilityTimeComplete="false"/>
<Representation id="720p" bandwidth="2500000" width="1280" height="720" codecs="avc1.4d401f"/>
<Representation id="1080p" bandwidth="5000000" width="1920" height="1080" codecs="avc1.640028"/>
</AdaptationSet>Четырёхсекундная длительность сегмента – duration / timescale = 360000 / 90000 = 4.0 с. Чанк длительностью 333 мс даёт @availabilityTimeOffset = 4.0 - 0.333 = 3.667, поскольку первый чанк становится доступен через 333 мс после начала кодирования сегмента. Плеер вычисляет время доступности сегмента N как availabilityStartTime + N × segmentDuration - @availabilityTimeOffset и отправляет запрос в момент, когда его внутренние часы достигают этого значения.
Тонкое, но важное следствие: значение @availabilityTimeOffset отсчитывается относительно длительности сегмента, а не длительности chunk’а. Это смещение, с которого первый байт становится доступен, а не последний. Сервер обязан соблюдать контракт – если он указывает @availabilityTimeOffset="3.667", а плеер запрашивает в этот момент, ответ должен немедленно начать стриминг. Серверы, которые заявляют о наличии смещения, но на деле ждут завершения сегмента перед отправкой данных, – самая частая ошибка в LL-DASH; в MPD они выглядят корректными, а на практике ведут себя как обычный DASH.
Механизм 4 – `<ServiceDescription>` и целевая задержка
MPD объявляет желаемую задержку воспроизведения в блоке <ServiceDescription> в начале документа. В этом блоке содержится три элемента информации: целевая задержка в миллисекундах, допустимый диапазон скорости воспроизведения (±5% – «нудж», с помощью которого плеер компенсирует расхождение тактовых генераторов), а также опциональный диапазон минимального и максимального качества.
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011"
profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:mpeg:dash:profile:cmaf-extended:2018"
type="dynamic"
availabilityStartTime="2026-05-21T08:00:00Z"
minimumUpdatePeriod="PT4S"
timeShiftBufferDepth="PT60S"
minBufferTime="PT2S"
suggestedPresentationDelay="PT3S">
<ServiceDescription id="0">
<Latency target="3000" max="6000" min="2000" referenceId="0"/>
<PlaybackRate min="0.95" max="1.05"/>
</ServiceDescription>
<Period id="p0" start="PT0S">
<AdaptationSet ...>...</AdaptationSet>
</Period>
</MPD><Latency target="3000" max="6000" min="2000"/> – целевая задержка «стекло к стеклу», которую продюсер хочет, чтобы плеер поддерживал: в этом MPD она составляет три секунды, с жёстким нижним пределом в две секунды (ниже плеер должен ребуферить, а не рендерить) и мягким верхним пределом в шесть секунд (выше плеер должен ускоряться, чтобы догнать). <PlaybackRate min="0.95" max="1.05"/> говорит, что плеер может изменять скорость воспроизведения в диапазоне от 95% до 105%, чтобы приблизиться к целевой задержке – этого достаточно мало, чтобы изменения были неслышимыми.
suggestedPresentationDelay="PT3S" – legacy-атрибут DASH, выполняющий схожую функцию. DASH-IF Restricted Timing Model (2025) описывает, как плеер должен комбинировать @suggestedPresentationDelay, <Latency target=""> и фактически измеренную задержку для расчёта корректировки скорости воспроизведения; в продакшене для плееров, совместимых с LL-режимом DASH, используется блок <ServiceDescription>, а @suggestedPresentationDelay служит резервным решением для старых плееров, не поддерживающих новый сигнал.
Profile URN cmaf-extended:2018, указанный рядом с isoff-live:2011 в атрибуте @profiles манифеста, – это явное указание на то, что весь low-латентный контракт действует. Плеер, обнаруживший URN и настроенный на low-латентный режим, читает @availabilityTimeOffset, @availabilityTimeComplete и <ServiceDescription> и соответственно корректирует своё расписание и алгоритм ABR.
Live LL-DASH MPD построчно
Вот реалистичный LL-DASH MPD для четырёхсекундного сегментированного, 333-мсилункового live-потока с тремя видеорендициями и одной аудиорендицией.
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011"
profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:mpeg:dash:profile:cmaf-extended:2018"
type="dynamic"
availabilityStartTime="2026-05-21T08:00:00Z"
publishTime="2026-05-21T08:03:14Z"
minimumUpdatePeriod="PT4S"
timeShiftBufferDepth="PT60S"
minBufferTime="PT2S"
suggestedPresentationDelay="PT3S">
<ServiceDescription id="0">
<Latency target="3000" max="6000" min="2000" referenceId="0"/>
<PlaybackRate min="0.95" max="1.05"/>
</ServiceDescription>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-iso:2014"
value="https://time.akamai.com/?iso"/>
<Period id="p0" start="PT0S">
<AdaptationSet contentType="video" mimeType="video/mp4"
segmentAlignment="true" startWithSAP="1">
<SegmentTemplate
timescale="90000"
duration="360000"
media="$RepresentationID$/seg-$Number$.m4s"
initialization="$RepresentationID$/init.mp4"
startNumber="1"
availabilityTimeOffset="3.667"
availabilityTimeComplete="false"/>
<Representation id="360p" bandwidth="800000" width="640" height="360" codecs="avc1.4d401e" frameRate="30"/>
<Representation id="720p" bandwidth="2500000" width="1280" height="720" codecs="avc1.4d401f" frameRate="30"/>
<Representation id="1080p" bandwidth="5000000" width="1920" height="1080" codecs="avc1.640028" frameRate="30"/>
</AdaptationSet>
<AdaptationSet contentType="audio" mimeType="audio/mp4" lang="en"
segmentAlignment="true" startWithSAP="1">
<SegmentTemplate
timescale="48000"
duration="192000"
media="$RepresentationID$/seg-$Number$.m4s"
initialization="$RepresentationID$/init.mp4"
startNumber="1"
availabilityTimeOffset="3.667"
availabilityTimeComplete="false"/>
<Representation id="aac128" bandwidth="128000" codecs="mp4a.40.2" audioSamplingRate="48000"/>
</AdaptationSet>
</Period>
</MPD>Читаем сверху. Элемент <MPD> рекламирует два профиля: isoff-live:2011 (базовый live-профиль) и cmaf-extended:2018 (low-latency-профиль URN). type="dynamic" указывает, что это live-поток. availabilityStartTime – временная привязка к реальному времени для расчётов доступности сегментов. publishTime – время генерации этого MPD сервером; плеер может сравнить его с текущим временем, чтобы определить, устарел ли манифест. minimumUpdatePeriod="PT4S" говорит плееру перечитывать MPD каждые четыре секунды – хотя в стабильном low-latency-режиме адресация сегментов через шаблон означает, что новый MPD почти не нужен. suggestedPresentationDelay="PT3S" – устаревший параметр, задающий задержку в три секунды от live edge.
<ServiceDescription> передаёт современные сигналы с низкой задержкой: целевое время – 3 секунды, жёсткий минимум – 2 секунды, мягкий максимум – 6 секунд, диапазон скорости воспроизведения – 0,95–1,05.
<UTCTiming> указывает плееру на авторитетный источник времени – в этом примере Akamai well-known time service. Low-latency-плеер не может полагаться на часы клиентского устройства, потому что потребительские устройства дрейфуют на десятки миллисекунд, а live-edge-расписание зависит от sub-100-ms-точных wall-clock; плеер забирает time service на старте, вычисляет offset между serverверным и клиентским временем, и использует этот offset для каждого вычисления segment-availability. Restricted Timing Model 2025 года стандартизировала это; production LL-DASH-развёртывания без <UTCTiming> сломаны на большинстве клиентов.
Видео <AdaptationSet> несёт один <SegmentTemplate>, общий для всех трёх рендиций. timescale="90000" и duration="360000" дают 4-секундный сегмент (360000 / 90000 = 4.0). media="$RepresentationID$/seg-$Number$.m4s" – URL-шаблон: сегмент 42 рендиции 720p живёт по 720p/seg-42.m4s. startNumber="1" говорит, что сегменты нумеруются с 1. availabilityTimeOffset="3.667" объявляет, что первый байт каждого сегмента доступен на 3,667 секунды раньше его номинального времени появления – то есть в момент, когда энкодер произвёл первый чанк. availabilityTimeComplete="false" объявляет, что сегмент производится прогрессивно.
Каждый <Representation> объявляет представление с фиксированным битрейтом, разрешением, кодеком и частотой кадров. Плеер выбирает одно представление из AdaptationSet в любой момент времени и может переключаться между ними на границах чанков (при условии независимости чанка).
Аудио <AdaptationSet> синхронизировано с видео и представлено одной Representation (128 кбит/с, AAC LC, 48 кГц).
Когда сегмент 42 производится, плеер вычисляет:
- segment-42-availability-time = availabilityStartTime + 42 × 4.0 - 3.667 = 08:02:48.333 UTC
- Скорректированное время работы плеера пересекает отметку 08:02:48.333.
- Плеер отправляет GET /720p/seg-42.m4s на origin.
- Origin немедленно начинает стриминг ответа с chunked-transfer.
- Первый CMAF-чанк приходит к плееру примерно через 80 мс (сетевой RTT + TTFB origin).
- Плеер декодирует чанк и отображает первый кадр примерно через 20 мс.
- За следующие 3,667 секунды прибывают ещё одиннадцать чанков – по одному каждые 333 мс.
- В 08:02:52.000 ответ завершается, а сегмент 43 уже 333 мс находится в производстве; плеер отправляет GET /720p/seg-43.m4s, и цикл продолжается.
Задержка «стекло-к-стеклу» в этом цикле составляет примерно:
- 0,333 с – энкодер (один chunk-канал);
- 0,080 с – сетевой RTT + время ответа источника (TTFB);
- 0,020 с – предварительная буферизация декодера (pre-roll);
- 1,5 с – буфер воспроизведения (целевая задержка 3,0 с; suggestedPresentationDelay 3,0 с; глубина буфера – 4,5 чанка);
- ≈ 2,0 с – задержка «стекло-к-стеклу» при рендеринге 720p в типичных условиях фиксированного широкополосного соединения.
ABR на chunked-transfer-ответе
ABR-переключение – это то, где LL- и plain-DASH-плееры наиболее заметно отличаются. ABR в plain-DASH прост: скачать сегмент N, разделить его размер на время загрузки – получить пропускную способность (throughput), выбрать самую высокую рендицию, у которой требуемая полоса пропускания ниже throughput минус запас (safety), и переключиться на следующем границе сегмента. При четырёхсекундных сегментах и одной секунде запаса плеер обеспечивает хорошее разрешение ABR: каждые четыре секунды – новый замер пропускной способности и чистая возможность для переключения.
LL-DASH ломает обе половины. Плеер больше не ждёт завершения сегмента, чтобы оценить пропускную способность – к моменту окончания сегмента N он уже в середине декодирования и отстаёт от принятия решения о переключении на 10 секунд. Поэтому плеер измеряет пропускную способность по частичным данным: количество байт, полученных за последние 500 мс или 1 секунду, делённое на затраченное время, даёт непрерывную оценку пропускной способности. В руководстве DASH-IF Low-Latency Modes это называется low-latency throughput estimator; dash.js v3.0 стал первой референсной реализацией, и теперь этот алгоритм является стандартом в Shaka v3.2+, ExoPlayer 2.16+ и основных коммерческих плеерах.
Оценщик throughput должен быть умнее обычного скользящего среднего, потому что сам ответ темпирован: сервер передаёт байты с той скоростью, с которой их генерирует энкодер, что составляет примерно 1/N от полной пропускной способности канала при N-рендиционном потоке на максимальном качестве. Наивная оценка throughput заключила бы: «это соединение ограничено 1,5 Мбит/с» – и плеер перешёл бы на более низкое качество; на самом деле у канала достаточно запаса пропускной способности, просто энкодер не может заполнять его быстрее, чем за 333 мс × bitrate на chunk. Скорректированный оценщик измеряет время между прибытиями chunk’ов и вычисляет эффективный сетевой throughput, исходя из того, насколько простаивает соединение между chunk’ами. Если плеер получает 60-байтный chunk каждые 333 мс, а сам chunk приходит за 30 мс, то канал простаивает 303 мс из каждых 333 мс, а эффективная пропускная способность – примерно 60 КБ / 30 мс = 2 МБ/с. Именно эту метрику плеер использует для ABR.
Логика переключения здесь отличается. В plain DASH переключение происходит на границе сегмента – один сегмент длится 4 секунды, то есть переключение может происходить не чаще, чем раз в 4 секунды. В LL-Даш плеер теоретически может переключаться на любом независимом чанке – примерно раз в секунду. Однако есть компромисс: переключение посередине сегмента требует, чтобы плеер загрузил init-сегмент новой рендиции (если он ещё не был загружен), прервал оставшуюся часть текущего chunked-ответа и начал получать чанки новой рендиции с ближайшей независимой границы. dash.js v5 (текущий референсный плеер на 2026 год) реализует это с консервативной политикой: переключение происходит только на независимых чанках, никогда в первой половине сегмента после предыдущего переключения и никогда, если задержка упадёт ниже <Latency min="">-пола. Большинство production-развёртываний упрощают логику, переключаясь только на границах сегментов и соглашаясь на четырёхсекундное разрешение ABR; более гибкая возможность mid-segment-переключения зарезервирована для самых агрессивных low-latency-развёртываний.
Где фактический пол задержки в 2026 году
Mux, Bitmovin, Akamai, AWS Elemental и Wowza публикуют бенчмарки по LL-DASH. Общий вывод – полный путь от экрана до экрана (glass-to-glass) в продакшене составляет 2–4 секунды. Публичные данные Mux за 2024 год: среднее время – 3,6 с по 38 000 сессий, медиана – 2,9 с, p95 – 5,5 с, p99 – 8,2 с – что напрямую сопоставимо с LL-HLS при тех же условиях. Развёртывания Bitmovin в 2025 году показывают 2,5–4,0 с в штатных условиях, с минимальным значением 1,5 с, достижимым только при оптимизированной pipeline кодирования (отсутствие B-кадров, GOP длительностью в одну секунду, сегмент по две секунды с чанками по 200 мс). У клиентов Akamai среднее время – 4,0 с, с длинным хвостом, вызванным джиттером Wi-Fi и буферным раздуванием (buffer bloat) на потребительских роутерах.
Стена в две секунды – та же, что и у LL-HLS, и по тем же причинам. LL-DASH не может ускорить энкодер быстрее, чем его pipeline: буфер на 1 GOP для B-кадров в качестве референса, CABAC-энтропия и мультиплексирование чанков – это минимум 500 мс задержки со стороны энкодера. Снижение GOP до одной секунды и отключение B-кадров – стандартная оптимизация для вещания pre-broadcast.
Он не может ускорить предварительную загрузку декодера быстрее, чем intake-латентность аппаратного декодера устройства (200–400 мс на современных смартфонах и телевизорах), не может уменьшить сетевой RTT ниже физических ограничений (60–120 мс через континент по оптоволокну, больше – по Wi-Fi и мобильной сети) и не может устранить HTTP-оверхед CDN (50–200 мс TTFB на edge).
Ниже двух секунд вы уже выходите за рамки HTTP-стриминга – попадаете в зону WebRTC или MoQ, и платите за это иным профилем масштабируемости.
LL-DASH и LL-HLS вместе – унифицированный CMAF-стек
Самое важное архитектурное озарение 2026 года – в том, что LL-HLS и Low-Latency DASH (LL-DASH) используют одни и те же базовые медиафайлы. Единицей передачи по сети для обоих протоколов являются CMAF-чанки – различие проявляется только на уровне манифестов. Современные пакеры (Shaka Packager, AWS MediaPackage v2, Unified Streaming, Bitmovin Live, Norsk, Mux Live) генерируют один набор CMAF-чанков и два параллельных манифеста: HLS-мультивариантный плейлист с #EXT-X-PART и DASH MPD с @availabilityTimeOffset. Те же чанки – для обеих сторон. Один и тот же origin. Один и тот же CDN. DRM остаётся неизменным (Common Encryption – CENC, определённый в ISO/IEC 23001-7, с Widevine PSSH для Chrome / Android, PlayReady PSSH для Edge / Xbox и FairPlay key delivery для Safari).
Паттерн развёртывания:
- iOS / iPadOS / macOS Safari / Apple TV → LL-HLS через chunked-CMAF (поскольку Safari не поддерживает воспроизведение DASH на основе MSE, а HLS – единственный протокол, который он умеет воспроизводить нативно).
- Android (Chrome, ExoPlayer) / Windows (Chrome, Edge) / macOS (Chrome, Firefox) / Linux / Smart TV (Tizen, webOS, Android TV, Roku в некоторых конфигурациях) → LL-DASH с использованием Shaka Player, dash.js, ExoPlayer или нативного DASH-стека устройства.
- Один и тот же набор CMAF-чанков используется для обоих протоколов.
Это паттерн «unified CMAF», и именно его используют все современные OTT-платформы в 2026 году – Netflix, Disney+, Prime Video, YouTube TV, Hulu, DAZN, а также live-потоковый путь Twitch на базе HLS-over-CMAF и большинство live-ecommerce-стеков. Полная спецификация формата CMAF доступна в CMAF: формат упаковки, объединивший HLS и DASH; детали LL-версии HLS описаны в LL-HLS: подробный разбор; данная статья посвящена LL-версии DASH.
Экономия конкретная. Один набор CMAF-файлов вместо двух наборов сегментов вдвое сокращает объём хранилища на origin и место в кэше CDN, упрощает инвалидацию и снижает нагрузку на CPU пакетизатора. Гайды DASH-IF и HLS-IF 2026 года оба рекомендуют развертывание unified CMAF как базовую точку старта для любого нового live-OTT-стека.
Распространённые подводные камни
Четыре механизма описывают суть LL-DASH. Подводные камни показывают, что может пойти не так на практике, если один из них настроен неправильно. Каждая команда, внедряющая LL-DASH, сталкивается с подмножеством этих ловушек.
«Ловушка – сервер рекламирует @availabilityTimeOffset, но ждёт завершения сегмента. MPD указывает @availabilityTimeOffset="3.667", плеер отправляет запрос в early-availability-time, но origin задерживает ответ до тех пор, пока сегмент 42 полностью не будет записан на диск. Плеер фиксирует задержку TTFB в 4 секунды на каждом сегменте, и бюджет задержки падает до уровня plain-DASH. Проверяйте: запрос должен отправляться за 3,5 секунды до времени завершения сегмента и анализируйте, сколько времени проходит до получения первого байта. Первый байт должен прийти в течение примерно 100 мс после запроса, а не через 4 секунды.»
«Ловушка – packager эмитит один moof на сегмент вместо одного moof на chunk. CMAF-сегмент с одним большим moof в начале и одним большим mdat после него технически валидный CMAF, но он не chunked – плеер не может ничего декодировать, пока весь mdat не прибудет. Проверьте CMAF-парсером (Bento4 mp4dump, verification-режим Shaka Packager или MP4Box -info -diso), что каждый сегмент содержит несколько пар moof + mdat. Production-цель: одна пара на 200–500 мс.»
«Ловушка – <UTCTiming> отсутствует или указывает на недоступный сервер. Без надёжного источника времени плеер переходит на системные часы устройства, которые могут отклоняться на десятки миллисекунд и быть неточными на минуты, если NTP отключён. Плеер рассчитывает неверное время доступности сегментов, запросы приходят слишком рано (404) или с опозданием (возникает задержка), из-за чего развёртывание выглядит периодически неработоспособным. Всегда включайте <UTCTiming> и проверяйте, что URL возвращает корректный ответ.»
«Ловушка – CDN cache TTL на манифесте слишком длинный. MPD обновляется каждые @minimumUpdatePeriod (обычно 2–4 секунды в режиме live). Если CDN кэширует MPD на 60 секунд, он отдаёт новым зрителям устаревший манифест, из-за чего те вычисляют номера сегментов, отсталых на несколько минут, и вынуждены долго ребуферить, пока не догонят поток. Установите Cache-Control: max-age=2 (или даже max-age=1) на ответ с MPD и убедитесь, что CDN действительно соблюдает эти настройки. Origin shielding помогает снизить нагрузку на origin.»
«Ловушка – CDN не уважает chunked transfer encoding. Некоторые устаревшие конфигурации CDN буферизуют весь ответ на edge-узле до отправки клиенту – режим «store-and-forward» – что блокирует работу chunked transfer. Пользователь видит один большой ответ только после завершения сегмента, а не поток chunks. Все основные CDN (Akamai, Cloudflare, Fastly, CloudFront, Bunny) в 2026 году поддерживают передачу chunked transfer без буферизации, но эта функция включена по умолчанию не везде – требуется явная настройка на уровне ресурса. Проверяйте корректность работы, анализируя заголовки ответа и временные метки поступления байтов.»
«Ловушка – <Latency target=""> выставлен слишком агрессивно. Целевая задержка 1,5 с при размере чанка 333 мс оставляет плееру буфер воспроизведения всего 1,0 с (3 чанка), что ниже безопасного порога ребуфера для большинства сетей. Плеер пытается догнать live edge, ускоряется до 1,05×, ребуферит, переходит на более низкое качество, и зритель замечает колебания качества. Рекомендация для продакшена: целевая задержка ≥ 2,5 с при чанках по 333 мс; ≥ 2,0 с при чанках по 200 мс.»
«Ловушка – не-независимые чанки слишком редки. Тот же режим отказа, что и у LL-HLS (LL-HLS). Некоторые энкодеры по умолчанию устанавливают один независимый (I-кадр) чанк на сегмент – то есть один раз в 4 секунды, – из-за чего переключения ABR вынуждены ждать границы сегмента. Настройте энкодер на один I-кадр в секунду (keyint=fps), проверьте через ffprobe -show_packets и настройте packager так, чтобы границы CMAF-чанков выравнивались по каденсу I-кадров.»
«Ловушка – fallback для non-low-latency-плееров сломан. Старые плееры, не поддерживающие @availabilityTimeOffset, всё равно должны воспроизводить поток – они должны видеть его как обычный plain-DASH-поток с несколько большей задержкой. Fallback работает только в том случае, если сам файл сегмента является валидным и может быть распарсен как обычный non-chunked CMAF-сегмент после завершения записи энкодером. Некоторые конфигурации packager оставляют границы moof/mdat целыми, но генерируют некорректный mvex-бокс, из-за чего non-low-latency-плееры его не распознают. Проверяйте корректность через DASH-IF-референс-плеер в non-low-latency-режиме на том же MPD.»
Когда LL-DASH – правильный выбор, а когда нет
LL-HLS – правильный выбор, если вам нужна доставка по HTTP, экономика CDN и задержка 2–5 секунд, а аудитория использует устройства, отличные от Apple. Такой подход охватывает большую часть рынка live-OTT в 2026 году для браузеров и Android: трансляции спортивных событий без ставок в реальном времени, новости, концерты, онлайн-обучение в прямом эфире, live-шопинг, где основной элемент взаимодействия – чат, обзор видеонаблюдения, первичная диагностика в телемедицине, когда пациенту важно видеть врача, но не требуется синхронная работа с инструментами.
LL-DASH – неправильный выбор в трёх направлениях. Вверх, когда важна задержка ниже двух секунд – спортивные ставки с real-time-ставками, live-аукционы, real-time-гейминг, телемедицинские консультации с синхронными интерактивными инструментами – здесь ответ дают WebRTC delivery и Media over QUIC. Вниз, когда задержка выше десяти секунд допустима – длинный VOD, повторы, подкаст-видео, архив – обычный MPEG-DASH проще, дешевле и дружелюбнее к кэшированию. Вбок, когда вы отдаёте контент только на устройства Apple – отдавайте LL-HLS на тот же chunked-CMAF-оригин.
Интересное недавнее сравнение – LL-DASH против HESP. HESP обеспечивает задержку до 400 мс с двухканальной архитектурой (канал инициализации + канал продолжения) при увеличении объёма хранения примерно вдвое. LL-DASH не может достичь такой же задержки, как HESP, но соответствует ему по совместимости с CDN и превосходит по эффективности использования хранилища. Для большинства практических задач LL-DASH выигрывает по соотношению стоимости и задержки; HESP предпочтительнее, когда критична задержка менее одной секунды, а использование WebRTC слишком дорого с операционной точки зрения.
Где здесь Фора Софт
Мы поставляли LL-DASH в live-e-learning-платформы, OTT-сервисы для Smart TV и Android, live-shoppin-платформы и системы телемедицинской триажа, где воспроизведение в браузере – основная поверхность. Наша команда инженеров стриминга рассматривает LL-DASH и LL-HLS как единую систему: один пакер, один origin на основе chunked CMAF, два параллельных манифеста, один стек DRM – потому что режимы отказа в продакшене чаще всего возникают на стыках между энкодером, пакером, origin’ом, CDN и плеером, а унифицированный стек сокращает количество таких стыков с десяти до четырёх. Мы также делали и обратное: помогали клиентам понять, что их use-case с задержкой менее секунды на самом деле требует WebRTC, и избегали поставки LL-DASH в продукты, где он никогда не достиг бы целевой задержки. Честный разговор о границах задач в начале экономит три месяца вопросов «почему всё ещё буферит» в конце.
Ключевые выводы
- LL-DASH – это стандартный MPEG-DASH с четырьмя дополнительными механизмами: фрагментами CMAF, HTTP-стримингом по частям, @availabilityTimeOffset и <ServiceDescription> с заданной целевой задержкой.
- В 2026 году ожидаемая производственная задержка составит 2–4 секунды от экрана до экрана (glass-to-glass), что сопоставимо с LL-HLS при аналогичных условиях.
- Chunked transfer (HTTP-стриминг на уровне ответа) и CMAF chunk (фрагментирование сегментов на уровне медиа) – независимые концепции, объединённые лишь общим термином; LL-DASH использует оба подхода.
- Единый стек на основе Unified CMAF: один пакетизатор, один набор файлов chunked CMAF, LL-HLS для устройств Apple, LL-DASH – для всех остальных платформ. Это станет стандартом по умолчанию для новых live-OTT-проектов в 2026 году.
- Наиболее частая ошибка в производстве – источник (origin), который объявляет готовность сегмента @availabilityTimeOffset, но при этом ждёт его полного завершения перед отправкой; обязательно проверяйте end-to-end работоспособность до публикации статуса готовности.
- Задержка менее 2 секунд возможна только с использованием WebRTC или MoQ, но не с LL-DASH.
Что читать дальше
- MPEG-DASH: подробный разбор MPD, Periods, AdaptationSets, Representations – фундамент, на котором построен LL-DASH.
- ll-hls подробный разбор: parts, preload hints, blocking reload, rendition reports – аналог от Apple для той же полосы 2–5 с.
- CMAF: формат упаковки, объединивший HLS и DASH – формат, совместимый с ll-hls и LL-DASH.
CTA
- Поговорить со streaming-инженером – чтобы определить, какая технология (LL-HLS, LL-HLS, WebRTC или MoQ) лучше всего соответствует вашей целевой задержке и бюджету на CDN.
- Посмотреть наши кейсы – примеры развёртываний в live-обучении, OTT, телемедицине и live-шопинге.
- Скачать – LL-HLS Readiness Checklist (2026) – чек-лист из двадцати четырёх пунктов, которые каждая команда должна проверить перед объявлением готовности LL-HLS к работе в продакшене.