HLS и DASH: сегментированный стриминг и вопросы задержки

В этом разделе мы рассмотрим, как FFMPEG используется для генерации потоков по протоколам HLS (HTTP Live Streaming) и DASH (Dynamic Adaptive Streaming over HTTP) — двух ключевых технологий сегментированного стриминга. Основное внимание будет уделено HLS, так как он наиболее распространён и наглядно демонстрирует особенности такого подхода к передаче видео. Мы разберём, как FFMPEG режет поток на сегменты, формирует плейлисты, и почему этот подход по своей природе связан с большой задержкой. Также обсудим, где такие решения уместны, а где — нет.
Как FFMPEG создаёт HLS-поток
HLS — это протокол, разработанный Apple, который передаёт видео не как непрерывный поток, а как последовательность коротких файлов (сегментов), загружаемых по HTTP. FFMPEG может выступать в роли генератора HLS, принимая входной поток (например, с камеры или файла) и преобразуя его в набор сегментов и управляющего файла-плейлиста.
Рассмотрим типичную команду:
ffmpeg -i input -c:v libx264 -c:a aac -f hls -hls_time 4 -hls_list_size 5 stream.m3u8
Разберём её по частям:
-i input— входной источник (может быть файлом, RTSP-потоком, камерой и т.д.).-c:v libx264— кодирование видео в H.264.-c:a aac— кодирование аудио в AAC.-f hls— указывает FFMPEG использовать формат вывода HLS.-hls_time 4— длительность каждого сегмента в секундах (здесь — 4 секунды).-hls_list_size 5— количество сегментов, отображаемых в плейлисте.m3u8.stream.m3u8— имя основного плейлиста.
Что происходит при выполнении команды?
FFMPEG делает следующее:
- Принимает входной поток и транскодирует его (если нужно) в H.264 + AAC.
- Режет видео на сегменты по 4 секунды каждый. Каждый сегмент сохраняется как отдельный файл, например:
stream0.ts,stream1.ts,stream2.tsи т.д. - Формирует плейлист
stream.m3u8— текстовый файл в формате M3U8, содержащий список активных сегментов и их метаданные.
Пример содержимого stream.m3u8:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:2
#EXTINF:4.000,
stream2.ts
#EXTINF:4.000,
stream3.ts
#EXTINF:4.000,
stream4.ts
#EXT-X-ENDLIST
Примечание: В режиме live-трансляции тег
#EXT-X-ENDLISTотсутствует, так как трансляция продолжается.
Каждый новый сегмент добавляется в конец плейлиста, а старые — удаляются, если размер списка ограничен (например, -hls_list_size 5 оставляет только 5 последних сегментов).
Почему HLS по определению имеет большую задержку
Задержка (латентность) в HLS не является ошибкой или недоработкой — она заложена в самой архитектуре протокола. Ниже мы разберём ключевые причины.
1. Необходимость накопления нескольких сегментов
Клиент (например, браузер или плеер) не может начать воспроизведение, пока не загрузит хотя бы один сегмент. Но на практике плееры ждут 2–3 сегмента, чтобы сформировать буфер и избежать обрывов при скачках сети.
Если каждый сегмент длится 4 секунды, а плеер ждёт 3 сегмента, минимальная задержка уже составляет 12 секунд.
🔹 Пример:
СегментA(0–4 с) — загружен.
СегментB(4–8 с) — загружен.
СегментC(8–12 с) — загружен.
Только теперь плеер начинает воспроизведение с начала сегментаA.
Реальное время: 12 сек, но видео показывает 0 сек → задержка = 12 с.
2. Кэширование на уровне CDN и прокси
HLS использует HTTP, что позволяет задействовать CDN (Content Delivery Network) и промежуточные кэши. Это повышает масштабируемость, но добавляет задержку:
- CDN может кэшировать сегменты на несколько секунд.
- Промежуточные прокси (например, корпоративные или провайдерские) также могут задерживать доставку файлов.
- Некоторые CDN принудительно кэшируют
.ts-файлы, что делает невозможным «мгновенное» обновление.
3. Период обновления плейлиста
Клиент периодически запрашивает обновлённый stream.m3u8, чтобы узнать, появились ли новые сегменты. Интервал обновления зависит от реализации, но обычно составляет от 1 до 3 секунд.
Это означает, что даже если сегмент уже готов, клиент может не узнать о нём сразу.
Сравнение задержки: HLS vs другие протоколы
| Протокол | Типичная задержка | Причина задержки |
|---|---|---|
| HLS | 10–30 сек | Сегментация, буферизация, кэширование |
| RTMP | 3–8 сек | TCP, буферы сервера, отсутствие сегментации |
| SRT | 0.5–2 сек | Адаптивное управление буферами, FEC, низкоуровневая передача |
| WebRTC | 0.2–1 сек | P2P, UDP, минимальные буферы, эфемерная передача |
✅ Вывод: HLS — самый медленный из распространённых протоколов, но это компенсируется его масштабируемостью и надёжностью.
Где уместно использовать HLS?
Несмотря на высокую задержку, HLS остаётся одним из самых популярных протоколов для потокового видео. Вот где он работает лучше всего:
✅ Уместные сценарии
| Сценарий | Почему подходит |
|---|---|
| Массовые трансляции (концерты, спортивные события) | Тысячи зрителей → нужна масштабируемость через CDN. Задержка не критична. |
| Видеокурсы и вебинары (по записи) | Важно качество и стабильность, а не интерактивность. |
| ТВ-вещание через интернет | Архитектура HLS совместима с традиционным ТВ-опытом (зритель смотрит "эфир", а не общается). |
| Архивные стримы и VOD (Video on Demand) | Плейлисты легко кэшируются, поддерживаются все браузеры. |
❌ Неуместные сценарии
| Сценарий | Почему не подходит |
|---|---|
| Вебинары с обратной связью | Задержка 15 секунд делает диалог невозможным. |
| Видеонаблюдение в реальном времени | Оператору нужно видеть "сейчас", а не "15 секунд назад". |
| Интерактивные трансляции (опросы, игры) | Зритель отвечает с задержкой — система не успевает реагировать. |
| WebRTC-интеграции | Требуется синхронность, HLS несовместим по задержке. |
DASH: аналог HLS с похожими ограничениями
DASH (Dynamic Adaptive Streaming over HTTP) — это открытый стандарт, аналогичный HLS, но не привязанный к Apple. Он также использует сегментацию и HTTP-доставку, поэтому страдает от тех же проблем с задержкой.
Различия незначительны с точки зрения латентности:
- DASH может использовать короткие сегменты (даже
<1сек), но это требует частых запросов и не всегда поддерживается CDN. - Формат описания — MPD (Media Presentation Description) вместо
.m3u8. - Поддержка более сложных сценариев адаптации, но архитектура буферизации остаётся похожей.
🔹 FFMPEG также поддерживает DASH, но реже используется для него, чем для HLS.
Вывод: FFMPEG — удобный генератор HLS, но не для ультранизкой задержки
FFMPEG отлично справляется с ролью HLS-генератора:
- Простая команда → готовый поток.
- Поддержка транскодирования, сегментации, настройки размера сегментов.
- Интеграция с любыми входами (RTSP, файлы, UDP и т.д.).
Однако важно понимать:
❗ HLS — это технология для масштабируемых, но не интерактивных трансляций.
Если в вашем сценарии критична задержка, стоит рассмотреть другие решения:
- SRT — для межстудийных линий.
- WebRTC — для интерактивных приложений.
- RTMP (с короткими буферами) — как компромисс.
FFMPEG остаётся мощным инструментом, но не решает всех задач. В следующих лекциях мы рассмотрим GStreamer — более гибкую систему, где можно строить пайплайны с минимальной задержкой и точным контролем над буферами.
Практический совет: как уменьшить задержку в HLS (ограниченно)
Хотя полностью устранить задержку в HLS невозможно, можно частично её снизить:
| Настройка | Эффект |
|---|---|
-hls_time 1 | Сегменты по 1 секунде → быстрее появляются в плейлисте |
-hls_list_size 3 | Меньше сегментов в буфере → клиент начинает раньше |
| Использование LL-HLS (Low-Latency HLS) | Экспериментальный режим Apple с частичной загрузкой сегментов и push-обновлениями плейлиста |
| Отказ от CDN / кэширования | Прямая доставка с сервера, но теряется масштабируемость |
⚠️ Важно: LL-HLS поддерживается не всеми плеерами и требует специальной настройки сервера. FFMPEG частично поддерживает его через флаги, но реализация сложнее.
Итог
- HLS — это сегментированный протокол, основанный на HTTP.
- FFMPEG легко генерирует HLS-потоки через опции
-f hlsи настройки сегментации. - Задержка неизбежна из-за архитектуры: накопление сегментов, кэширование, обновление плейлиста.
- HLS уместен для массовых, неинтерактивных трансляций, где важна стабильность и масштабируемость.
- Для низколатентных сценариев (видеосвязь, мониторинг) HLS не подходит — нужны другие протоколы и инструменты.