2012-07-25 10 views
17

ffmpeg verarbeitet RTMP-Streaming als Eingabe oder Ausgabe, und es funktioniert gut.Verwenden von FFMPEG zum kontinuierlichen Streamen von Videodateien an einen RTMP-Server

Ich möchte einige Videos (eine dynamische Wiedergabeliste, die von einem Python-Skript verwaltet wird) zu einem RTMP-Server streamen und mache derzeit etwas ganz Einfaches: Videos einzeln mit FFMPEG auf den RTMP-Server streamen verursacht jedes Mal, wenn ein Video endet, einen Verbindungsabbruch, und der Stream ist bereit, wenn das nächste Video beginnt.

Ich möchte diese Videos ohne Verbindungsunterbrechungen kontinuierlich streamen, dann könnte der Stream korrekt angezeigt werden.

Ich benutze diesen Befehl meine Videos nacheinander an den Server

ffmpeg -re -y -i myvideo.mp4 -vcodec libx264 -b:v 600k -r 25 -s 640x360 \ 
-filter:v yadif -ab 64k -ac 1 -ar 44100 -f flv \ 
"rtmp://mystreamingserver/app/streamName" 

ich viele Tage für einige Workarounds über das Internet sah zu streamen, und ich fand einige Leute reden eine Named Pipe als Eingabe in ffmpeg, habe ich es versucht und es hat nicht gut funktioniert, da ffmpeg nicht nur den RTMP-Stream schließt, wenn ein neues Video kommt, sondern schließt sich auch.

Gibt es eine Möglichkeit, dies zu tun? (Streamen eine dynamische Playlist von Videos mit ffmpeg zu RTMP-Server ohne Verbindung bricht

+1

Die Verwendung einer Named Pipe ist der richtige Weg. Können Sie näher erläutern, wie das für Sie nicht funktioniert hat? – blahdiblah

+0

@blahdiblah Ich benutzte die Named Pipe als Eingabe in ffmpeg, ffmpeg pause und warte auf ein paar Daten aus der Pipe, dann habe ich 'cat video.mp4> fifo' und ffmpeg angefangen zu streamen und nach dem Streamen des Videos zu beenden. Ich denke, ich weiß nicht, wie man die Named Pipe richtig verwendet, wenn ich 'cat video1.mp4 video2.mp4> fifo' ffmpeg zeige den Fehler' stream 4, offset 0x1d83c: Teildatei 'nach dem Streaming das erste Video. Ich weiß, dass ich es falsch mache, ich muss die Videodaten auf angemessene Weise durch die Pipe weitergeben. – KKetch

+1

Es ist mir gelungen, eine statische Playlist mit Videos zu streamen, indem ich für jedes Video eine Pipe verwende (ex vid1.mp4 -> pipe1, vid2.mp4 -> pipe2 usw.). Dann schreibe ich in einen einzigen Stream namens "stream" auf diese Weise "cat pipe1 pipe2 pipe3> stream", und ich benutze die Stream-Pipe als Eingabe in FFMPEG, um meinen Stream zu veröffentlichen, aber da ich nach einer dynamischen Playlist suche ** wie kann ich sende mehr Videos an die "Stream" -Rohre, um den Stream am Leben zu erhalten? ** Ich habe es noch nicht herausgefunden. (Anmerkung, außer für das erste Video musste ich die Metadaten jeder Videodatei mit dem Befehl tail ausschneiden, damit das funktioniert.) – KKetch

Antwort

6

Update (wie ich die akzeptierte Antwort nicht löschen können): die richtige Lösung ist eine, eine benutzerdefinierte Demuxer, ähnlich wie die Concat zu implementieren. es gibt derzeit keine andere saubere Art und Weise. Sie haben die Hände schmutzig und Code bekommen!

Im Folgenden eine hässliche Hack sind. Dies ist ein sehr schlechter Weg ist, es zu tun, nur nicht!

Die Lösung verwendet die concat demuxer und übernimmt alle Ihre Quellmedien fil Es verwendet den gleichen Codec. Das Beispiel basiert auf MPEG-TS, dasselbe gilt jedoch für RTMP.

  1. Playlist-Datei Erstellen Sie eine riesige Liste von Einspeisepunkten für Sie dynamische Wiedergabeliste mit folgendem Format hält:

    file 'item_1.ts' file 'item_2.ts' file 'item_3.ts' [...] file 'item_[ENOUGH_FOR_A_LIFETIME].ts'

    Diese Dateien nur Platzhalter sind.

  2. ein Skript, das den Überblick über Sie aktuelle Playlist-Index hält und erstellt symbolische Links on-the-fly für current_index + 1

    ln -s /path/to/what/to/play/next.ts item_1.ts

    ln -s /path/to/what/to/play/next.ts item_2.ts

    ln -s /path/to/what/to/play/next.ts item_3.ts

    [...]

  3. zu spielen beginnt ffmpeg -f concat -i playlist.txt -c copy output -f mpegts udp://<ip>:<port>

  4. Get Namen von einem wütenden Systemadministrator

+0

danke, habe gerade deine Antwort gesehen. Ich habe es früher mit Hinekyle-Kommentaren herausgefunden, auch wenn mich diese Art von Hacks jetzt nicht interessiert. – KKetch

+0

Kannst du näher erläutern, was du mit 'Make a script chovy

+0

Der Versuch, dasselbe für .m3u8 24/7 Stream zu tun. Aber der Befehl '-c kopiert die Ausgabe -f mpegts stream.m3u8' löst einen Fehler aus. – chovy

0

Sie können über die Pipeline der Schleife in einen Puffer, und von diesem Puffer der Pipeline an Streaming-Instanz gejagt und aufgerufen.

In Schale würde es wie folgt aussehen:

#!/bin/bash 

for i in *.mp4; do 
     ffmpeg -hide_banner -nostats -i "$i" -c:v mpeg2video [proper settings] -f mpegts - 
done | mbuffer -q -c -m 20000k | ffmpeg -hide_banner -nostats -re -fflags +igndts -thread_queue_size 512 -i pipe:0 -fflags +genpts [proper codec setting] -f flv rtmp://127.0.0.1/live/stream 

Natürlich können Sie jede Art von Schleife verwenden können, auch durch eine Playlist Looping.

  • ich herausfinden, dass mpeg etwas stabiler ist, dann x264 für den Eingangsstrom
  • Ich weiß nicht, warum, aber mindestens 2 Fäden für die MPEG-Komprimierung besser
  • der Eingangskompressions Bedarf arbeitet um schneller zu sein als die Ausgangsbildrate, so erhalten wir schnell genug neue Eingabe
  • Wegen des nicht fortlaufenden Zeitstempels müssen wir sie überspringen und eine neue in der Ausgabe erzeugen
  • Die Puffergröße muss groß genug sein Damit die Schleife genügend Zeit hat, um den neuen Clip zu erhalten.

ich auf Python-basierte Lösung arbeite, ist noch nicht vollständig, aber mit Ausnahme einiger Warnungen meines Teststrom läuft über mehrere Tage:

ffplayout

Dieser verwendet ein XML-Playlist-Format. Und die Wiedergabeliste ist dynamisch, so dass Sie immer die aktuelle Wiedergabeliste bearbeiten und Titel ändern oder neue hinzufügen können.

0

Sie müssen zwei Playlist-Dateien erstellen und am Ende jeder Datei einen Link zu einer anderen Datei angeben.

list_1.txt

ffconcat version 1.0 
file 'item_1.mp4' 
file 'list_2.txt' 

list_2.txt

ffconcat version 1.0 
file 'item_2.mp4' 
file 'list_1.txt' 

Alles was Sie jetzt brauchen, ist dynamisch den Inhalt der nächsten Playlist-Datei zu ändern.