
Когда Роман Арутюнян (rarutyunyan) выпустил модуль nginx-rtmp-module, это сильно перевернуло взгляд на доступность организации видеовещания. До этого, это казалось каким-то дорогим и сложным делом.
31 декабря Adobe официально хоронит флешплеер и убирает ссылки на скачивание с сайта. Это, конечно, не может не радовать. Эти засранцы то и дело подсовывали включенные по умолчанию галочки, так что даже продвинутому пользователю прилетал вместе с флешплеером еще и какой-то антивирус в лучшем случае. То, что это чудовище бесконечно просило обновлений ручками через браузер, знают все. Ходил даже анекдот, предлагающий создателям флешплеера законодательно ограничить паспорта сроком на 1 неделю с возможностью бесконечной перевыдачи.
Кому сдался флешплеер в конце 2020-го, вы хотите сказать? Да дело в том, что флеш плеер единственный поддерживал воспроизведение протокола rtmp в браузере с относительно низкой задержкой. Да и он не так уж и плох, учитывая, что по умолчанию все стриминговые сервисы, youtube или twitch из кодировщика просят передавать им видео по протоколу rtmp. Конечно, приходит более свежий SRT но разговор не об ��том.
Вы убрали возможность играть видео в браузере по rtmp, а где альтернативы-то?
Форматы, работающие по http требуют хорошей буферизации. Задержка выливается в 15 секунд. Если вы общаетесь со своей аудиторией онлайн, это неприемлемо. WebRTC решения плохо дружат с реализацией один ко многим. Ну как плохо, плати, и будет хорошо. Cофт есть на рынке. Только беда еще с покрытием, по моим ощущениям, WebRTC только только нащупал какую-то стабильную фазу, при которой его можно использовать. Но все равно есть небольшие проблемы с форматами видео на разных платформах. Раньше все это выглядело так ужасно, что проще было просить ставить флешплеер только ради малой задержки.
В issue к nginx-rtmp-module не я один [1] [2] оставлял вопросы о поддержке форматов передачи видео по http с низкой задержкой (2-3 секунды). Ведь если бы можно было вещать в формате dash и hls до 3 секунд на nginx-rtmp-module, меня бы это полностью устроило. Но ответов на эти вопросы нет. Низкая задержка нужна в 2020 году и без нее ну никак. К сожалению, проект c 2017 года не развивается.
Медиасервер OvenMediaEngine.
Прекрасной альтернативой, отвечающей порывам всех моих желаний, является
- Задержка по WebRTC полсекунды.
- Задержка по dash low latency 2 секунды.
- HLS low latency скоро обещают.
Возможности:
- RTMP Push, MPEG2-TS Push, RTSP Pull Input
- WebRTC sub-second streaming
- Embedded WebRTC Signalling Server (WebSocket based)
- ICE (Interactive Connectivity Establishment)
- DTLS (Datagram Transport Layer Security)
- SRTP (Secure Real-time Transport Protocol)
- ULPFEC (Forward Error Correction) with VP8, H.264
- In-band FEC (Forward Error Correction) with Opus
- Low-Latency MPEG-DASH streaming (Chunked CMAF)
- Legacy HLS/MPEG-DASH streaming
- Embedded Live Transcoder (VP8, H.264, Opus, AAC, Bypass)
- Origin-Edge structure
- Monitoring
- Experiment
- P2P Traffic Distribution
- RTSP Pull, MPEG-TS Push Input
Так как команда активно развивает медиасервер, для быстрых апгрейдов я решил использовать предложенную ими установку через докер, накатывая внутрь контейнера всего две вещи: сертификаты от Lets Encrypt и файл настройки сервера.
С моей точки зрения из-за свежести проекта, документация OvenMediaEngine хоть и включает страницу с быстрым стартом, но не рассказывает о best default practice. Вникая во все это самостоятельно, выделил две проблемы с подачей материала и почувствовал что нужна статья.
- Показывают, как работают примеры по http и ws протоколу, хотя, очевидно, показывать нужно сразу, как работать на https и wss, все равно же придется заново все перенастраивать. К тому же, о прикреплении бесплатных сертификатов от Lets Encrypt в документации ни слова, хотя официально полностью поддерживают.
- Аналогично, после настройки и запуска сервера точка входа публично доступна для всех.(как и у nginx-rtmp-module) Нужно сразу показывать, как защищать точку входа.
Это все мелочи. Похвалю за очень удобные средства отладки. Они предлагают две страницы
http://demo.ovenplayer.com
https://demo.ovenplayer.com
http и https для отладки сервера. Более того, внесенные настройки сразу же отражаются как GET параметры в адресной строке — это чертовски удобно тестировать между браузерами. Поверьте, путаница в протоколах, портах, описках в урлах при первой подготовке сервера то еще занятие! А так, сохранил ссылку в браузере в закладках да и возвращайся когда нужно к настройке!
Установка. Быстрый старт
Итак, я возьму 20-ую Убунту.
https://airensoft.gitbook.io/ovenmediaengine/v/0.10.10/getting-started
docker run -d \
-p 1935:1935 -p 4000-4005:4000-4005/udp -p 3333:3333 -p 8080:8080 -p 9000:9000 -p 10000-10010:10000-10010/udp \
airensoft/ovenmediaengine:latest
После ставим certbot. Привязывайте ip к домену, получайте сертификаты.
Далее, получаем имя контейнера докера, например, 87b8610034bc
Server.xml
sudo docker container lsВытащим конфиг из контейнера для редактирования. (Мне удобнее в момент изучения конфига видеть его где-то с подсветкой синтаксиса, поэтому вытаскиваю файл)
sudo docker cp 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml ./Server.xmlСтарый добрый xml.
Выглядит конфиг так
https://github.com/AirenSoft/OvenMediaEngine/blob/master/misc/conf_examples/Server.xml
Раздел VirtualHost. Нам нужно задать имя сервера и указать пути к сертификатам внутри контейнера.
Имя сервера в виде звездочки "*" или еще дополнительные имена в конфиге не позволят запуститься OME корректно при использовании TLS.
<Host>
<Names>
<Name>stream.***.ru</Name>
</Names>
<TLS>
<CertPath>/opt/ovenmediaengine/bin/cert.pem</CertPath>
<KeyPath>/opt/ovenmediaengine/bin/privkey.pem</KeyPath>
<ChainCertPath>/opt/ovenmediaengine/bin/chain.pem</ChainCertPath>
</TLS>
</Host>
Затем, нужно оставить только TLSPort порты.
<Publishers>
<HLS>
<TLSPort>${env:OME_HLS_STREAM_PORT:8080}</TLSPort>
</HLS>
<DASH>
<TLSPort>${env:OME_DASH_STREAM_PORT:8080}</TLSPort>
</DASH>
<WebRTC>
<Signalling>
<TLSPort>${env:OME_SIGNALLING_PORT:3333}</TLSPort>
</Signalling>
</WebRTC>
</Publishers>
Почему я рекомендую указывать те же порты, что и использовались для http? Сервер иначе не стартанет на одинаковых портах (не умеет), а выдумывать новые порты, когда при установке докера разработчики уже сделали в примере биндинги для контейнера, лишнее.
Заливаем конфиг обратно
sudo docker cp ./Server.xml 87b8610034bc:/opt/ovenmediaengine/bin/origin_conf/Server.xml
И, соответственно, по заданным путям мы кидаем наши ключи
docker cp /etc/letsencrypt/live/stream.*.ru/chain.pem 87b8610034bc:/opt/ovenmediaengine/bin/
docker cp /etc/letsencrypt/live/stream.*.ru/privkey.pem 87b8610034bc:/opt/ovenmediaengine/bin/
docker cp /etc/letsencrypt/live/stream.*.ru/cert.pem 87b8610034bc:/opt/ovenmediaengine/bin/
Перезапуск
sudo docker restart 87b8610034bcПробуем.
Урл вещания в obs
rtmp://stream.*.ru:1935/appключ ‘stream’

Линки для паблика
dash https://stream.*.ru:8080/app/stream/manifest.mpd
dash ll https://stream.*.ru:8080/app/stream/manifest_ll.mpd
hls https://stream.*.ru:8080/app/stream/playlist.m3u8
webrtc wss://stream.*.ru:3333/app/stream/Если после запуска трансляции в OBS все хорошо и по линкам отдается манифест, можете проверить видео на странице с плеером.
Подписывание ссылок
OME так устроен, что позволяет создать публичные линки с разными правами. Например, одну и туже ссылку можно ограничить ip диапазоном или временем работы по разному для разных людей. Изменения в настройки сервера при этом вносить не нужно. Они используют схожую логику как у гугла Sign Policy.
1. Добавить блок SignedPolicy в секцию VirtualHost в Server.xml
<SignedPolicy>
<PolicyQueryKeyName>policy</PolicyQueryKeyName>
<SignatureQueryKeyName>signature</SignatureQueryKeyName>
<SecretKey>secretkey</SecretKey>
<Enables>
<Providers>rtmp</Providers>
<Publishers>webrtc,hls,dash,lldash</Publishers>
</Enables>
</SignedPolicy>
После этого, вы не сможете ни посылать поток по старой ссылке в OBS ни принимать трафик по публичным ссылкам без подписей.
2. Запускаем signed_policy_url_generator.sh с параметрами, описанными внутри.
Например:
sudo bash ./signed_policy_url_generator.sh secretkey rtmp://stream.***.ru:1935/app/stream signature policy '{«url_expire»:8807083098927}'
url_expire — обязательный параметр, который просит в миллисекундах (это не unix timestamp, а currentmillis.com ) указать, когда истечет ссылка.
результат:
rtmp://stream.***.ru:1935/app/stream?policy=eyJ1cmxfZXhwaXJlIjo4ODA3MDgzMDk4OTI3fQ&signature=xjS7NY-l4lY1f9e9sOiRNhPtAqIrtmp://stream.***.ru:1935/app — идет в OBS в Server, остальная часть — в «Stream key».

3. Если OBS стартанул трансляцию, теперь нужно обязательно подписать необходимые публичные ссылки. Например для WebRTC.
sudo bash ./signed_policy_url_generator.sh secretkey wss://stream.***.ru:3333/app/stream signature policy '{"url_expire":8807083098927}'Таким образом, не имея доступа к секрету, получить какой либо доступ к OME из дефолтных настроек больше нельзя.
Из настроек остается только прописать докер на автозапуск контейнера с системой. Ну и установить обновление сертификатов на крон, со скриптом, копирующим в контейнер ключи и рестартующим его. Ну или каким-то другим способом, как вы это делаете.
sudo systemctl enable dockersudo docker update --restart unless-stopped 87b8610034bcКодировщик
Ребята считают OBS самым популярным кодировщиком для своего сервера. Поэтому как и в документации, так и более подробно в блоге можно найти подходящие настройки, максимально снижающие задержку в трансляции.
Настройки кодировщика для OBS студии для задержки в половину секунды следующие

Столь малая задержка конечно обходится более низким качеством изображения на пресете zero-latency. Другие пресеты хоть и добавляют задержку около 1.5 секунды, но картинку делают лучше.
Так же у них есть универсальный энкодер для андройда.
https://play.google.com/store/apps/details?id=com.airensoft.ovenstreamencoder.camera
Еще немного о корейской морковке
- Сервер выдает несколько потоков под разные платформы, а плеер уже выбирает нужный под возможности браузера. Единственный минус современного видеовещания, это большие размеры бандлов зависимостей. Например, только DASH.js весит 175 kb gzip.
- В зависимости от указания порядка источников в конфиге OvenPlayer, они будут стартовать соотвественно.
- Когда пользователь выбирает в плеере в качестве источника webrtc, OME на лету конвертирует аудио в требуемый формат opus.(Это требования стандарта.)
- По непонятным для меня причинам, WebRTC не может работать с mono звуком, поэтому не пытайтесь в настройках медиасервера переключать звук со стерео — он не запустится. Это не проблема OME.
Пожелания
- Система логов — это обычные txt файлики. Было бы очень круто иметь чуть более продвинутую визуальную аналитику. Например, знать сколько зрителей онлайн и какой траффик
- Я пробовал новый nginx-unit с его модным json-api в качестве команд управления/конфига. Суть в чем, обновляешь вебсервер, а он продолжает работать, заливаешь сертификаты, а ему не надо перезагружаться, домен, поддомен, добавить заголовки, убрать — все налету без перезагрузки. А поверх json-api появляется миллион офигенно удобных админок с UI. Хотя в OME и вроде бы и нет нужды в таком API, но наверняка кто-то что-то потом обязательно придумает)
Немного о ребятах. Они себя позиционируют как группа экспертов по медиа технологиям, ведут блог с любопытным контентом.
Судя по тому, что они плотно сотрудничают с местными телекомами, чувствуется очень хороший бекграунд для поддержки опенсорса в области стриминга. Это замечательно. Я прикреплю пару фоток из их нового офиса.
Ребята передают всем привет, статью заметили.


