Multistream přes OBS a ffmpeg
OBS Studio umí bez problému streamovat na jednu platformu, ale pokud je potřeba posílat stejný livestream současně na více služeb, samotné OBS nestačí. Jedna z možností je použít službu Restream.io, ale technická varianta je postavit si vlastní mezivrstvu: OBS pošle stream do lokálního RTMP serveru a ffmpeg ho odtud rozešle dál.
Princip řešení
Celé řešení má tři části:
- OBS vytvoří jeden výstupní stream.
- Lokální RTMP server v nginx tento stream přijme.
- ffmpeg vezme vstup z lokálního RTMP serveru a odešle ho na jednotlivé platformy.
Výhoda je v tom, že OBS řeší jen jeden cíl a rozkopírování streamu se děje až mimo něj. Tohle je praktické hlavně tehdy, pokud se má vysílat současně třeba na YouTube, Facebook a další službu.
Lokální RTMP server přes nginx
Jako ingest server jsem použil nginx s RTMP modulem. V Ubuntu stačí nainstalovat balíčky:
sudo apt install nginx nginx-mod-rtmp
V mém případě jsem upravoval soubor /etc/nginx/sites-available/default. Běžnou HTTP/S konfiguraci jsem zakomentoval, protože porty 80 a 443 už obsluhoval Apache. Přidaná byla jen RTMP část na portu 1935:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
Po úpravě konfigurace stačí nginx restartovat:
systemctl restart nginx
Nastavení OBS
OBS pak neposílá stream přímo na cílovou platformu, ale na lokální RTMP server. Výstupní adresa vypadá takto:
rtmp://localhost:1935/live/stream
Tím vznikne jeden lokální stream, který lze dál zpracovat nezávisle na OBS.
Streamovací URL jednotlivých služeb
Dalším krokem je získat streamovací URL a stream key jednotlivých služeb. Pro YouTube a Facebook je to relativně přímočaré v administračním rozhraní dané platformy.
V době vzniku původního článku byl komplikovanější Instagram. Streamovací URL nebyla jednoduše dostupná a použil jsem tehdy aplikaci Streamon. Praktická zkušenost byla taková, že URL měla jen krátkou platnost a bylo nutné v aplikaci nejdřív spustit stream a teprve potom do něj začít posílat data.
Druhá tehdejší zkušenost byla, že Instagram počítal s vertikálním výstupem a obraz si ořezával na výšku. Bylo tedy potřeba připravit scénu tak, aby hlavní objekt zůstal ve středu. To ber jako dobovou poznámku, ne jako aktuálně ověřený univerzální postup.
Rozkopírování streamu pomocí ffmpeg
Jakmile lokální RTMP server přijímá stream z OBS, může ffmpeg vzít vstup z rtmp:localhost:1935/live/stream a přeposlat ho na jednotlivé platformy. V původním řešení jsem spouštěl samostatné příkazy pro jednotlivé cíle a jeden další příkaz pro lokální záznam.
Facebook:
<code bash>
ffmpeg -i rtmp:localhost:1935/live/stream -c:v copy -c:a copy -map 0 -f tee „[f=flv]rtmps:live-api-s.facebook.com:443/rtmp/…“
</code>
Instagram:
<code bash>
ffmpeg -i rtmp:localhost:1935/live/stream -c:v copy -c:a copy -map 0 -f tee „[f=flv]rtmps:live-upload.instagram.com:443/rtmp/…“
</code>
YouTube:
<code bash>
ffmpeg -i rtmp:localhost:1935/live/stream -c:v copy -c:a copy -map 0 -f tee „[f=flv]rtmp:a.rtmp.youtube.com/live2/…“
</code>
Lokální záznam do souboru:
<code bash>
ffmpeg -i rtmp:localhost:1935/live/stream -c:v copy -c:a copy -f mp4 lokalni-zaznam.mp4
</code>
Použité parametry -c:v copy a -c:a copy znamenají, že ffmpeg video ani audio nepřekóduje, ale jen je přeposílá dál. To snižuje výpočetní náročnost, pokud je vstupní stream už připravený v kompatibilním formátu.
===== Omezení a praktické poznámky =====
* OBS samo o sobě neumí poslat jeden stream na více serverů najednou, proto je potřeba mezivrstva.
* Lokální RTMP server je jednoduché řešení, pokud se stream rozděluje na jednom počítači.
* Pokud se mají použít sociální sítě s odlišnými požadavky na formát obrazu, je potřeba na to myslet už při přípravě scény.
* U služeb třetích stran nebo neoficiálních aplikací se může workflow v čase změnit, takže hlavní hodnota článku je princip řešení přes OBS + nginx-rtmp + ffmpeg.
===== Zdroje =====
* OBS Studio
* Restream.io
* Streamon
* OBS fórum – stream to multiple platforms or channels at once
* OBS fórum – private RTMP server using nginx
* ffmpeg