NGINX + nginx-rtmp-module — трансляция видео с веб-сервера
Вещание видео будет осуществляться с помощью модуля для nginx — nginx-rtmp-module.
Для этого необходимо собрать веб-сервер nginx из исходников, включив вышеназванный модуль.
Содержание:
Сборка программного обеспечения
Захват видео с камер
Несколько камер
Запись
HLS
MPEG-DASH
Директивы
Сборка NGINX + nginx-rtmp-module
Для удобства работы с nginx, сначала мы установим его из пакетов, хотя бы, чтобы создались скрипты автозапуска.
Установка nginx и пакетов для сборки
Ubuntu:
apt-get install nginx libpcre++-dev libssl-dev libxslt1-dev libgd2-xpm-dev libgeoip-dev
CentOS:
Настраиваем репозиторий:
vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
yum install nginx pcre-devel openssl-devel
Сборка из исходников
Смотрим версию установленного пакета:
nginx -v
Теперь переходим по ссылке https://nginx.org/download и копируем ссылку на установленную версию nginx (архив tar.gz). В моем случае, это была версия 1.10.0.
* обратите внимание, что в данном списке версии идут не по порядку — ориентируйтесь по дате (средняя колонка).
Скачиваем исходник:
wget http://nginx.org/download/nginx-1.10.0.tar.gz
Скачиваем модуль:
wget https://github.com/arut/nginx-rtmp-module/archive/master.tar.gz
Распаковываем исходник nginx и модуль:
tar xzf nginx-1.10.0.tar.gz
tar xzf master.tar.gz
И переходим в распакованный каталог nginx:
cd nginx-1.10.0
Смотрим, с какими опциями собран уже установленный nginx:
nginx -V
Копируем текст, который идет после configure arguments:
Теперь конфигурируем nginx со скопированными опциями + --add-module=../nginx-rtmp-module-master. Получиться что-то на вроде:
./configure --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=../nginx-rtmp-module-master
Собираем исходник:
make
И выполняем установку:
make install
Запускаем веб-сервер:
systemctl start nginx
Настройка захвата видео
Если используется брандмауэр, не забываем добавить в разрешения tcp порт 1935.
Установка утилит
Ubuntu:
apt-get install ffmpeg rtmpdump
CentOS:
Устанавливаем расширенный репозиторий пакетов EPEL:
yum install epel-release
Тянем дополнительный репозиторий:
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
Теперь можно устанавливать пакеты:
yum install ffmpeg rtmpdump
Настройка NGINX
Открываем на редактирование следующий файл:
vi /etc/nginx/nginx.conf
И дописываем следующее:
rtmp {
server {
listen 1935;
application cam1 {
live on;
}
}
}
* важно, чтобы данный блок шел не внутри, а отдельно от основного http.
Перезагружаем сервис:
systemcl restart nginx
На данном этапе мы настроили простейший rtmp-сервер, который сможет принимать запросы на передачу видео.
Чтобы проверить его работу, воспользуемся ранее установленной утилитой ffmpeg:
ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream
* где admin:admin — логин и пароль на подключение к веб-камере; 192.168.0.12 — IP-адрес камеры; cam1 — имя application, которое мы задали в конфигурационном файле nginx; stream — произвольное название для потока.
В подтверждение правильного выполнения команды, мы увидим что-то наподобие:
frame= 1381 fps= 26 q=-1.0 size= 27586kB time=00:00:55.27 bitrate=4088.6kbits/
frame= 1394 fps= 26 q=-1.0 size= 27822kB time=00:00:55.79 bitrate=4085.1kbits/
frame= 1407 fps= 26 q=-1.0 size= 28131kB time=00:00:56.31 bitrate=4092.5kbits/
frame= 1420 fps= 26 q=-1.0 size= 28371kB time=00:00:56.83 bitrate=4089.6kbits/
frame= 1433 fps= 26 q=-1.0 size= 28609kB time=00:00:57.35 bitrate=4086.5kbits/
frame= 1446 fps= 26 q=-1.0 size= 28852kB time=00:00:57.87 bitrate=4084.1kbits/
Теперь можно запустить приложение воспроизведения видео, например, VLC плеер и подключиться к веб-серверу (Медиа - Открыть URL):
Вводим URL: rtmp://192.168.0.100/cam1/stream
* где 192.168.0.100 — IP-адрес сервера nginx; cam1 — наш application; stream — наше произвольное название для потока.
Если мы увидим видео с камеры, значит все настроено верно.
Теперь прерываем работу ffmpeg и открываем конфиг nginx:
vi /etc/nginx/nginx.conf
И добавляем следующее:
rtmp {
server {
listen 1935;
application cam1 {
live on;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream;
}
}
}
Перезапускаем nginx:
systemctl restart nginx
И снова, но уже не запуская вручную ffmpeg, проверяем наличие видеопотока при помощи VLC.
Несколько камер
Открываем nginx.conf:
vi /etc/nginx/nginx.conf
Настраиваем автоматическое определение воркеров:
worker_processes auto;
* оптимальное число одновременных потоков, позволит nginx работать быстрее.
В корень конфига добавляем:
rtmp_auto_push on;
* включает локальные ретрансляции для использования нескольких воркеров.
Теперь переходим к настройкам rtmp и приводим наш конфиг к следующему виду:
rtmp {
server {
listen 1935;
application cam1 {
live on;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream;
}
application cam2 {
live on;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam2/stream;
}
}
}
На самом деле, его можно также настроить так:
rtmp {
server {
listen 1935;
application cam1 {
live on;
}
application cam2 {
live on;
}
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam2/stream;
}
}
Или так:
rtmp {
server {
listen 1935;
application cams {
live on;
}
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cams/stream1;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cams/stream2;
}
}
И перезапускаем nginx:
systemctl restart nginx
Запись
Для хранения видео на сервер, есть также несколько варинатов настройки.
1-й вариант: использование нескольких application. В каждом из них своя папка для хранения видео:
rtmp {
record all;
live on;
server {
listen 1935;
application cam1 {
record_path /tmp/record1;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream;
}
application cam2 {
record_path /tmp/record2;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam2/stream;
}
}
}
Создаем папки:
mkdir /tmp/record1 /tmp/record2
Задаем права (владельца):
chown nginx:nginx /tmp/record*
2-й вариант: один application с разными именами для потоков:
rtmp {
server {
listen 1935;
application cams {
live on;
record all;
record_path /tmp/record;
}
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cams/stream1;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cams/stream2;
}
}
Необходимо также создать папку и задать владельца:
mkdir /tmp/record
chown nginx:nginx /tmp/record
и не забываем перезагрузить nginx:
systemctl restart nginx
Полезные опции для записи
record_suffix -%Y-%m-%d-%H-%M-%S.flv;
record_max_size 5120K;
record_interval 3m;
record_suffix — добавляет окончание к каждому созданному файлу.
record_max_size — ограничивает размер каждого файла определенным объемом (в данном примере, 5 Мб). При лимите, будет создан новый файл.
record_interval — ограничивает файл видеофрагментом в несколько минут (в нашем примере, 3).
HLS
Прежде, чем начать, убедитесь, что брандмауэр отключен или пропускает http-запросы. Selinux на момент проведения тестов, лучше отключить.
Протокол HLS позволяем транслировать потоковое видео поверх HTTP. Это позволит сэкономить ресурсы сервера при множественном обращении и создать более кроссплатформенную инфраструктуру.
Для его включения, приводим наш nginx.conf к следующему виду:
rtmp {
live on;
hls on;
hls_fragment 5s;
server {
listen 1935;
application cam1 {
hls_path /tmp/cam1;
}
application cam2 {
hls_path /tmp/cam2;
}
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam1/stream;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c copy -f flv rtmp://127.0.0.1/cam2/stream;
}
}
Перезапуск:
systemctl restart nginx
Ждем 4-5 секунд и смотрим содержимое папок в /tmp:
ls /tmp/cam1
ls /tmp/cam2
Внутри каждой из них мы должны увидеть файл с расширением m3u8 — это плейлист с видеонарезками. Если файлы есть, значит HLS заработал.
Осталось научить наш NGINX отдавать данные файлы. Для этого в секции http добавим:
location / {
root /tmp;
}
И снова:
systemctl restart nginx
В том же VLC для проверки вводим следующий URL:
http://192.168.0.100/cam1/stream.m3u8
MPEG-DASH
Как альтернатива HLS, используется для видеотрансляции поверх HTTP. Его основные преимущества — поддержка со стороны большого количества браузеров и работа на javascript-плеере.
И так, его настройка сильно напоминает настройку HLS. В конфиге NGINX:
rtmp {
live on;
dash on;
server {
listen 1935;
application cams {
dash_path /tmp/cams;
}
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.12:554/Streaming/Channels/1/ -c:v libx264 -profile:v baseline -c:a libfaac -ar 44100 -f flv rtmp://127.0.0.1/cams/stream1;
exec_static ffmpeg -i rtsp://admin:admin@192.168.0.13:554/Streaming/Channels/1/ -c:v libx264 -profile:v baseline -c:a libfaac -ar 44100 -f flv rtmp://127.0.0.1/cams/stream2;
}
}
* обратите внимание, здесь мы решили настроить все в одном application с разными потоками для каждой камеры. И не потому, что так нужно для MPEG-DASH — скорее для демонстрации возможности различных способов конфигурации.
** также можно заменить, что мы добавили опции конвертации потока при переводе его в RTMP — это важно для MPEG-DASH.
Перезапускаем nginx:
systemctl restart nginx
Проверяем появление файлов с расширением .mpd.
ls /tmp/cams
Если они есть, переходим в /tmp
cd /tmp
И выполняем следующую команду:
git clone https://github.com/arut/dash.js.git
* мы скачали js-плеер для просмотра dash-видео.
** по хорошему, в продуктивной среде следует создать отдельный виртуальный домен и хранить все файлы в специальной выделенной директории, а не в каталоге /tmp. Для теста это не принципиально.
И создаем новую ветку live:
cd dash.js
git checkout live
Проверим работу плеера. Открываем браузер и вводим следующий URL:
http://192.168.0.100/dash.js/baseline.html
* где 192.168.0.100 — IP-адрес нашего видео-сервера.
И нажимаем play — начнется показ демонстративного видео.
Теперь откроем файл baseline.html внутри папки dash.js:
vi /tmp/dash.js/baseline.html
Найдем строчку:
url = "http://dash.edgesuite.net/envivio/dashpr/clear/Manifest.mpd",
И заменим ее на:
url = "http://192.168.0.100/cams/stream1.mpd",
* где cams — наш application; stream1 — имя потока с первой камеры.
И снова открываем браузер и вводим:
http://192.168.0.100/dash.js/baseline.html
Полезные директивы
respawn_timeout 15s;
chunk_size 8192;
respawn_timeout — время ожидания перед повторным запуском дочернего процесса. По умолчанию, 5 секунд.
chunk_size — максимальный размер порции для мультиплексирования потока. По умолчанию, 4096.
Полный перечень директив опубликован Романом Арутюняном по ссылке: