Приём видео: обзор
Какие источники понимает сервер, как выбрать подходящий, как включить приём по требованию и что происходит при обрыве.
Источник задаётся директивой input внутри блока stream. Больше ничего не требуется: имя потока
становится путём в URL, а раздача по HLS, DASH, MSE-WS, RTSP и WebRTC поднимается автоматически.
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; }
Схема в начале URL полностью определяет способ приёма — отдельной директивы «тип источника» нет.
Два способа получить видео#
| Способ | Кто инициирует соединение | Схемы |
|---|---|---|
| Забор (pull) | сервер сам идёт к камере или чужому серверу | rtsp://, rtsps://, http://, https://, udp://, multicast://, rtmp://, rtmps://, file://, demo:// |
| Приём публикации (push) | кодировщик или браузер сам публикует на сервер | publish:// |
Забор проще в эксплуатации: сервер знает, жив ли источник, и сам переподключается. Публикация нужна там, где к источнику нельзя подключиться снаружи — за NAT, из браузера, из мобильного приложения.
Подробности: RTSP, HLS, DASH, MPEG-TS и Приём публикации: RTMP и WHIP.
Источник → когда применять#
| Схема | Что это | Когда применять |
|---|---|---|
rtsp:// · rtsps:// |
забор с камеры, видеорегистратора или кодировщика | основной сценарий видеонаблюдения; поддерживаются Basic и Digest, транспорт TCP или UDP |
http:// · https:// |
забор HLS, DASH или непрерывного MPEG-TS — формат определяется автоматически | пересборка чужой раздачи, приём от вышестоящего сервера, приём от облачного источника |
udp:// · multicast:// |
MPEG-TS по UDP: одноадресный или групповой | головные станции и IPTV-транспорт внутри своей сети |
rtmp:// · rtmps:// |
сервер сам подключается к RTMP-источнику и забирает поток | источник, который умеет отдавать только по RTMP |
publish:// |
сервер ждёт, пока источник опубликует поток к нему | студийные кодировщики, публикация из браузера, источник за NAT |
file:// |
локальный файл MP4, проигрываемый по кругу в реальном темпе | заглушка вместо камеры, проверка конвейера, демонстрация |
demo:// |
встроенный синтетический тест-паттерн с часами | проверка установки до появления камер, нагрузочное тестирование |
copy:// |
второй путь к уже принятому потоку без второго подключения | публичный алиас потока, отдельный набор меток доступа |
Всё, что не совпало ни с одной известной схемой, отдаётся приёмнику RTSP. Строка rstp://10.0.0.10/live
проходит проверку конфигурации и падает уже при запуске потока — с сообщением разбора RTSP-адреса,
а не «неизвестная схема». Проверяйте схему глазами.
Режим по требованию#
По умолчанию сервер подключается к источнику при старте и держит соединение постоянно. Флаг
on_demand меняет это: поток не подключается, пока его никто не смотрит, и отключается снова, когда
зрителей нет дольше отведённой грации.
on_demand_grace 30; # глобально, секунды stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; on_demand; # голый флаг = включено }
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
on_demand |
булев флаг: on_demand; · on_demand on; · on_demand off; |
off |
горячее (перезапускается только этот поток) |
on_demand_grace |
целое, секунды; глобальная директива | 30 |
рестарт |
Одно и то же значение служит и окном ожидания, и грацией простоя — это сделано намеренно, чтобы поток не «дребезжал» между подключением и отключением.
Что считается спросом: любой запрос HLS (мастер-плейлист, плейлист дорожки, init, сегмент,
часть LL-HLS), запрос DASH, апгрейд MSE-WS, подключение HTTP-TS, запрос превью-кадра, запрос WHEP,
DESCRIBE или SETUP по RTSP. Спрос засчитывается после проверки прав доступа, поэтому
неавторизованный запрос никогда не разбудит закрытую камеру.
Что спросом не считается: публикация по WHIP — это приём, а не просмотр.
on_demand молча игнорируется на записывающем потокеЕсли у потока есть dvr, флаг не действует и в журнале появляется
on_demand ignored — recording pins demand (always pulls/accepts). Причина простая: «писать только
пока смотрят» — это архив с дырами. То же самое относится к источнику publish://.
on_demand_grace 0 — это одна секунда, а не «отключить»Значение приводится к минимуму в 1 секунду. Обратите внимание на несимметричность: у media_timeout
ноль действительно отключает сторожевой таймер, а здесь — нет.
Режим экономит трафик до камеры и ресурсы сервера, но добавляет задержку первому зрителю: он ждёт подключения к источнику и первого опорного кадра.
Переподключение и сторожевой таймер#
Обрыв источника не разрушает поток. Кольцевой буфер, зрительские сессии и запись в каталоге
переживают переподключение: ни один зритель не отключается и ни один запрос HLS не отвечает 404
во время повторного соединения. В момент возобновления в плейлист вставляется
EXT-X-DISCONTINUITY, а звуковая ось пересогласуется заново.
Тайм-ауты приёма зафиксированы в сборке и не настраиваются:
| Семейство источников | Подключение | Чтение |
|---|---|---|
| RTSP | 10 с | 10 с (сторож бездействия — тройное значение, но не менее 20 с) |
| HTTP: HLS, DASH, MPEG-TS | 5 с | 10 с |
Настраивается другое — сторож «замершего медиа»:
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
media_timeout |
целое, секунды; 0 отключает |
20 |
рестарт |
Он ловит самую неприятную неисправность камеры: сокет открыт и здоров, ответы на служебные запросы
приходят, а кадры не идут. Каждая дорожка считается отдельно, и дорожка, которая никогда не
отдавала данных, ложную тревогу не вызывает — источник без звука не будет переподключаться из-за
отсутствующей звуковой дорожки. Отсчёт ведётся по монотонным часам, поэтому перевод системного
времени не вызывает срабатывания. Сторож не взводится, если в цепочке источников есть publish://:
живой, но молчащий публикатор не должен отключаться.
source_timeout= у input не действуетФорма input <url> source_timeout=N; разбирается и сохраняется, но ни один приёмник её не читает.
Пользуйтесь глобальным media_timeout.
Что считается ошибкой источника#
Состояние потока видно в панели управления и в API (GET /api/v1/streams). Ключевые поля:
| Поле | Значение |
|---|---|
alive |
по какой-либо дорожке недавно приходили данные |
health |
сводный вердикт: ok · degraded · failing · absent |
health_reasons |
причины вердикта: source_error · no_source · ts_stuck · ts_delay_high |
source_error |
текст последней ошибки источника; null, если ошибок нет |
reconnects |
сколько раз поток переподключался к источнику |
no_data_secs |
сколько секунд не приходило новых кадров |
input_errors, input_loss, input_discontinuities |
счётчики проблем на приёме |
Вердикт рассчитывается так:
- есть текст
source_error→failing, причинаsource_error; - припаркованный поток
on_demandбез ошибки →ok(это не сбой, а штатный простой); - кадров не было ни разу →
absent, причинаno_source; - кадров нет 30 секунд и дольше →
failing, причинаts_stuck; - кадров нет 8 секунд и дольше →
degraded, причинаts_delay_high; - иначе →
ok.
Срабатывание сторожа замершего медиа показывается как
media stall — source frozen (socket alive, no fragments).
curl -sS "https://media.example.com/api/v1/streams" \ -H "Authorization: Bearer $TOKEN" \ | python3 -c 'import sys, json for s in json.load(sys.stdin)["items"]: print(s["id"], "alive=" + str(s["alive"]), "health=" + s["health"], s["health_reasons"])'
Ожидаемый вывод для исправной установки — по строке на поток:
cam1 alive=True health=ok [] cam2 alive=True health=ok []
Общие директивы источника#
| Параметр | Тип и допустимые значения | По умолчанию | Применение |
|---|---|---|---|
input |
URL источника; повторяется — строит цепочку резерва | — | горячее (перезапускается только этот поток) |
on_demand |
булев флаг | off |
горячее |
tls_verify |
"" · system · insecure · pin:<64 hex> · ca:<путь> |
"" (системные корневые сертификаты) |
горячее |
disabled |
булев флаг — поток не запускается, но остаётся в файле | off |
горячее |
template |
имя блока template, откуда наследуются значения по умолчанию |
— | горячее |
source_transport |
tcp · udp · udp-then-tcp; глобальная директива |
tcp |
рестарт |
media_timeout |
целое, секунды; 0 отключает; глобальная директива |
20 |
рестарт |
on_demand_grace |
целое, секунды; глобальная директива | 30 |
рестарт |
tls_verify управляет доверием к сертификату источника при схемах rtsps://, https:// и
rtmps://. Значение проверяется при загрузке конфигурации, поэтому опечатка — это явная ошибка, а
не молчаливый откат к системным корневым сертификатам:
stream "cam1": bad tls_verify "pin:zz": invalid verify spec "pin:zz": pin must be 64 hex chars (leaf DER SHA-256)
Наследование через template работает на один уровень: шаблон не может ссылаться на шаблон.
Собственные директивы потока всегда важнее унаследованных.
Куда двигаться дальше#
- RTSP, HLS, DASH, MPEG-TS — формы адресов и параметры для каждого забираемого источника.
- Приём публикации: RTMP и WHIP — как настроить приём от кодировщика.
- Резервирование источников — запасной источник и правила переключения.
- Протоколы раздачи — что получат зрители.