Mit dieser kleinen Anleitung, kannst du einen Playlist-Livestream mit Linux erstellen.
Somit kannst du Videos zu Plattformen wie Twitch, YouTube, Mixer, Dlive & Co. streamen.
Wir werden am Ende das fertige Video per „codec copy“ einfach 1:1 auf die Plattform schieben. Damit sparen wir uns die Codierung und dadurch enorm Rechenleistung.
Was brauchen wir?
– Einen Linux-Server => Braucht nicht viel Power. Wirklich nicht viel!
– Viel Speicherplatz für Videos
– Eine gute Internetanbindung => So viel Bandbreite wie die Videos an Datenrate haben
– Root-Rechte auf dem Server
– Videos, ganz viele Videos
1. Videos organisieren und anpassen
Wir brauchen nun sehr viele Videos, die wir streamen möchten.
Diese müssen ggf. auf folgende Kriterien angepasst werden.
Eventuell musst du die vorhanden Videos noch einmal in ein anderes Format rendern.
Die Videos müssen
– im Format mp4 mit x264 Codec sein
– die zu streamende Auflösung haben (z.B. 1920×1080)
– die zu streamende Bilder pro Sekunde haben (z.B. 60FPS)
– die zu streamende Datenrate für das Bild haben (z.B. 6000kbps)
– die zu streamende Datenrate für den Ton haben (z.B. 320kbps)
Die Auflösung, Datenraten und FPS sollten den Vorgaben für normale Livestreams der Plattformen entsprechen.
Twitch erlaubt nur Livestreams mit 1080p + 60FPS und einer maximalen Datenrate von 6000kbps. Wer mit mehr streamt, riskiert von Twitch abgeschaltet zu werden.
(Steht so im FAQ.)
Wer gerne einen 4K-Stream machen möchte, sollte dafür sorgen, das die Videos in 4K mit guter Datenrate (30-40Mbit/s) vorliegen.
Speichere die Videos nun auf dem Server ab.
Du kannst auch (wenn du es von Zuhause aus machst) eine USB-Festplatte an einen Raspberry Pi (oder ähnliches) anschließen und dort die Videos drauf speichern.
Ja auch ein Pi reicht für den Livestream komplett aus!
WICHTIG: Alle Videos müssen in EINEM Ordner vorhanden sein. Es darf KEINEN Unterordner geben! Achte daher etwas auf die Benamung von den Dateien 😉
Am besten bennene die Dateien sehr einfach, ohne Sonderzeichen.
Beispiel: DateiNameDesVideos.mp4
Tipp: Sorge dafür das deine Videos eine konstante Bitrate haben, die bei allen Videos gleich ist. Ansonsten könnte es zu Problemen mit ffmpeg kommen.
2. FFMPEG + Screen installieren
Wir installieren uns FFMPEG. Damit können wir schlussendlich Streamen.
apt install ffmpeg -y
Zusätzlich installieren wir noch Screen, damit der Stream im Hintergrund weiter laufen kann.
apt install screen -y
3. Eine Playlist erstellen
Wir erstellen uns nun eine Playlist-Datei, welche die Videos behinhaltet.
Gehe nun in den Ordner, indem die ganzen Videos liegen.
cd /dein/Ordner/mit/Videos
Hast du viele Videos nun dort drin, wäre es sehr mühselig die ganzen Dateinamen nun abzukopieren und in eine Playlist zu packen.
Wir helfen uns mit diesem Befehl:
find . -iname "*.mp4" -exec basename {} \;>Playlist.txt
Wunderbar!
Editiere nun die Datei noch, damit die Playlist nun folgendem Muster entspricht:
file 'video1.mp4' file 'video2.mp4' file 'video3.mp4' file 'video4.mp4'
Aktuell stehen ja nur die Dateinamen drin. Davor muss jetzt noch file ‚ und am Ende noch einmal ein ‚!
Du kannst auch nun die Reihenfolge der Playlist noch editieren. Die Videos werden der Reihe nach abgespielt. Möchtest du also einen gewissen „Mix“ haben, pass die Reihenfolge an.
WICHTIG: Wir können leider keine Pfade mitgeben, damit müssen alle Videos im gleichen Ordner liegen, indem sich die Playlist-Datei und die folgenden Start-Scripts befindet.
Wem das ganze von Hand etwas zu doof ist, kann „gute“ Texteditoren wie z.B. Notepad++ oder NotepadQQ nutzen.
Dort lässt sich mit wenigen Klicks der notwendige Text einfügen.
Um etwas an jeden Zeilenanfang zu setzen, suche nach „^“ und ersetze es mit „file ‚„.
Um etwas an das Ende jeder Zeile zu setzen, suche nach „.mp4“ und lass es durch „.mp4′“ ersetzen.
4. Die Stream-Datei anlegen
Nun legen wir uns eine Datei an, welche einfach den Stream startet und zur gewünschten Quelle schickt.
nano LIVESTREAM.sh
Ich habe hier nun zwei Möglichkeinten für dich.
Die erste ist ein einfacher „Stream“. Wenn die Playlist vorbei ist, wird der Stream beendet.
Die zweite ist ein Loop. Ist die Playlist zuende, wird sie neu gestartet.
Einfacher Playlist-Stream:
Füge für den einfachen Stream in die LIVESTREAM.sh nun folgenden Startbefehl ein:
ffmpeg -re -f concat -i Playlist.txt -codec copy -flvflags no_duration_filesize -f flv rtmp://DEIN-SERVER/DeinStreamKey
Aber was tud sie?
ffmpeg -re -f concat→ Startet ffmpeg
-i → Wir geben die Playlist- Datei an
-codec copy → Wir geben als Codec die Daten des Videos an. Wir rendern nichts auf dem Server
-f flv rtmp → Trage hier dein Zielserver ein (z.B. Twitch, YouTube, Mixer, ….)
Loop-Stream für ein 24/7-Livestream:
Füge für den einfachen Stream in die LIVESTREAM.sh nun folgenden Startbefehl ein:
while [ 1 -eq 1 ] do ffmpeg -re -f concat -i Playlist.txt -codec copy -flvflags no_duration_filesize -f flv rtmp://DEIN-SERVER/DeinStreamKey done
Aber was tud sie?
Wir führen eine Schleife aus.
Solange „1“ wirklich „1“ bleibt, führe den ffmpeg-Startbefehl aus.
Ansonten sei fertig.
Mehr ist es nicht.
1 wird auch solange nichts dazwischen kommt, immer 1 bleiben.
Speichere die Datei ab.
Nun noch ein
chmod +x LIVESTREAM.sh
damit die Datei auch ausführbar ist.
5. Starte es mit Screen, dann läuft der Stream im Hintergrund weiter
Dazu erstellen wir uns eine „Start-Datei“.
nano START-STREAM.sh
Hier fügen wir einfach folgenden Startbefehl hinein:
screen -S 24hStream ./LIVESTREAM.sh
Und nun noch die Datei ausführbar machen
chmod +x START-STREAM.sh
FERTIG!
6. Stream starten
Gebe nun auf der Komandozeile folgendes ein:
./START-STREAM.sh
Es sollte nun ein Screen geöffnet werden, welcher den Output von FFMPEG ausgibt und dein Stream sollte live gehen!
Aber wie und was wird nun gestreamt?
Das klären wir noch kurz.
Welche Auflösung wird gesendet?
Die des originalen Videos.
Wechselt die Auflösung, weil die Videos in unterschiedlicher Auflösung vorliegen, ändert sich auch die Auflösung des Streams.
Welche FPS wird gesendet?
Die des originalen Videos.
Hat es 30FPS, werden nur 30FPS gestreamt.
Hat das nächste Video 60FPS, werden 60FPS gestreamt.
Welche Datenrate wird gesendet?
Die des originalen Videos.
Wurde das Video mit variabler Datenrate codiert, schwankt die Bandbreite eben etwas. Wurde das Video mit fester Datenrade codiert, wird dauerhaft mit dieser Datenrate gestreamt.
Was passiert wenn die Playlist fertig ist?
FFMPEG schließt sich und der Stream ist aus.
Nutzt du das Loop-Script, wiederholt sich die Playlist.
Wie kann ich die Bildqualität bei niedriger Datenrate verbessern?
Wenn du nicht viel Uploadbandbreite zur Verfügung hast, rendere deine Video mit der x264 / h264 CPU-Voreinstellung „medium“, „slow“ oder „placebo“.
Dauert zwar zum rendern etwas länger, die Bildqualität kann aber dann bei niedrigen Datenraten etwas verbessert werden.
In der Regel sollte Medium ausreichen.
Kann ich auch h265 / x265 nutzen?
Nein. Das unterstützen die Plattformen (aktuell) nicht.
Nur als kleiner Einblick in den Leistungshunger eines Livestreams, ist hier ein Screenshot eines Pine ROCK64 (vergleichbar mit Raspberry Pi 3).
Der Stream braucht etwa 2-5% CPU-Leistung.
Gestreamt wurde ein 1080p Stream mit 60FPS und etwa 8Mbit/s Datenrate.
Tipps für Leute die es bis zum Ende schaffen
Du streamst von Zuhause aus?
Dein Internet wird vermutlich alle 24 Stunden neu verbunden. Um den Stream dadurch nicht neu starten zu lassen, brauchen wir eine Art Puffer bzw. interner „Server“, der dauerhaft für ffmpeg da ist.
Die einfachste Lösung: Installiere dir Docker und dann den Container „Restreamer“ und Streame einfach dort hin. Restreamer kann dann zu deinem Wunschziel (z.B. Twitch) streamen.
Fällt dein Internet aus, bricht der ffmpeg-Stream ab und ist dadurch offline. Restreamer kann aber sich automatisch neu verbinden und dein Stream wird nicht abgebrochen.
Du willst zu mehreren Zielen streamen?
Verwende doch einfach Restream.io. Damit kannst du realtiv einfach und komplett kostenlos zu mehreren Plattformen streamen.
Hast du auch kurze Internetaussetzer, kann die Plattform es etwas „puffern“, damit deine Zuschauer ein fast unterbrechungsfreien Stream genießen können.
Update 17.07.2022 – Tipp von Christian mit dem flvflags-Parameter hinzugefügt.
Mit welchem Betriebssystem, hast du es denn getestet? Ich bekomme immer einen Broken Pipe Fehler von FFMPEG mit Debian.
Ich habe es mit Ubuntu 18.04 LTS und Debian 10 erfolgreich getestet. Auch mit einem Raspberry Pi läuft es.
Sobald aber die Daten von einer externen Festplatte oder Netzwerklaufwerk abgespielt werden, habe ich den gleichen Fehler.
Es muss am System selbst liegen, ein Fix dafür habe ich aber nicht.
Sobald die Festplatte direkt am System gemountet ist und ein Linux-Dateisystem (z.B. ext4) hat, funktioniert es super.
Grüß dich!
Erstmal möchte ich dir danken, ich hab schon ewigkeiten mit dem Gedanken gespielt mit hilfe eines PI*s einen eigenen 24/7 Stream auf die beine zu stellen und dein Tutorial hat mir den Anstoß gegeben weiter zu machen.
Leider Stand ich aber schon direkt an einem Problem und das ist der Speicher, der ist nunmal begrenz und irgendwann wird es mehr videos geben als der Pi Festplatten verträgt, daher die idee: Eine Playlist Restreamen. (Kurz nochmal zur erklärung, ich möchte eine immer größere playlist restreamen, ohne den pi je wieder anfassen zu müssen und in normaler geschwindigkeit )
Angestoßen habe ich das ganze mit FFmpeg (ich lasse in FFpeg die playlist downloaden bzw das video und dieses wieder hochstreamen). So soll also nur das video die zeit auf der platte sein wie es gebraucht wird, quasi ein qache verhalten.
Jedoch bin ich mittlerweile an meiner grenze, ich habe es hinbekommen das der pi ein video restreamt, jedoch bekomme ich die geschwindigkeit nicht angepasst. Der pi lädt sich das ganze runter und gibts dann in fast doppelter geschwindigkeit wieder hoch und das mag Youtube nicht. Hast du vlt eine besse Lösung als meine?
Da kann ich dir aktuell nicht helfen, da ich dein Script nicht kenne.
Ich selbst habe mich schon dran versucht, Videos herunterzuladen, diese zu streamen und dann die Videos wieder löschen zu lassen, damit ich keine riesen große Festplatte anschließen muss.
Das hat aber nie funktioniert.
(Vielleicht war mein Script auch einfach zu doof)
Aktuell kann ich daher nur empfehlen, eine große Festplatte anzuschließen und Videos passend dort abzulegen.
Hier einmal ein passender ffmpeg-Aufbau für 1080p Videos mit 60FPS und 5000kbps Datenrate:
ffmpeg -i INPUT-VIDEO.mp4 -preset medium -codec:a aac -b:a 128k -codec:v libx264 -pix_fmt yuv420p -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 5000k -r 60 -s 1920x1080 -g 120 OUTPUT-VIDEO.mp4
Ich habe schon nach besseren Lösungen im Netz gesucht, aber nur Code-Schrott und viele, viele Fragen gefunden :S
Um eine Sorte von „Broken Pipe Fehler“ während eines (flv) Streams vorzubeugen, das hier in den ffmpeg command mit reinpacken:
-flvflags no_duration_filesize
flv @ 0x20d2019] Failed to update header with correct duration.
flv @ 0x20d2019] Failed to update header with correct filesize. Error writing trailer of rtmp://a.rtmp.youtube.com/live2/xyzetcpp: Broken pipe
Frame=91565 fps= 24
Danke für den Tipp!
Ich sehe gerade, hab ich etwas schlecht formatiert für Otto Normal.
Nutze diese Option im ffmpeg Befehl:
-flvflags no_duration_filesize
Damit beugt man diesen Fehler vor:
flv @ [0x20d2019] Failed to update header with correct duration.
flv @ [0x20d2019] Failed to update header with correct filesize. Error writing trailer of rtmp://a.rtmp.youtube.com/live2/xyzetcpp: Broken pipe
Schonmal getestet, ob damit der BrokenPipe Error wirklich aus bleibt?
Hallo zusammen nochmal,
ich hab das ganze jetzt nochmal getestet und es tritt aktuell nur noch ein Fehler auf. Nämlich der Error writing Trailer fehler, der ein Broken Pipe error auslöst.
Ich habe dazu jetzt folgende Fehler Behebung gefunden.
For anyone struggling with this the problem is ffmpeg trying to seek to the beginning of the file to add the MOOV atom. Add -movflags frag_keyframe+empty_moov to your ffmpeg encoding so that the seek isn’t necessary. -movflags faststart will not accomplish the same thing.
Jetzt stellt sich mir nur noch die Frage wo wird das -movflags frag_keyframe+empty_moov genau eingebaut? Oder ist das egal?
Vielleicht weißt du ja mehr dazu Hörli.
Hi!
Sorry für die späte Antwort, dein Kommentar ist vom Spam-Filter aufgehalten worden.
Es ist egal wo du das Flag hin packst. ffmpeg sollte es finden und nutzen können. Am besten einach ans Ende hinzufügen und gucken ob es besser wird.
Moin und tausend Dank für diese tolle Anleitung – ich habe gerade meinen Kanal eröffnet – ich kann aber leider nicht Screen installieren, da ich dieses auf Windows streame. Hättest du eine Idee wie ich den Loop hinbekomme ohne „Screen“. Der Stream läuft schon, nur der Loop ist etwas kompliziert ohne „screen“. LG Letsplayfry
Hi!
Für Windows benötigst du kein Screen, da du dort einen Desktop hast.
Solange deine Sitzung nicht geschlossen wird (z.B. lokal abmelden), kannst du das Terminal-Fenster einfach geöffnet lassen.
Ich gehe mal nicht davon aus, das dein Windows-System eine Core-Variante ohne Desktop ist 😉
Hallo Hoerli, danke für Deine schnelle Antwort – ich habe mir extra einen VPS Server geholt 🙂 wollte es eigentlich mit OBS machen das frisst aber zu viele Ressourcen. Heißt das, dass wenn die Playlist abgearbeitet wurde diese neustartet? Sag mal eine weitere Frage – hättest du eine Idee wie ich die Beschreibung und das Spiel automatisch ändern könnte? Ich dachte an sowas wie den Namen der VideoDatei. Tausend Dank für Deinen Support und einen schönen Sonntag.
Das Script startet neu, sobald das Ende erreicht wurde oder es durch – was auch immer – unterbrochen wurde.
Da die Videodaten nur „kopiert“ werden, braucht das so gut wie keine Leistung. OBS rendert alles neu, was enorm Leistung benötigt.
Wenn du Titel oder Spiel automatisch anpassen willst, musst du dir selbst ein passendes Script dazu schreiben, was aus vorhandenen Daten die Informationen entnimmt und an z.B. Twitch sendet.
Die APIs sollten das ermöglichen.
Ich habe hierfür nichts auf Lager. Hab mich selbst noch nie damit beschäftigt.
Vielen Dank für Dein Support und die Hilfe – ich mach mich mal ran – hast du eine Idee wie ich das selber Scripten könnte? Oder hast du jemanden an der Hand? LG Fry
Nein, da habe ich leider nichts für dich.
Hallo Hoerli, ich bins noch mal … sorry für die doofe Frage aber irgendwie loopt er nicht richtig …. er bricht nach dem ersten Video immer ab es kommt kein weiteres…. weißt du woran das liegen könnte. Habe alles so gemacht wie du gesagt hast. Kann es sein das man die Playlist nach dem Starten des Streams nicht mehr ändern darf? LG
Hallo, danke für den Guide, genau das habe ich gesucht, jetzt hast du am Ende gemeint, dass man mit Restreamer es verhindern kann, wenn die Playlist fertig ist, dass der Stream neu gestartet wird. Leider passiert es dennoch das er bei mir den Stream neu anfängt, sprich offline geht und dann wieder Online.
Das lässt sich leider nicht vermeiden.
Der Stream wird immer gestoppt, sobald die Datei endet.
Man kann höchstens mit Puffern arbeiten, ist aber nur eine „trickserei“, statt eine sinnvolle Lösung.
Ja hatte da damals Artmedia genutzt, hat aber dasselbe Problem wie genau meinst du, das mit puffern? Finde da die Einstellungen dazu nicht ^^
Zum Thema „Neustart des Streams am Playlist-Ende“. Wer dies verhindern möchte, einfach die Playlist selbst loopen, also nicht über die while-do-Schleife (-stream_loop -1). Die while-do-Schleife kann natürlich für unerwartete Abbrüche von ffmpeg trotzdem beibehalten werden.
Und damit man sich das Erstellen und manuelle Anpassen der Playlist erspart, einfach das Auslesen des Pfads direkt in den ffmpeg Aufruf mit reinnehmen.
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) ….
Hallo, vielleicht kann mir ja hier einer helfen. Mein Problem ist: Da ich Ffmpeg-Streams hintereinander ausführe, kommt es beim Playern zum Abbruch (stream closed). Mein FFmpeg-Command (playlist.sh)
ffmpeg -re -i yt-dlp f18-g www://youtube………….-f-flv rtmp://meinrtmp
ffmpeg -re -i http://dai.ly/viddoe………-f flv rtmp://meinrtmp
Weil ich nichts runterladen möchte. Ist hier dieser Abbruch beim Stream irgendwie umgehbar wie beim „concat“ Streamen?
Danke für jeden Tip.
Dein Input scheint aber von YouTube und einem anderen Anbieter zu sein. Auf dieser Seite wurde erklärt, wie man quasi intern Streamen könnte, aber nicht von externen Quellen, wo man nicht unbedingt weiß, ob die überhaupt zugreifbar sind…
Es mag zwar kein direkter Download sein, aber auch ein Stream ist mehr oder weniger ein flüchtiger Download…
Es wäre besser, alle Dateien lokal auf dem Server zu lagern…
Danke für das Tutorial.
Gibt es ectl einen Hinweis wie ich am den Videotitel ÜBER dem Video angezeigt bekomme?
Grüße
Patrick
Hi
Dazu muss tatsächlich das Video frisch gerendet werden, was wiederum Ressourcen benötigt.
Der „copy“-Befehl klappt dadurch nicht mehr.
Da muss ich Recht geben. Sobald man etwas zum Video hinzufügen möchte, muss es neu kodiert werden und viele virtuelle Systeme im Internet schaffen es in der Regel auch nicht. Der „Copy“-Befehl leitet nur weiter, verbraucht in der Regel auch nicht viele Ressourcen…
Danke für deine Antwort. Ja habe ich auch gemerkt das das in Verbindung mit copy nich geht. Hast du da ne Hilfe für mich wie ich das umsetzen könnte? Würde das gerne mal probieren und austesten was Resourcentechnisch so möglich ist. Eigentlich wäre es gut wenn man neben dem file Name in der txt Datei irgendwie den Video Titel mit angeben könnte. Vielleicht eine Art json? Ach ja hab mich auch etwas probiert an einer „Restzeit Anzeige“ für das Video, allerdings bin ich da auch etwas überfordert ^^ Grüße
Patrick
Dazu habe ich leider nichts.
Ich habe ab diesem Punkt dann einfach wieder OBS Studio genutzt, da ich ohnehin ein Rechner mit Leistung brauchte.
Das war einfacher und funktionierte zuverlässig.
Ok danke trotzdem
Hallo,
Ich habe alles genauso gemacht wie beschrieben.
Nur irgendwie nimmt er den Command „while [ 1 -eq 1 ]
do
ffmpeg -re -f concat -i Playlist.txt -codec copy -flvflags no_duration_filesize -f flv rtmp://DEIN-SERVER/DeinStreamKey
done“ nicht an er sagt immer:
./Livestream.sh: Zeile 4: Syntaxfehler beim unerwarteten Symbol »done«
./Livestream.sh: Zeile 4: `done‘
Grüße
Hi!
Das ist ein 0815-Linux-Script.
Das „done“ sollte korrekt eingelesen werden können.
Eventuell hast du beim abkopieren irgendwie ein Zeichenfehler drin gehabt?
Das passiert manchmal.
An sich läuft das Script aber.
Ich selbst habe es auf diversen Debian-Distributionen getestet.
Da muss ich zustimmen. Ich hatte ebenfalls eine Datei gehabt, wo die Shell Fehlermeldungen ausgab. Nachdem die Datei anders neu erstellt wurde, war der Fehler auch weg, wobei man auch auf die Abspeicherung achten muss und so…
Hey
Könnte ich den von dir beschriebenen Vorgang auch auf einem Synology NAS mit Docker-Containern ausführen? Und wie kann ich die Dauerschleife abbrechen, damit ich selbst streamen kann?
Ich habe kein Sinology-NAS und auch kein Rocker Container dafür.
Sofern du einen selbst haust, kann das alles darin bestimmt laufen 🙂
Ich würde es mal ausprobiert und dir bescheid geben ob es geklappt hat^^
Aber noch mal zu der einen Frage wie stelle ich an das ich denn Stream pausiere um dann wirklich live zu gehen?