Резервирование источников
Цепочка запасных источников из повторяющихся директив input: порядок приоритета, правила переключения вниз и возврата на основной, наблюдение и ограничения.
Резервирование настраивается повторением директивы input внутри одного потока. Дополнительных
директив не требуется — порядок строк и есть порядок приоритета.
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; # 0 — основной input rtsp://admin:пароль@10.0.0.11:554/Streaming/Channels/101; # 1 — первый резерв input demo://; # 2 — последний рубеж }
Все схемы источников равноправны внутри цепочки: в ней могут соседствовать RTSP, HTTP, file:// и
demo://. Длина цепочки не ограничена, но на практике больше трёх звеньев редко нужно.
Цепочка — это по-прежнему один поток с одним именем, одним архивом и одним набором зрителей. Переключение источника происходит внутри него и снаружи почти незаметно.
Как сервер переключается#
| Событие | Поведение |
|---|---|
| Отказ текущего источника | немедленный переход к следующему в списке — без паузы. Смысл резерва в быстром переключении |
| Конец цепочки | цикл начинается заново после паузы 3 секунды плюс случайная добавка от 0 до 3 секунд (в худшем случае около 6 секунд) |
| Работа на резерве | параллельно с приёмом идёт отсчёт 30 секунд; когда он истекает, приём с резерва прерывается и сервер набирает основной источник напрямую |
| Возврат на основной | если основной ответил — работа продолжается на нём, без паузы. В журнале причина остановки резерва — return_to_primary |
Случайная добавка к паузе нужна не для красоты: при массовом отказе (пропала связь с целым узлом) одинаковая пауза у сотен потоков собирает их в синхронные волны переподключений, и каждая волна сама вызывает следующую. Разброс разводит такую группу по времени за один цикл.
Отдельной проверки «жив ли основной» нет. По истечении 30 секунд сервер просто пробует подключиться к нему заново — сама попытка и есть проверка. Если основной по-прежнему недоступен, поток возвращается на тот же резерв и отсчёт начинается снова.
Что происходит со зрителями#
Переключение источника не разрывает просмотр. Кольцевые буферы, зрительские сессии и запись в
каталоге сохраняются: ни один зритель не отключается, ни один запрос HLS не отвечает 404 в момент
перехода. В плейлист вставляется EXT-X-DISCONTINUITY, а звуковая ось пересогласуется — плееры
воспринимают это как обычный разрыв в живом потоке.
Архив тоже продолжается: запись не прерывается, но в месте перехода остаётся разрыв продолжительностью в реальную паузу приёма.
Как увидеть, что поток работает на резерве#
Два поля снимка потока в API и в панели управления:
| Поле | Значение |
|---|---|
active_source_idx |
номер источника, на котором поток работает сейчас; 0 — основной |
source_switches |
накопительный счётчик переходов в обе стороны; не сбрасывается |
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"]: if s["active_source_idx"] or s["source_switches"]: print(s["id"], "источник №" + str(s["active_source_idx"]), "переключений:", s["source_switches"])'
Для исправной установки вывод пуст — все потоки на основных источниках. Строка в выводе означает либо работу на резерве, либо перенесённые ранее переключения:
cam1 источник №1 переключений: 3
По этим двум полям удобно строить оповещения: «поток работает не на основном источнике» и «поток переключается слишком часто».
Ограничения, о которых нужно знать#
Переключение не бесшовное по кадрам. Между отказом одного источника и первым опорным кадром другого проходит реальное время: разрыв соединения, подключение к новому адресу, ожидание опорного кадра. Зритель увидит паузу. Резерв защищает от длительной пропажи картинки, а не от секундного перерыва.
Скорость обнаружения отказа зависит от того, как именно он выглядит. Разрыв соединения
обнаруживается сразу. «Замершая» камера — сокет открыт, служебные ответы приходят, кадров нет —
обнаруживается сторожем медиа, то есть через media_timeout секунд (по умолчанию 20). Это и есть
верхняя граница задержки переключения в худшем случае. Слишком малые значения media_timeout дадут
ложные срабатывания у источников с редкими опорными кадрами.
Резервируется источник, а не сервер. Цепочка защищает от отказа камеры или канала до неё. Отказ самого медиасервера ею не покрывается.
У режима по требованию свои правила. Припаркованный поток on_demand не подключается ни к
одному источнику, пока нет зрителей, — цепочка начинает работать с момента появления спроса.
Все звенья цепочки должны быть равнозначны по содержимому. Сервер не перекодирует и не подгоняет параметры: если резерв отдаёт другое разрешение или другой кодек, зритель получит смену параметров прямо в потоке. Не все плееры переживают такое одинаково хорошо — по возможности назначайте резервом второй профиль той же камеры или равноценный источник.
source_timeout= у отдельного звена не работаетФорма input <url> source_timeout=N; разбирается и сохраняется, но ни один приёмник её не читает —
задать разное время ожидания для разных звеньев цепочки нельзя. Общее время ожидания задаётся
глобальным media_timeout.
Типовые схемы#
Второй профиль той же камеры. Основной поток — главный профиль, резерв — субпоток. Если камера теряет главный поток, зритель продолжает смотреть в меньшем разрешении:
stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/102; }
Две независимые камеры на одну точку. Основная и дублирующая камера снимают один и тот же объект:
stream entrance { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; input rtsp://admin:пароль@10.0.0.11:554/Streaming/Channels/101; }
Заглушка вместо чёрного экрана. Последним звеном ставится файл или синтетический источник — зритель вместо «нет сигнала» видит осмысленную заставку, а поток остаётся живым и записывается:
vod library /srv/media; stream cam1 { input rtsp://admin:пароль@10.0.0.10:554/Streaming/Channels/101; input file:///srv/media/no-signal.mp4; }
Со звеном-заглушкой поток всегда alive, поэтому обычные проверки живости перестают ловить отказ
камеры. Стройте оповещение на active_source_idx, а не на alive.
Переключение на стороне клиента#
Цепочка input защищает приём. Если требуется, чтобы зритель сам переходил на другой поток —
например, при отказе целого сервера, — это делается на стороне плеера: страница получает список
адресов и переключается между ними. Встроенный плеер сам такого списка не ведёт; для этого
достаточно собственной страницы, которая меняет src встроенного кадра. См.
Встраиваемый плеер.
Куда двигаться дальше#
- Приём видео: обзор — переподключение, сторож медиа и признаки отказа источника.
- RTSP, HLS, DASH, MPEG-TS — формы адресов для звеньев цепочки.
- Мониторинг и метрики — на чём строить оповещения.