Manchmal möchte man selber sein Video-Streaming kontrollieren.
Sei es, dass die bekannteren Anbieter wie Discord, Zoom, Cisco Webex oder
Microsoft Teams die Teilnehmerzahl beschränken, die Soundqualität
schlicht grottig ist: mindestens die ersten drei haben "Klangverbesserer"
im Einsatz (manchmal sogar mit "KI" beworben), die Hintergrundgeräsche
wie beispielsweise Musik herausrechnen. Ganz blöd bei Musikrunden
und Circles.
Oder man möchte abseits übergriffiger AGBs streamen, da so manche Anbieter sich gleich die Rechte an Texten, Bildern, Lesungen o.ä. abgreifen wollen. OpenSource Videokonferenz-Systeme wie Jitsi oder BBB/BigBlueButton brauchen heftigere Server und aufwändigere Konfiguration. Oder sie erlauben - wie z.B. NextCloud Talk in der Praxis nur sehr, sehr wenige Teilnehmer (2-10). Dabei kann man vergleichsweise einfach eine ansehnliche Anzahl an Leuten erreichen. Und hier ist wie. Als Software auf Client-Seite braucht es OBS (und für ein entspannteres Zuspielen von Videos VLC). Auf dem Server kann quasi jeder beliebige Webserver verwendet werden (Apache, Lighttps, NginX, ...), und es wird FFmpeg benötigt. Der Webserver kann ganz trivial konfiguriert sein. Es wird nichts zusätzliches benötigt. Kein PHP, keine Plugins, keine Module, keine Sondersoftware. Einfach nur der Basis-Webserver. Man kann natürlich mehr installieren und für andere Projekte nutzen - wird aber für das Streaming nichts zusätzliches gebraucht. Wie die Software installiert wird, ist systemabhängig. Wer das noch nicht selber schafft, für den ist diese Anleitung und wahrscheinlich auch das Betreiben (& Debuggen) eines eigenen Streaming-Servers ein Schritt zu viel. |
Sometimes you just want to be in control of your very own video streaming
service. Whether that the usual video conferencing companies limit the
number of participants (like Discord, Zoom, Cisco Webex or Microsoft Teams),
or an abysmal sound quality. Especially for music - the first three have
"sound enhancement" that tries to filter out any music - which is
Not Good(TM) if you want to stream music.
Or maybe you want to stream content without intrusive terms, as some services claim all rights to everything you transfer: texts, images, readings, music... OpenSource video conferencing systems like Jitsi or BBB/BigBlueButton need heftier servers and much more work with respect to configuration and administration. Or they offer (like NextCloud Talk) only a very, very limited number of participants (2-10). But if you know how, then you can reach a respectable number of viewers without having to go overboard with prerequisites.. And here is how: On client-side you need the OBS software. For an easier playback/injection of videos I recommend installing the VLC video player alongside. On server side you can use basically any web server (Apache, Lighttps, NginX, ...), plus the FFmpeg software. A basic installation of the web server is sufficient. It only needs to serve static files - which basically any server can do in its basic configuration. You do not need any plugins, no modules, no PHP, no special software. Just the basic webserver. Of course you still can add modules, e.g. if you want to use the PHP (or whatever) for additional projects. But that is not needed for this streaming setup. On how to install the software - won't be covered here. Running a streaming setup is not for the faint-hearted or people who do not know on how to install, administer and securely run an internet server. |
Als Streaming-Zentrale nutz(t)e ich OBS.
Damit kann ich Videos abspielen, Bildschirme grabben und das Video
von diesen weiterstreamen (beispielsweise Videokonferenzen mit
Sprecher-Ansicht für Live-Konzerte). Und auch gleichzeitig streamen
und aufnehmen.
Dazu definiere ich Szenen, die ich nacheinander überblende, beispielsweise Videos, Screen-Grabs oder Zwischenbilder. Bei den Szenen kann ich mehrere Elemente miteinander kombinieren, beispielsweise das Hintergrundbild, Texte (die ich auch "live" ändern kann. |
For streaming console I use(d) OBS.
With OBS you can stream videos, screen-grabs (e.g. video conferencing with
speaker-view - what we used for live converts). And you can simultaneously
stream and record.
For this I define "scenes" that will be cut/faded one after the other, e.g. videos, screen-grabs or "next up:" images. In the scenes I can combine various elements, e.g. background image, multiple videos (e.g. speaker and slides), texts (that can be changed live). |
Als Transport in Richtung Upstream-/Verteil-Server verwende ich RTMP -
vielleicht kann man da noch optimieren, aber das war das, was ich
kurzfristig ans Fliegen bekommen habe. Einzustellen in den "Einstellungen"
unter "Stream".
Natürlich kann man auch in Richtung YouTube, Twitch, Facebook und anderen streamen - hier existieren vorgefertige Profile - aber das wollten wir ja nicht. Die Video-Parameter für den Stream werden unter "Ausgabe" und dem Reiter "Streamen" eingestellt. Diese sollten zur Anwendung und zur Streaming-Seite passen. Im Bild meine Werte, die etwa einem "normalen" HD DVB-T Bild entsprechen. Wenn man den Stream dann auch gleich nochmal lokal aufzeichnen will, kann man sich den gewüschten Output entsprechend ebenfalls einstellen, dann unter dem Reiter "Aufnehmen". |
For streaming the video to the upstream-/distribution-server I use RTMP.
Maybe that leaves room for improvement - but RTMP stream was the one I
have been able to get proper results on short notice. You can set the
upstream server in the "preferences" under "stream".
Of course you could use one of the predefined services like YouTube, Twitch, Facebook or one of the others (here you have predefined profiles) - but that is exactly what we did not want here. The video encoding parameters for the stream are set unter "output" and the "stream" tab. These should be chosen according to your needs. Below the values I used which represent a "normal" HD DVB-T quality. If you want to (simultaneously) record the event locally, you can set the according parameters in the tab "recording". |
Auf dem Server muss der RTMP-Stream umgebaut/umcodiert und
anschließend an alle Interessenten verteilt werden.
Entsprechend braucht der Server genug CPU-Leistung. In meinem Beispiel reichten aber schon 2 virtuelle CPU-Kerne für rund 100 Zuschauer, ein dritter hätte mehr Luft gehabt und dann auch für das Gbit/s gereicht. Entscheidend ist auch die Bandbreite: bei einem Videostream von 2 Mbit/s Bandbreite passen nicht mal 50 Zuschauer in einen "kleinen" bis "normalen" gehosteten vServer, für mehr bis ~400? Zuschauer ist dann schon 1 Gbit/s Serveranbindung notwendig. Das sollte man vorher auch mal austesten, was davon der Provider anbietet und was er tatsächlich liefern kann. Ich verwende HLS-Streaming. Das bedeutet: viele 4-Sekunden-Schnipsel an .TS-Videos, und die aktuelle Position wird durch eine immer wieder aktualisierte .M3U8-Abspielliste definiert. Der Client lädt die .M3U8-Datei und spielt die enthaltenen .TS-Videoclips ab, aktualisiert die .M3U8-Datei alle paar Sekunden und hägt unbekannte Clips an. Das .M3U8 zeigt ein Zeitfenster auf die Dateiliste. Beispielsweise:
|
On the server the RTMP stream is converted/remuxed and distributed
to all viewers.
So the server needs an minimum CPU power to do this. In my case 2 virtual CPU cores were enough for ~100 viewers. A 3rd one would have been nicer for a more comfortable buffer - and probably would have been enough to saturate 1Gbit/s (and ~400 viewers). The other contraint is bandwidth: if your videostream is running at 2 Mbit/s per viewer (normal/better DVB-T) then less than 50 viewers will saturate a "small" to "normal" vServer. For more (and up to ~400? viewers) you need a vServer with 1 Gbit/s = 1000 Mbit/s network connection. And of course you should test the capacity the provider actually can deliver before you need to depend on it. Here we use HLS streaming. That basically cuts the video into manymany 4-second-videoclips in .TS-format. The current video clips are listed in a .M3U8 file which also is renewed every few seconds. The video player loads the .M3U8 file and plays the videos listed in it - and repeats reloading the .M3U8 file, appending the videos to its playlist. So the .M3U8 gives a window of "current" .TS clips like this:
|
Auf dem Server loggt man sich mit SSH ein, wechselt in das
Directory in dem die Videclips erzeugt werden sollen
und ruft FFmpeg entsprechend auf mit beispielsweise
folgenden Parametern auf.
Die Parameterwahl wird im Detail erklärt von Martin Riedl, (Teil 2, Übersicht) Die alternative Variante sollte deutlich(st) weniger Ressourcen benötigen, weil nur noch kopiert aber nicht umcodiert wird - ist aber nicht verifiziert. |
Log into the server (with SSH), change into the directory where you want
to create your streming files and call ffmpeg with the according parameters.
Which parameters and why to choose them is explained in
Martin Riedl,
(Teil 2,
Übersicht)
The alternate version should use much less ressources as it is not recoding, but only copying the video data. It is untested, though. |
ffmpeg -listen 1 -i rtmp://SERVERIPADDRESS:PORT \ -c:v libx264 -crf 21 -preset veryfast -g 25 -sc_threshold 0 \ -c:a aac -b:a 128k -ac 2 \ -f hls -hls_time 4 -hls_list_size 5 -hls_playlist_type event \ STREAMNAME.m3u8 Alternative: ffmpeg -listen 1 -i rtmp://SERVERIPADDRESS:PORT \ -codec copy \ -f hls -hls_time 4 -hls_list_size 5 -hls_playlist_type event \ STREAMNAME.m3u8 |
Damit nur wir den Stream bespielen können, muss der Zugriff geschützt werden. Am einfachsten mit einer Firewall-Filterregel. Die man auch persistieren sollte. | To protect against other people/intruders from streaming via our infrastructure you should protect it, e.g. by setting firewall filters, e.g. |
iptables -A INPUT --source CLIENTIPADDRESSE -j ACCEPT iptables -A INPUT -p tcp --dport PORTNUMMER -j REJECT --reject-with tcp-reset |
FFmpeg wartet auf den Start eines Streams, und endet automatisch
wenn der Stream endet. Das bedeutet, dass FFmpeg neu gestartet werden
muss, wenn ein neuer Stream startet.
Dies kann man auf folgende Weisen machen:
Zur Wiedergabe kann man einfach nur auf die .M3U8-Datei verweisen, oder auch zusätzlich einen Web-Player auf der Webseite anbieten. Ich habe dazu die Basic Usage Demo des hls.js Players auf meinen Webserver kopiert und angepasst. Als JavaScript-Schnipsel habe ich die aktuellen hls.min.js und hls.min.js.map von deren github verwendet. Stand Ende 2020 können iPads und iPhones sowie ältere Browser nichts mit dem Webclient anfangen. Die können dann das Video meist durch Anklicken/Download des M3U8-Links abspielen. |
After starting ffmpeg it waits for a TCP connection and an RTMP stream.
It will terminate automatically on end of stream (or an error). This
implies that you will have to re-start ffmpeg each time if you want to
(re)start a new stream.
There are a number of ways to do that:
The viewers simply can open the .M3U8 file in the browser, which usually will launch an appropriate media player. Additionally you can add a web player on your web site for convenience. I used the Basic Usage Demo of the hls.js player, which I copied to my web site and adapted accordingly. Differing from the demo page I used the current hls.min.js and hls.min.js.map files from the project's github. As of Autumn 2020 iPads and iPhones and older browsers cannot use the web player mentioned above. So make sure to include a link to the .M3U8 file they can view. |
# /etc/systemd/system/ffmpeg-stream.service # # ueberschreibt einfach bestehende alte Streams # overwrites old streams without asking back [Unit] Description=ffmpeg Streaming After=network.target [Service] User=www-data WorkingDirectory=/var/www ExecStart=ffmpeg -listen 1 -i rtmp://SERVERIPADDRESS:PORT -codec copy -f hls -hls_time 4 -hls_list_size 5 -hls_playlist_type event STREAMNAME.m3u8 RestartSec=2 Restart=always [Install] WantedBy=multi-user.target |
Weitere "Kleinigkeiten" die man beachten sollte:
|
Some more "little things" you should have an eye on:
|
2020-10