Протоколы раздачи
Полная карта адресов раздачи — HLS, LL-HLS, DASH, MSE-WS, HTTP-TS, RTSP, RTMP, WHEP и превью: задержка, применение и ограничения браузеров.
Принятый поток разбирается один раз и складывается в общий кольцевой буфер фрагментов. Все протоколы раздачи читают этот же буфер: HLS отдаёт фрагменты как сегменты плейлиста, MSE-WS шлёт их в браузер по вебсокету, RTSP распаковывает их обратно в пакеты. Переупаковка не повторяется.
Отсюда главный практический вывод: включать «лишние» протоколы раздачи не вредно. Стоимость несёт поток и число отправленных байт, а не количество включённых протоколов.
Полная карта раздачи#
Все HTTP-адреса обслуживаются слушателем http (и https) — отдельного медиа-порта нет.
| Протокол | Адрес | Доставка | Где применять | Включение |
|---|---|---|---|---|
| HLS fMP4 | https://media.example.com/<поток>/master.m3u8 |
несколько секунд | универсальная совместимость: браузеры, мобильные, телевизоры, CDN | всегда |
| LL-HLS | https://media.example.com/<поток>/master.ll.m3u8 |
доли секунды | тот же HLS, когда важна задержка | глобально, low_latency on; (по умолчанию включено) |
| HLS-TS | https://media.example.com/<поток>/mpegts.m3u8 |
несколько секунд | старые приставки и телевизоры, не понимающие fMP4 | hls_ts; в потоке |
| DASH | https://media.example.com/<поток>/index.mpd |
несколько секунд | встраиваемые плееры и устройства, ориентированные на DASH | всегда |
| MSE-WS | wss://media.example.com/<поток>/mse.ws |
доли секунды | видеостены и панели наблюдения в браузере, где нужна низкая задержка без WebRTC | всегда |
| HTTP-TS | https://media.example.com/<поток>/stream.ts |
доли секунды | простые потребители, умеющие читать непрерывный поток по HTTP | http_ts; в потоке |
| RTSP | rtsp://media.example.com:8554/<поток> |
десятки миллисекунд | видеорегистраторы, стороннее ПО, служебная диагностика, самая низкая задержка | rtsp <порт>; |
| RTSPS | rtsps://media.example.com:<порт>/<поток> |
десятки миллисекунд | то же поверх TLS | rtsps <порт>; |
| RTMP | rtmp://media.example.com:1935/<приложение>/<поток> |
доли секунды | передача в сторонние сервисы, принимающие RTMP | rtmp <порт>; |
| RTMPS | rtmps://media.example.com:1936/<приложение>/<поток> |
доли секунды | то же поверх TLS | rtmps <порт>; |
| WHEP (WebRTC) | POST https://media.example.com/s/<поток>/whep |
доли секунды | самая низкая задержка в браузере; единственный способ услышать в браузере звук G.711 | webrtc <порт>; |
| Превью-кадр | https://media.example.com/<поток>/preview.mp4 |
— | плитки, списки камер, заставка до нажатия «play» | всегда |
| Multicast MPEG-TS | групповой адрес, задаётся в потоке | доли секунды | раздача внутри своей сети без запроса от клиента | multicast_out …; в потоке |
| Встроенный плеер | https://media.example.com/<поток>/embed.html |
— | быстрый просмотр и встраивание в свою страницу | всегда |
Имя потока может содержать /: cam, live/cam1, cam/<UUID>/main. Все адреса привязаны к концу
пути, поэтому внутренние слеши сохраняются.
Дополнительные адреса HLS#
| Адрес | Что это |
|---|---|
index.m3u8, index.fmp4.m3u8, master.fmp4.m3u8 |
синонимы master.m3u8 |
index.ll.m3u8 |
синоним master.ll.m3u8 |
/<поток>/<дорожка>/playlist.m3u8 |
плейлист дорожки: v0 — видео, a0 — звук |
/<поток>/<дорожка>/init.mp4 |
заголовок инициализации |
/<поток>/<дорожка>/<номер>.m4s |
сегмент |
/<поток>/<дорожка>/part_<номер>_<индекс>.m4s |
часть LL-HLS |
Обычный HLS — master.m3u8, низколатентный — master.ll.m3u8. Это два разных адреса одного и того
же потока; переключателя в строке запроса нет. Если low_latency off;, адреса .ll.m3u8 отвечают
404, а мастер-плейлист остаётся обычным.
Браузер скрывает от страницы код отказа при апгрейде вебсокета. Поэтому у mse.ws есть отдельная
проба заголовками:
curl -sS -I "https://media.example.com/demo/mse.ws"
HTTP/1.1 204 No Content Cache-Control: no-store
204 — доступ разрешён, 403 — отказано, 404 — потока нет.
Что включается директивой#
Директивы внутри блока stream применяются без перезапуска службы — перезапускается только сам
поток; глобальные директивы отмечены отдельно.
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
http_ts |
булев флаг: http_ts; · http_ts on|off; |
off |
горячее |
hls_ts |
булев флаг | off |
горячее |
audio_only_playlist |
булев флаг | off |
горячее |
multicast_out |
<группа>:<порт>[?ttl=&iface=&loopback=&tos=] |
выключено | горячее |
rtsp_transports |
both · tcp · udp |
both |
горячее |
caps |
список протоколов для вкладок плеера | авто | горячее |
allowed_referers |
список имён хостов | не ограничено | горячее |
segment_seconds |
дробное, секунды | 2.0 |
горячее |
segments_count |
целое | 5 |
горячее |
prepush |
дробное, секунды; 0 — по умолчанию протокола |
0 |
горячее |
low_latency |
on · off; глобальная директива |
on |
рестарт |
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; http_ts; # добавить /cam1/stream.ts hls_ts; # добавить /cam1/mpegts.m3u8 segment_seconds 2; segments_count 5; }
http_ts и hls_ts используют один и тот же кольцевой буфер MPEG-TS — любой из двух флагов
включает мультиплексор.
Семейство fMP4 — HLS, LL-HLS, DASH, MSE-WS, WHEP, RTSP — читает готовую упаковку, поэтому добавление
любого из них не создаёт работы по переупаковке. Флаги http_ts и hls_ts включают второй
мультиплексор — в MPEG-TS; он бездействует, пока нет зрителей. А multicast_out — постоянный
потребитель: пакеты уходят в сеть всегда, независимо от того, слушает ли их кто-нибудь.
Задержка#
Задержка у зрителя складывается из двух слоёв. Первый — доставка: путь кадра от источника через сервер до плеера. Второй — буфер плеера: запас между живым краем и точкой воспроизведения, который плеер держит, чтобы неровность сети не превращалась в подвисания картинки. Буфер обычно больше доставки, поэтому именно он определяет итог.
Доставка измерена на стенде разработки с синтетическим источником и настройками по умолчанию; измерялись четыре протокола, остальные в таблицу не попали. Итог у зрителя — целевая задержка встроенного веб-плеера, заложенная в его коде. Это позиция относительно живого края: она уже включает доставку, складывать колонки не нужно. Для RTSP плеер не участвует — буфер задаёт клиент, обычно минимальный.
| Протокол | Доставка до плеера (измерено) | Итог у зрителя (цель плеера) |
|---|---|---|
| RTSP | 96 мс | доли секунды — буфер задаёт клиент |
| MSE-WS | 223 мс | ≈1 с (цель 0,95 с; на Safari — 1,5 с) |
| LL-HLS | 317 мс | ≈4 с |
| HLS обычный | 2 605 мс | ≈8 с — примерно 3 сегмента от живого края |
Цели сдвинуты в сторону плавности сознательно: подвисания недопустимы, поэтому плеер держит запас, гасящий неровность сети, и мягко подтягивается к цели вместо рывков. У обычного HLS и DASH запас — несколько сегментов (цель у них общая, ≈8 с), у MSE-WS — доли секунды. Если задача требует меньшей задержки, целевое значение снижается настройкой плеера.
Реальные значения зависят от источника, сети и плеера. Порядок величин при этом устойчив: обычный HLS отстаёт от эфира на несколько сегментов, LL-HLS — на несколько секунд, MSE-WS — примерно на секунду, RTSP — на доли секунды.
Настройка задержки:
segment_seconds— целевая длительность сегмента. Реальная длина попадает в диапазон от целевой до целевой плюс интервал между опорными кадрами: сегмент всегда закрывается по опорному кадру. Интервал опорных кадров на камере влияет на задержку сильнее любой серверной настройки.segments_count— сколько сегментов держится в живом окне. Меньше — меньше задержка, но у зрителя с плохой связью меньше запаса.prepush— насколько позади живого края начинает новый зритель. Больше — устойчивее к плохой связи, меньше — ниже задержка.- Размер части LL-HLS сервер выбирает сам и объявляет в плейлисте атрибутом
PART-TARGET; настройки у него нет.
Если камера выдаёт опорный кадр раз в 4 секунды, сегменты короче 4 секунд не получатся, сколько бы
ни было указано в segment_seconds. Настройте на камере интервал опорных кадров равным
1–2 секундам, и только потом занимайтесь серверными параметрами.
Какие кодеки доходят до какого зрителя#
Перекодирования нет, поэтому кодек источника определяет всё дальнейшее. Каждый протокол несёт только то, что способен нести:
| Раздача | Видео | Звук |
|---|---|---|
| HLS fMP4 и LL-HLS | H.264 · H.265 · AV1 | только AAC и Opus |
| MSE-WS | H.264 · H.265 · AV1 | только AAC и Opus |
| DASH | H.264 · H.265 · AV1 | только AAC и Opus |
| HLS-TS | только H.264 и H.265 | только AAC |
| HTTP-TS | только H.264 и H.265 | только AAC |
| Multicast MPEG-TS | только H.264 и H.265 | только AAC |
| RTSP и RTSPS | H.264 · H.265 · AV1 | AAC · Opus · G.711 обоих законов — всё |
| WHEP (WebRTC) | H.264 · H.265 · AV1 | Opus · G.711 обоих законов — но не AAC |
| RTMP и RTMPS | H.264 · H.265 | только AAC |
Несовместимая дорожка не вызывает ошибку — она просто не создаётся. Зритель получает исправное видео без звука, а не сломанный поток.
- RTMP несёт только AAC. Поток со звуком Opus или G.711, отданный по RTMP, уходит без звука — молча, без предупреждения клиенту.
- WHEP не несёт AAC. Если у источника звук AAC, ответ WHEP вообще не содержит звуковой дорожки: AAC не согласуется в WebRTC.
- Любая раздача на основе MPEG-TS — это H.264/H.265 плюс AAC. AV1, Opus и G.711 не имеют стандартного отображения в MPEG-TS и исключены по построению.
Звук G.711 и браузеры#
Большинство IP-камер выдают звук G.711, и ни один браузер не умеет декодировать G.711 через Media Source Extensions. Это ограничение браузеров, а не сервера, и исправить его на стороне плеера нельзя.
Сервер обрабатывает это честно: звуковая дорожка G.711 просто не создаётся в браузерных раздачах. Мастер-плейлист HLS не объявляет несуществующую дорожку и не упоминает её в списке кодеков — иначе плеер завис бы на всём варианте, хотя видео исправно.
| Способ просмотра | Видео | Звук |
|---|---|---|
| HLS, LL-HLS, MSE-WS, DASH (живое) | H.264 · H.265 · AV1 | AAC · Opus |
| Просмотр архива в браузере | то же | AAC · Opus (записи с G.711 играют беззвучно) |
| WHEP (WebRTC) | H.264 · H.265 · AV1 | Opus · G.711 обоих законов — но не AAC |
Выгруженный фрагмент архива .mp4 |
то же | всё, включая G.711 |
WHEP — единственный ответ. WebRTC несёт G.711 штатно. Платой будет операционный профиль WebRTC: UDP, согласование адресов, более высокая стоимость на зрителя. Обратите внимание на обратный случай: зритель WHEP на потоке со звуком AAC звука не получит.
Долговременное решение — перевести камеру на AAC там, где модель это позволяет. Преобразования G.711 в AAC на сервере нет: это потребовало бы перекодирования, которого в продукте нет.
Потребителей вне браузера это не касается: по RTSP звук G.711 передаётся как есть, и в архив на диске он пишется полностью.
Заведите поток input demo://?ac=g711; — это синтетический источник со звуком G.711 и жёсткой
синхронизацией. Контрольные варианты — ?ac=aac и ?ac=opus.
RTSP: транспорт и ограничения#
rtsp://media.example.com:8554/<поток>
Управление дорожками: …/trackID=0 — видео, …/trackID=1 — звук.
Поддерживаемые методы:
OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER
Ровно два транспорта: RTP/AVP/TCP;unicast;interleaved= и RTP/AVP;unicast;client_port=. Какой из
них разрешён клиенту, задаётся в потоке:
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; rtsp_transports tcp; # both (по умолчанию) | tcp | udp }
Отказы: 461 Unsupported Transport — запрошенный транспорт запрещён или не удалось занять пару
UDP-портов; 453 Not Enough Bandwidth — исчерпан лимит max_sessions; 455 — метод не в свою
очередь.
Групповая раздача выполняется только push-ом MPEG-TS через multicast_out. Запрос многоадресного
транспорта по RTSP будет отклонён.
Смежные настройки:
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
rtsp_frame_source |
cmaf · raw_au; глобальная |
cmaf |
рестарт |
rtp_max_payload |
целое, байты; диапазон 376–65507 | 1200 |
рестарт |
max_sessions |
целое; 0 — без ограничения; глобальная |
0 |
рестарт |
Значение rtp_max_payload 1200 безопасно для туннелей и VPN. Внутри локальной сети с MTU 1500 его
можно поднять примерно до 1460 и сэкономить на заголовках. rtsp_frame_source raw_au берёт кадры из
буфера отдельных единиц доступа — задержка чуть ниже.
printf 'OPTIONS rtsp://media.example.com:8554/demo RTSP/1.0\r\nCSeq: 1\r\n\r\n' \ | timeout 5 nc media.example.com 8554
RTSP/1.0 200 OK CSeq: 1 Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER
Варианты мастер-плейлиста для приставок и телевизоров#
Некоторые устройства не справляются с отдельной звуковой дорожкой в мастер-плейлисте. Для них
предусмотрен параметр ?variant=, действующий только на мастер-плейлист:
?variant= |
Результат |
|---|---|
отсутствует · standard · separate_audio |
обычный мастер-плейлист fMP4 |
video |
мастер-плейлист без звуковой дорожки |
mono |
мастер-плейлист со смешанными видео и звуком в MPEG-TS; ведёт на mpegts.m3u8. Отвечает 404, если у потока не включён hls_ts |
| любое другое | 400 unknown variant |
curl -sS "https://media.example.com/demo/master.m3u8?variant=video" | head -5
#EXTM3U #EXT-X-VERSION:9 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:BANDWIDTH=10803752,AVERAGE-BANDWIDTH=9003127,CODECS="avc1.64001F",RESOLUTION=1280x720,FRAME-RATE=25.000,CLOSED-CAPTIONS=NONE v0/playlist.fmp4.m3u8?sid=281474976710657
Директива audio_only_playlist; добавляет в мастер-плейлист вариант «только звук» — этого требуют
правила публикации некоторых мобильных платформ.
Раздача MPEG-TS в группу#
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; multicast_out 239.1.1.1:5000 ttl=4 iface=10.0.0.5 loopback=1 tos=184; }
Равнозначная форма — со строкой запроса: multicast_out 239.1.1.1:5000?ttl=4&iface=10.0.0.5.
| Параметр | Тип | По умолчанию |
|---|---|---|
ttl |
целое 0–255 | 4 |
loopback |
булев (0/false — выключить) |
включено — приёмник на том же хосте работает |
iface |
литеральный IPv4 | не задан, интерфейс выбирает ядро |
tos |
целое 0–255, поле DSCP | не задано |
Группа обязана быть литеральным адресом IPv4. Значение проверяется при загрузке конфигурации:
stream "cam1": bad multicast_out "239.1.1.1" (expected <group:port>[?ttl=&iface=&loopback=&tos=])
Поток нарезается на датаграммы по 1316 байт; таблицы PAT и PMT периодически повторяются, чтобы поздно подключившийся приёмник смог их получить. Догон ограничен восьмикратной скоростью реального времени, чтобы не захлестнуть приёмники.
Кэширование и CDN#
Заголовок Cache-Control |
На что выставляется |
|---|---|
public, max-age=31536000, immutable |
закрытые сегменты .m4s и .ts, части LL-HLS, init*.mp4, завершённые сегменты архива, сборка плеера |
no-store |
все плейлисты, index.mpd, preview.mp4, stream.ts, embed.html, ошибки, открытый хвост архива |
Смена содержимого выражается именем, а не строкой запроса: init-<16 hex>.mp4,
/player/embed.<хеш>.js. Устаревший init-<hex>.mp4 отвечает 410 init rotated — это сигнал
плееру перечитать плейлист. Вытесненный сегмент отвечает 410, ещё не созданный — 404.
Тела медиа отдаются с Accept-Ranges: bytes и поддерживают 206 и 416.
allowed_referers отключает кэширование потокаЕсли у потока задан список разрешённых источников встраивания, его сегменты и init переводятся с
immutable на no-store. Защита от встраивания на чужих сайтах и раздача через CDN здесь взаимно
исключают друг друга — выбирайте осознанно.
Ограничение числа сессий#
Директива max_sessions действует глобально, на все протоколы сразу. Проверка выполняется после
авторизации, а на HLS — только при первом обращении к мастер-плейлисту, поэтому уже смотрящий
зритель никогда не отключается посреди просмотра из-за исчерпания лимита.
Медленный зритель не мешает остальным: индивидуальных очередей нет, каждый читает общий кольцевой буфер по своему курсору. Отставший «наматывает круг» только сам, а поставщик кадров не блокируется.
| Протокол | Что происходит с отстающим |
|---|---|
| MSE-WS | срок записи кадра 10 с; превышение отключает эту сессию. Круг буфера — пересинхронизация, сессия продолжается |
| HTTP-TS | пересинхронизация вперёд; запись в сокет сама создаёт обратное давление |
| Multicast | пересев на ближайший опорный кадр, догон восьмикратной скоростью |
| RTMP | срок записи 10 с |
Куда двигаться дальше#
- Встраиваемый плеер — готовая страница просмотра и её параметры.
- Приём видео: обзор — с какой стороны поток приходит.
- Авторизация просмотра — как закрыть раздачу токенами.
- Порты и сеть — какие порты открывать наружу.