Резервный стрим для трансляций 24/7 (Nginx-rtmp-backup | Ubuntu) – Mikulski
Наложение сайта

Резервный стрим для трансляций 24/7 (Nginx-rtmp-backup | Ubuntu)

Я давно подумывал о том, чтобы поднять еще один самый простенький VPS для Youtube-стрима Mikulski_Radio. Потому что в отличие от остальных площадок, Youtube очень чувствителен даже к коротким дисконнектам: малейший чих – и трансляцию приходится создавать заново. Особенно печально в тех нередких случаях, когда нужно внести правки в скрипт радио и ,соответственно, перезапустить его. Да и просто классно сохранить все накопленные лайки для “бесконечной” трансляции. Благо, что по умолчанию (в отличие от остальных платформ), Youtube выдает дополнительный backup ключ, который и нужен как раз для того, чтобы в случае падения основного стрима, произошло переключение на запасной поток.
Когда я для этого настроил стрим-заглушку на новом VPS (по этой моей инструкции) и запустил в работу, то подумал, а почему бы не поискать решение и для всех остальных площадок?
Я логично предположил, что умельцы должны были придумать какой-либо апгрейд для Nginx-rtmp модуля. И действительно, первый же запрос в Гугле вывел меня на комплект скриптов Nginx-rtmp-backup, опубликованный на Github.

ДИСКЛЕЙМЕР:
Я не программист и не линуксоид, а лишь энтузиаст-копипастер, который делится тем, в чем смог разобраться. Поэтому, не исключено, что знающие специалисты некоторые моменты или формулировки могут счесть неправильными или нелепыми.

Подача данного материала предполагает, что вы обладаете базовым уровнем знаний команд linux-терминала, а также понимаете принцип работы и настройки конфига Nginx-Rtmp-модуля.
Как бы то ни было, следующие статьи и туториалы помогут вам разобраться:
Свой Рестрим-Сервер (Nginx RTMP)
Как я сделал свое Стрим-Радио 24/7(Ffplayout)
Создание 24/7 радио-стрима (Liquidsoap)
Создание 24/7 радио-стрима ч.2 (Liquidsoap)

Nginx-rtmp-backup

Суть этого решения проста, но немного заковыриста при попытке объяснить.
В Nginx-rtmp-модуле создается три Rtmp-приложения/адреса (application): основной стрим (main), запасной (backup) и конечный (out).
Для конфигов main и backup указываются специальные операторы, реагирующие на события публикации (exec_publish) или остановки стримов (exec_publish_done).
Эти операторы шлют в терминал shell-команду для активации нужного скрипта, отвечающего за запуск/остановку экземпляра avconv, ffmpeg или gstreamer на выбор .
avconv|ffmpeg|gstreamer копирует все параметры кодировщика основного/запасного стрима и транслирует его в out – видимый зрителю.

Получается следующее:

  • main и backup параллельно начинают свое воспроизведение
  • avconv|ffmpeg|gstreamer подхватывает main и начинает транслировать его в out
  • main по какой-либо причине останавливается
  • первый экземпляр avconv|ffmpeg|gstreamer для main закрывается и запускается новый, который подхватывает backup и начинает его транслировать в out
  • когда main восстанавливает свое воспроизведение, то avconv|ffmpeg|gstreamer закрывает backup и снова направляет main в out.

При этом, дополнительная нагрузка этих процессов небольшая (в моем случае, при стриме 720p с битрейтом 3000k):

  • 2-3,5% ЦПУ и 15mb ОЗУ для экземпляра gstreamer
  • 1,5-2,5% ЦПУ; 10mb ОЗУ для nginx worker process

Единственный минус такого подхода в том, что на переключение источников уходит несколько секунд, а потому настроить бесшовное переключение на аварийный поток не представляется возможным. Тем не менее, gstreamer имеет наименьшую задержку и по сравнению с ffmpeg делает это за пару мгновений.
А еще у меня есть некоторые сомнения в стабильности работы gstreamer в режиме 24/7. Пока что еще не получилось протестировать на ощутимо продолжительной дистанции, чтобы сделать какие-либо выводы на этот счет.

Установка и настройка

На Github и внутри самих скриптов прилагаются подробные инструкции и комментарии, поэтому проблем возникнуть не должно. Однако, так как мы будем использовать gstreamer, который не предусмотрен в качестве опции в репозитории первоисточника, то воспользуемся уже модифицированным форком.

Предположим, что у нас уже установлен Nginx и Rtmp-модуль к нему (туториал).
Понадобится gstreamer:

sudo apt-get install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools

Переходим в директорию, которая может быть прочитана Nginx, клонируем туда репозиторий и открываем только что скопированную папку:

cd /usr/local/share
sudo git clone https://github.com/hosseini92/nginx-rtmp-backup.git
cd nginx-rtmp-backup

Теперь нужно отредактировать config.sh
Там можно изменить имена для Rtmp-applications (вместо main, backup, out), определить поведение (будет ли backup обратно переключаться на main, когда тот возобновит работу или нет) и выбрать что использовать в качестве прокладки (avconv|ffmpeg|gst). Но, чтобы не запутаться, оставим все по умолчанию, кроме

# username for nginx worker processes
NGINX_USER="nobody"
# group for NGINX_USER
NGINX_GROUP="nogroup"

Указываем тут свои логин и группу sudo-пользователя (их можно посмотреть введя в терминал команду id).
Далее выдаем права на выполнение скрипту init.sh и запускаем его:

sudo chmod a+x init.sh
sudo ./init.sh

Теперь можно править конфиг Nginx.

Обязательно меняем самую первую строчку user и вписываем туда имя пользователя, которого указывали ранее в NGINX_USER. По умолчанию, там определен www-data (или что-то вроде). На этом я потерял просто кучу времени, так как несовпадающие имена приводили к тому, что операторы exec не запускали скрипты.

user <USER>;

Теперь спускаемся в секцию rtmp и добавляем следующее:

rtmp {
	server {
		listen 1935;

		application out {
			live on;
		}

		application main {
			live on;
			play_restart on;
			exec_publish /usr/local/share/nginx-rtmp-backup/main_publish.sh $name;
			exec_publish_done /usr/local/share/nginx-rtmp-backup/main_publish_done.sh $name;
		}

		application backup {
			live on;
			play_restart on;
			exec_publish_done /usr/local/share/nginx-rtmp-backup/backup_publish_done.sh $name;
		}
	}
}

Соотвественно, никто не запрещает в out прописать рестримы на любые желаемые площадки, разрешить публикацию только с определенных IP, запретить подключаться к main и out и любые прочие желаемые настройки. Главное, чтобы строки с exec_publish и exec_publish_done оставались на своих местах. Например:

rtmp {
	server {
		    listen 1935;
            chunk_size 4096;
            allow publish 127.0.0.1;
            deny publish all;

		application out {
			live on;
            push rtmp://stream.dlive.tv/live/<key>;
            push rtmp://a.rtmp.youtube.com/live2/<key>;
		}

		application main {
			live on;
			play_restart on;
            allow play 127.0.0.1;
            deny play all;        
			exec_publish /usr/local/share/nginx-rtmp-backup/main_publish.sh $name;
			exec_publish_done /usr/local/share/nginx-rtmp-backup/main_publish_done.sh $name;
		}

		application backup {
			live on;
			play_restart on;
			exec_publish_done /usr/local/share/nginx-rtmp-backup/backup_publish_done.sh $name;
		}
	}
}

Теперь остается только запустить стримы по соответствующим адресам и с одинаковым ключом. Допустим, ключ придумаем – stream, тогда:
Для main это будет rtmp://ваш.домен/main/stream
Для backup, соответственно, rtmp://ваш.домен/backup/stream
Итоговая трансляция будет доступна по адресу: rtmp://ваш.домен/out/stream и на всех площадках куда вы обозначили рестрим источника.

Логи сохраняются в директорию /var/log/nginx-rtmp-backup

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии