Всё началось с того, как при мне с помощью OBS Studio и какой-то программки для анимации обоев рабочего стола сделали из логотипа видеологотип (который еще и под текущую играющую музыку анимировался). В тот момент я понял что OBS Studio может НАМНОГО больше, чем просто стримить игры. После более близкого знакомства с OBS Studio, она претендует на место самой крутой программы, которую я когда-либо встречал.
Мне предстояло стримить небольшой ивент для друзей, но поскольку у меня есть оборудование для хорошего звука и желание делать круто, я озадачился организацией стрима с отдельным звуком и несколькими камерами. Стрим по разным причинам получился такой себе, но после этого опыта, я вроде бы представляю как надо. И хочу поделиться. Вот.
Что?
Идея заключается в том, чтобы найти 2-3 беспроводных оператора, которые ходят по разным площадкам мероприятия, общаются с людьми, снимают движуху, и т.д. (ну, как у серьезных ребят, короче). А кто-то сидит, коммуницирует с ними по рации, и формирует из всего этого (и еще чего-нибудь, например, сдержимого всякого рода окошек/мониторов/проекторов) интересный видеоконтент, который не скучно смотреть.
Также можно объединять экраны нескольких компьютеров в один стрим, возможно это может быть полезно для игр. Хотя скорее всего конкретно для этой задачи есть и другие технологии.
Зачем?
Потому что это позволяет делать очень круто и сильно сместить технологический потолок качества стрима практически задаром.
При использовании кучи видеопотоков, крутота стрима будет определяться уже творческой и организационной составляющей (ну и качеством соединений).
Чем?
- Ноут
1.1. OBS Studio
1.2. nginx с модулем RTMP - Операторы со своими смартфонами
2.1. Какая-нибудь приложуха из выдачи по запросу "stream rtmp", например Larix Broadcaster, или (если есть немного лишних денег) Ace Live Streaming или BitStream - Стабильный вайфай, желательно 5GHz
- Стабильный аплинк
При наличии еще чего-нибудь, можно сделать хороший звук, хотя бы на стационарных камерах (которые могут быть любыми относительно качественными вэбками).
А при наличии еще одной ЭВМ на линуксе (говорят, даже Raspberry Pi ок для ≤3 потоков), можно немного разгрузить основной комп и его сеть для обработки и отправки стрима.
Как?
Общепризнанный протокол для видеостриминга — RTMP. Попытки юзать что-то еще ведут к диким лагам, это была моя главная ошибка.
Справедливости ради, стоит отметить проприетарную технологию NewTek NDI (спасибо, Alexsey), которая вроде как круче, чем RTMP. Однако, для нашего юз-кейса, использование NDI потребует немало лишних денег.
Оказывается, принять RTMP-стрим и перенаправить его в OBS Studio — проще простого. Надо всего-то скомпилировать nginx с кастомным модулем и написать конфиг. Но об этом позже.
По-хорошему, надо делать как-то так:
То-есть не давать мобилкам Интернет, чтобы они не тратили ресурсы ни на что кроме стрима.
Но ежели хороший вайфай с Интернетом уже есть (а лишней точки доступа на 5GHz нет), то можно не брезговать и юзать существующие соединения. Однако, отправлять конечный стрим всё-таки желательно с другого соединения, или, в крайнем случае, с того же, но через провод.
Если есть необходимость принимать стримы с камер и отправлять конечный стрим через один и тот же вайфай, тщательно протестируйте стабильность (и учтите, что она сильно снизится если на этот вайфай полезет толпа девайсов).
Как поднять RTMP-сервер?
Лучше делать это на линуксе, чтобы не испытывать проблем со всякими MINGW/MSYS. И на отдельном железе (не обязательно мощном). Либо в докере, тогда можно скипнуть этот раздел, ибо докерфайл уже есть. Через WSL тоже можно, но надо будет вручную пробросить TCP-порт 1935 в файрволе.
Вот отличный мэнуал How to set up your own private RTMP server using nginx, и в доке тоже годно написано. Краткий пересказ в вольном стиле:
Ставим зависимости:
sudo apt install build-essential libpcre3 libpcre3-dev libssl-dev
Качаем последнюю Mainline версию исходников отсюда:
wget http://nginx.org/download/nginx-1.15.2.tar.gz # Check for newer versions tar xzf nginx-* && cd !$
Качаем последнюю версию RTMP-модуля:
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip -O rtmp-module.zip unzip !$ -d .
Создаём Makefile:
./configure --with-http_ssl_module --add-module=./nginx-rtmp-module-master
Если свалится не дойдя до
Configuration summary
, исправляем проблемы.
Эта команда настроит Ваш стримерский nginx жить в/usr/local/nginx/
и запускаться по командеsudo /usr/local/nginx/sbin/nginx
. Таким образом nginx из репозитория ничего не почувствует. Это можно поменять, изучив./configure --help
.
Компилируем:
make -j4
Устанавливаем:
echo "nginx with RTMP module" > description-pak sudo checkinstall --pkgname nginx-rtmp --provides nginx --nodoc --deldesc -y sudo mkdir /usr/local/nginx/logs/ # Doesn't start without it
В принципе через
make install
в данном случае безопасно, но всё-таки не надо так.
Проверяем
$ /usr/local/nginx/sbin/nginx -v nginx version: nginx/1.15.2
Настраиваем
sudo vim /usr/local/nginx/conf/nginx.conf
В конец добавляем конфиг RTMP-сервера:
rtmp { server { listen 1935; application live { live on; record off; } } }
При желании, можно настроить HTTP-сервер на отображение статистики.
В доке описано что еще можно настроить, там действительно очень много всего. Если Вы знаете как сделать лучше, буду рад добавить раздел про конфигурацию сервера с материалом из комментариев.
Делаем удобно
alias rtmp-start="sudo /usr/local/nginx/sbin/nginx" alias rtmp-stop="sudo /usr/local/nginx/sbin/nginx -s stop" alias rtmp-status="cat /usr/local/nginx/logs/nginx.pid"
Что делать с RTMP-сервером?
Отправить на него стрим с мобильной приложухи по адресу
rtmp://[ваш локальный IP]:1935/live/habr
гдеlive
— это имя RTMP-приложения в конфиге nginx, аhabr
— это Stream Key, который надо менять для разных камер.
Если Вы настроили показ статистики (и не забыли поменять путь к файлу
stat.xsl
), проверить что стрим пришёл (по адресу http://localhost:8080/stat).
Подключить ко всем стримам OBS Studio.
PROFIT!!!
Очевидно, что сервер может быть не только локальным, но и доступным из внешки, что позволит делать всё то же самое, но не через вайфай, а через Интернет. Можно сделать свой аналог инстаграмовских групповых стримов, ну и вообще, безграничные возможности ))
Всё?
Есть еще пара вещей, которые я познал на ошибках и хотел бы поделиться:
- Можно и нужно менять целевой битрэйт конечного стрима по ходу трансляции, и подстраиваться под возможности соединения. Restream, например, рисует крутые графики, по которым понятно на сколько надо понижать. Есть Pull Request на автоподбор битрэйта, но он заглох ((
- Существует такой параметр Keyframe Interval, и он должен быть больше секунды (это надо вручную задавать в Advanced-версии настроек Output). Restream об этом рассказывает только после окончания стрима, UX на высоте! ))
- Есть еще один крайне полезный Pull Request, в котором я поучаствовал, и за который активно топлю, но он тоже выглядит заглохшим, хотя мэйнтейнер про него недавно вспомнил и переосмыслил. Лайкните, плиз, если Вам тоже кажется, что отсутствие кнопки Monitor на аудио-каналах — это ужасно.
Вот теперь точно всё, спасибо за внимание ^_^
P.S.
Для тех кто попытается всё-таки сбилдить nginx для вездесущей венды, вот грабли по которым я прошелся, тот еще квест оказался, я не зря этого процесса так опасался:
- Необходимо брать исходники ИМЕННО из Mercurial (хорошо что там есть кнопка "скачать zip"), в архивах с сайта нет папки
src\os\win32
. Если у Вас исходники с сайта, будет ошибкаdon't know how to make 'src/os/win32/ngx_win32_config.h'
. - Нужен древний MinGW отсюда а не
чуть менее древнийMSYS2. - При установке
mingw-developer-toolkit
нужно снять чекбокс с Perl. Perl должен быть виндовым. - Вот этот ответ хорошо помог.
- При компиляции используется
rc.exe
из%ProgramFiles(x86)%\Windows Kits\10\bin\10.0.16299.0\x64
, надо эту папку вручную в PATH добавить - Надо убрать флаг
-WX
изCFLAGS
в Makefile, чтобы ворнинги не прерывали компиляцию, там в 1.15.3 есть ворнинги...
Итого, у меня получилось как-то так:
#cmd: "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
#cmd: set PATH=%PATH%;%ProgramFiles(x86)%\Windows Kits\10\bin\10.0.16299.0\x64
#cmd: C:\MinGW\msys\1.0\msys.bat
#bash: cd nginx-1.15.3
./auto/configure \
--with-cc=cl \
--with-debug \
--prefix= \
--conf-path=conf/nginx.conf \
--pid-path=logs/nginx.pid \
--http-log-path=logs/access.log \
--error-log-path=logs/error.log \
--sbin-path=nginx.exe \
--http-client-body-temp-path=temp/client_body_temp \
--http-proxy-temp-path=temp/proxy_temp \
--http-fastcgi-temp-path=temp/fastcgi_temp \
--http-scgi-temp-path=temp/scgi_temp \
--http-uwsgi-temp-path=temp/uwsgi_temp \
--with-cc-opt=-DFD_SETSIZE=1024 \
--with-pcre=objs/lib/pcre-8.42 \
--with-zlib=objs/lib/zlib-1.2.11 \
--with-openssl=objs/lib/openssl-1.1.1 \
--with-openssl-opt=no-asm \
--with-select_module \
--with-http_ssl_module \
--add-module=nginx-rtmp-module-master
nmake