Видео вещание с OvenMediaEngine, до свидания nginx rtmp module

  • Tutorial


Когда Роман Арутюнян (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.


Прекрасной альтернативой, отвечающей порывам всех моих желаний, является корейская морковка опенсорсный проект OvenMediaEngine, предлагающий не только средства кодирования и кластеризации (как у nginx-rtmp-module) но и средства воспроизведения т.е. свой html5 плеер OvenPlayer.  Именно то, чего я так искал, зарелизили наши южнокорейские братья. С большим интересом я крутил его неделю и полностью перебрался на него.

  • Задержка по 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. Вникая во все это самостоятельно, выделил две проблемы с подачей материала и почувствовал что нужна статья.

  1. Показывают, как работают примеры по http и ws протоколу, хотя, очевидно, показывать нужно сразу, как работать на https и wss, все равно же придется заново все перенастраивать. К тому же, о прикреплении бесплатных сертификатов от  Lets Encrypt в документации ни слова, хотя официально полностью поддерживают. 
  2. Аналогично, после настройки и запуска сервера точка входа публично доступна для всех.(как и у 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-l4lY1f9e9sOiRNhPtAqI

rtmp://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 docker

sudo 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.

Пожелания


  1. Система логов — это обычные txt файлики. Было бы очень круто иметь чуть более продвинутую визуальную аналитику. Например, знать сколько зрителей онлайн и какой траффик
  2. Я пробовал новый nginx-unit с его модным json-api  в качестве команд управления/конфига. Суть в чем, обновляешь вебсервер, а он продолжает работать, заливаешь сертификаты, а ему не надо перезагружаться, домен, поддомен, добавить заголовки, убрать — все налету без перезагрузки. А поверх json-api появляется миллион офигенно удобных админок с UI. Хотя в OME и вроде бы и нет нужды в таком API, но наверняка кто-то что-то потом обязательно придумает)

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

Судя по тому, что они плотно сотрудничают с местными телекомами, чувствуется очень хороший бекграунд для поддержки опенсорса в области стриминга. Это замечательно. Я прикреплю пару фоток из их нового офиса.

Ребята передают всем привет, статью заметили.



Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 33

    +1
    А без доскера нельзя?
      0

      Можно конечно! Просто собираете приложение у себя по инструкции и все

        +1

        У него устаревший и патченый ffmpeg, что создаёт проблемы со сборкой на арче


        (А зависимость от libfdk-aac создаёт юридические проблемы с распространением бинарных сборок, чёт мда)

          0

          Я зашёл к таймвебу, у них нет этого дистрибутива по умолчанию для клиентов. Все таки слишком экзотическая ос. А в чем устаревание библиотеки?

            +1

            В том, что уже давно есть ffmpeg 4.3, в то время как OME завязан на ffmpeg 3.4 который имеет кучу мешающих мне багов


            Впрочем, со старым ffmpeg всё-таки худо-бедно собирается и на арче тоже если пропатчить prerequisites.sh, так что ладно. Однако вынужденный отказ от использования системных библиотек мне всё равно не очень нравится

              0
              У меня ночная мозилла не воспроизводит поток dash в h264. Адище с этими выпилинными кодеками какое-то. Хотя webrtc работает.
                0
                Они мне ответили, что апгрейд до 4 версии ffmpeg является топовым приоритетом.
                0
                Арч линукс одна из популярных ОС (на клиенте).
                  0
                  а что за клиент? Типа терминалов?
                    +1

                    Для терминалов головной боли много. Разработчики используют, Линукс энтузиасты в качестве домашней ОС.

            0
            А почему вы ярый противник PWA?
              +2
              "… и веба там, где ему не место", да.

              Потому что веб — это для браузеров. Приложения на Electron требуют слишком много ресурсов для выполнения простых задач ввиду низкого порога вхождения в разработку на JS. Как итог — утилита для записи флешек на 80 мегабайт. Программа, чтобы всего лишь записать флешку, запускает ещё один отдельный инстанс браузера. И текстовый редактор запускает инстанс браузера. И корпоративный мессенджер норовит. И мессенджер для геймеров. Мне, простите, суперкомпьютер купить, чтобы одновременно работать со всем этим? И это всё лишь потому что разработчикам лень кто-то захотел меньший TTM?
                +1
                PWA это же не электрон. Это просто кешированный сайт в браузере, с иконкой на экране телефона.
                  +1
                  Да, я понимаю. Поэтому и дописал продолжение фразы из анкеты. PWA — часть дегенеративной индустрии по изжитию нативных приложений в пользу более ресурсоёмкого веба в угоду «удобству» разработчика.
            +2
            Еще рано отказываться от nginx-rtmp, как минимум из-за того, что ребята все никак не сделают RTMP Pull (ну и M2TS), а из-за этого не подключить к этому делу свой транскодинг.
              0
              Так вроде бы заявлено. RTSP pull и m2ts в бете сейчас вроде бы есть
              airensoft.gitbook.io/ovenmediaengine/v/0.10.10/live-source/rtsp-pull-beta
              airensoft.gitbook.io/ovenmediaengine/v/0.10.10/live-source/mpeg-2-ts-beta
              А в каких случаях это требуется? Для серверов, которые сделаны, чтобы опускать битрейты?
                +1
                Спасибо, не заметил что M2TS уже в бете, видимо давно не заглядывал.
                Да, например это нужно для ABR Ladder'a, ну для всех других кейсов, где с медиа потоками нужно что-то сделать.
                Насколько я помню, то Oven еще не умеет принимать рестрим от nginx-rtmp и всяких энтерпрайз штук как Wirecast (на нем он начинает дико кушать CPU, и не понятно почему, а тикет мой закрыли за давностью)
                  0
                  Тикет, что он не принимает поток от nginx-rtmp точно видел на той неделе, видел, что обещали пофиксить. Я знаю, что они читают тут комментарии. Так что можно не стеснятся.
                    +1
                    Надеюсь пофиксят, ибо все эти проблемы (а им больше года) явно говорят о том, что у разработчиков узкий кейс применения их медиа-сервера.
                    Они нацелены на OBS->WebRTC. И в основном только с ним и работают.
                    Я, конечно, до сих пор в него верю, но вот например github.com/ossrs/srs выглядит куда лучше сейчас
                      0
                      Не смог найти тикет про nginx-rtmp как будто бы прям в паралельной вселенной это случилось. Может видел такой же вопрос где-то. rtmp pull обещают добавить. Ссылаются на другие приоритеты.
                      github.com/AirenSoft/OvenMediaEngine/issues/125#issuecomment-716319760

                      Ха, а вот srs не видел, он, смотрю, мощнее кишками, но с фронтом связка у него слабее. OvenPlayer тут смотрится интереснее. Хоть их и можно соединить наверняка, но в связке OME + OvenPlayer проект цельный, я бы все равно его выбрать сейчас. Для моей узкой задачи очень хорошо лег. Относительно просто все завелось, хоть и не без вопросов разрабам, которые я в статье раскрыл.

                      У OvenPlayer есть мелкие UX баги типа громкости сбрасывающейся при смене источников. Потеря автостарта при смене источников. Надо все это в тикеты завернуть. Мне очень понравилась ориентированность на аудиторию. Прямо законченный проект. И блог ведут и документашка вроде бы нормальная. На тикеты отвечают быстро. Мою статью даже попросили себе забрать переводом.
              0
              Когда Роман Арутюнян (rarutyunyan) выпустил модуль nginx-rtmp-module, это сильно перевернуло взгляд на доступность организации видеовещания.

              Не хочется уменьшать заслуг Романа, но никакого переворота не было. Был ffmpeg который итак все это умел, все им пользовались (если не пользовались GStreamer или проприетарщиной), а модуль просто добавил ffmpeg в nginx. Удобно, приятно, но все то же самое можно было делать настраивая nginx и ffmpeg отдельно (или используя медиасерверы, которые либо ).

              Форматы, работающие по http требуют хорошей буферизации. Задержка выливается в 15 секунд.

              Справедливости ради задержка в hls зависит от настроек, при желании можно уменьшить количество чанков в чанклисте и уменьшить продолжительность чанков и добиться 5-6 секундных задержек (это также отражается на качестве стриминга при нестабильном канале и все равно не догоняет rtmp, у которого задержка может быть и секунда).

              В issue к nginx-rtmp-module не я один [1] [2] оставлял вопросы о поддержке форматов передачи видео по http с низкой задержкой (2-3 секунды). Ведь если бы можно было вещать в формате dash и hls до 3 секунд на nginx-rtmp-module, меня бы это полностью устроило.

              В ffmpeg поддержка lHLS и lDASH как будто бы есть ffmpeg.org/ffmpeg-formats.html
              Можете попробовать, хотя до уровня rtmp вряд ли дотянет
              Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment’s URI. Apple doesn’t have an official spec for LHLS. Meanwhile hls.js player folks are trying to standardize a open LHLS spec. The draft spec is available in github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md This option will also try to comply with the above open spec, till Apple’s spec officially supports it. Applicable only when streaming and hls_playlist options are enabled. This is an experimental feature.
              Enable Low-latency Dash by constraining the presence and values of some elements.
                0
                По моим ощущениям Роман снизил потенциальный порог достаточно сильно. До
                того все это было слишком сложно для вливающегося со стороны. Терпение лопалось раньше, чем появлялся какой-то результат. Самое у романа было было уметь собрать nginx, и то с появлением динамических модулей стало все еще проще.

                Dash сейчас у меня в 2 cекунды задержки в 500kbps шикарно работает. Я вообще ждал, что rtmp добавят в браузеры нативно, если флеш задеприкейтят. Наивный я.
                  +1
                  Переворот был. Т.к. FFmpeg не умеет быть в роли сервера (а FFServer давно забросили и выкинули, а на тот момент когда он и был, использование его было адом).

                  Де-факто nginx-rtmp до сих пор остается самым проверенным решением для приема RTMP трафика, но только как принимающий трафик (!). Т.к. без проблем с него можно забрать RTMP поток в FFmpeg, из FFmpeg'a забрать MPEGTS и лепить HLS как душе угодно :)

                  Самое смешное, что даже если и добавят LHLS, то и воспроизводить его нечем будет, hls.js уже как больше года добавляет к себе эту поддержку :))

                  На деле и с обычным HLS можно добиться задержки в секунды две (выставляем GOP в секунду, и играемся с буффером). Но такие реактивные методы опасны тем, что любой маленький пролаг влечет за собой буфферизацию и совсем не комфортный просмотр.
                    0
                    Вроде неделю назад разродилися. Теперь есть LL-HLS у hls.js.
                    github.com/video-dev/hls.js/projects/7
                      0
                      Но, он до сих пор в альфе, релиза полноценного все еще не было (т.к. последний тег в релизах только с тегом alpha). Но судя по Вашей ссылочке, то скоро уже все будет, это радует :)
                        0
                        done :-) Зарелизили.
                  0
                  К сожалению, проект c 2017 года не развивается

                  Ну это не так:
                  https://github.com/sergey-dryabzhinsky/nginx-rtmp-module/
                  https://github.com/chetandhembre/nginx-rtmp-module
                  https://github.com/winshining/nginx-http-flv-module
                  Ещё когда (где-то в 2016) я поднимал нужно уже было пользоваться форком ибо только он работал ожидаемым образом.

                    +1
                    Тоже можно в копилочку github.com/pingostack/pingos
                      0

                      Ага, его тоже видел, но забыл. Спасибо за ссылку!

                        0
                        с китайскими комментами?) Да ну нафиг!))
                        0
                        это не тот уровень комьюнити, к сожалению.
                        0
                        Alexufo, интересная статья, жаль поздно увидел.
                        К сожалению сабж не тестировал еще, но пока топаю изучать доки, не могли бы вы подсказать, можно ли на его основе соорудить мини ютуб в LAN? Т.е. мне нужно из разных мест стримить на один ресурс, редиректить еще и на ютуб копию потока и отображать текущие трансляции как-то красиво.
                        Сейчас реализовано как раз на nginx-rtmp + ffmpeg + HLS. Не смотря на то что там latency и тп, важно то, что его крайне легко допилить. К примеру его обрабатываемые ивенты при подключении/отключении клиента и паблишера помогли наполнить БД, из которой потом гуй красиво тянет активные трансляции и считает клиентов.
                        1. может ли сабж такое?
                        2. Если да, то надо самому пилить или уже есть наброски?
                          +1
                          OME хорош для клиентской стороны. Ретранслировать он вроде как может как и кушать много источников, а вот событийной модели нет. Как я писал, со стороны статистики хотелось бы больших инструментов. Сейчас есть логи, которые представляют из себя файлы. И кушать их не очень приятно, однако, может быть они будут более удобны и информативны чем у nginx-rtmp-module
                          Если есть какой нибудь всеядный движек для сбора статистики, может быть их совместное использование будет не сложным и удобным.

                        Only users with full accounts can post comments. Log in, please.