Ich habe einen Stream von einer FFmpeg-Instanz zu einer anderen weitergeleitet, aber da der Zwischenstream komprimiert wurde, war das Endergebnis hässlich. Ich brauche eine verlustfreie Leitung, um dies zu verhindern, und ich möchte, dass sie sowohl Audio als auch Video enthält.
Ich vermute, dass es mehr als eine Antwort auf dieses Problem gibt. Bonuspunkte gibt es daher an jeden, der eine umfassende Liste von Lösungen bereitstellt (kompatible Container und Codecs, die weitergeleitet werden können). Bonuspunkte gibt es auch an jeden, der andere Daten berücksichtigt, wie etwa Untertitel.
EDIT: Ich suche nach geeigneten Codec/Container-Kombinationen. Ich weiß nicht, warum die Leute Schwierigkeiten hatten, das herauszufinden, da ich ja sagte, dass ich bereits eine Pipe verwendet habe und sie jetzt verlustfrei sein muss.
Ich weiß nicht, wie ich das erklären soll, ohne eingebildet zu klingen, aber dies ist eine FAQ-Site. Fragen zu stellen, die extrem spezifische Antworten erfordern, hilft den Millionen von Benutzern nicht, die diese Site erreichen, indem sie ihre eigenen Probleme in Suchmaschinen eingeben. Meine Frage sollte allen anderen helfen, die Daten verlustfrei zwischen FFmpeg-Instanzen übertragen müssen, ohne alle mit einer Wand aus Text und Code abzulenken, die erklären, was ich getan habe, warum es nicht funktioniert hat und warum dies die einzige Option ist.
Antwort1
So leiten Sie Video und Audio verlustfrei von ffmpeg
zuffmpeg
Anforderungen durch den Fragesteller:
- Verlustfreie Weiterleitung von einer Instanz
ffmpeg
zu einer anderen - es ist egal, ob es von und nach
/dev/null
Beispiel:
ffmpeg -s 1280x720 -f rawvideo -i /dev/zero -ar 48000 -ac 2 -f s16le -i \
/dev/zero -c copy -f nut pipe:1 | ffmpeg -y -i pipe:0 -c copy -f nut /dev/null
Ich sehe keinen Grund, warum jemand so etwas tun sollte.ffmpeg
Darüber hinaus gibt es nur wenige Gründe, von „ nach“ weiterzuleiten, ffmpeg
wenn Sie höchstwahrscheinlich mit nur einem ffmpeg
Prozess alles tun können, was Sie möchten.
Was die Optionen bewirken:
-s 1280x720 -f rawvideo
– Optionen zur Beschreibung der Eingabe seit/dev/zero
ist kein typisches Eingabeformat und daher sind diese zusätzlichen Optionen erforderlich.-i /dev/zero
– Der Videoeingang. Er wird in diesem Beispiel verwendet, um einen Videostream aus dem „Nichts“ zu generieren. Dies wurde in diesem Beispiel verwendet, da der Fragesteller keine Informationen zu den verwendeten Eingängen bereitstellen wollte.-ar 48000 -ac 2 -f s16le
– Optionen zur Beschreibung der Eingabe seit/dev/zero
ist kein typisches Audioformat.-i /dev/zero
– Der Audioeingang. Er wird in diesem Beispiel verwendet, um aus dem „Nichts“ einen Audiostream zu erzeugen.-c copy
–Streamkopie, oder remuxen Sie die Eingänge zum Ausgang. Es wird keine Neukodierung durchgeführt, der Vorgang ist also verlustfrei. Es ist nicht bekannt, ob das Kopieren des Streams für den Fragesteller akzeptabel ist oder nicht. Vielleicht ist stattdessen eine Neukodierung erwünscht?-f nut
– Sie müssen angeben,ffmpeg
welches Format für die Pipe verwendet werden soll. Nut ist ein Containerformat.ffmpeg -formats
Eine vollständige Liste finden Sie unter . Ein weiteres flexibles Format ist-f matroska
, aber es ist unmöglich, ein geeignetes oder spezifisches Ausgabecontainerformat vorzuschlagen, ohne weitere Informationen vom Fragesteller zu erhalten.pipe:1
– Verwenden Sie diepipe
Protokollzur Ausgabe auf stdout. Alternativ kann die Nummer weggelassen werden (nurpipe:
) und standardmäßig wird der stdout-Dateideskriptor zum Schreiben und stdin zum Lesen verwendet.
Antwort2
So habe ich das gelernt (aus Teilen früherer Antworten): Man verwendet den rawvideo
Codec für das Video, den pcm_s16le
Audio-Codec und nut
den Wrapper von FFmpeg, um den Stream zu kodieren. nut
Wird von den wichtigsten Programmen außerhalb von FFmpeg nicht unterstützt, ist aber derzeit der einzige mir bekannte Container, der die unkomprimierten Formate unterstützt, die für eine effiziente Datenweiterleitung zwischen Prozessen erforderlich sind.
Die Argumente für diese Kodierung könnten wie folgt aussehen:
... -c:v rawvideo -c:a pcm_16le -f nut - ...
Einige Audiodateien werden mit 24-Bit- oder größeren Samples gespeichert. Für diese sollten Sie stattdessen pcm_24le
oder ein anderes Format verwenden. Die vollständige Liste der unkomprimierten Audioformate wird durch Ausführen von angezeigt ffmpeg -codecs
(Sie müssen die Liste danach durchsuchen). Wenn Sie die Samplegröße Ihrer Audiodateien nicht kennen, pcm_16le
sollte die Verwendung von keinen merklichen Qualitätsverlusten verursachen.
Stellen Sie am empfangenden Ende der Leitung die Eingabe auf die Standardeingabe ein. ffmpeg erkennt dann das Format und dekodiert den Stream.
... ffmpeg -i - ...
Die Auslassungspunkte (...) in dieser Antwort sind nicht Teil des Codes. Hier kommt Ihr Code hin. Die einzelnen Bindestriche (-) weisen FFmpeg an, entweder die Standardeingabe oder die Standardausgabe zu verwenden, je nachdem, wo sie erscheinen.
AKTUALISIEREN:
Ich habe ein einfaches Experiment durchgeführt, um dies zu verbessern, und es scheint, dass AVI ein besserer Container ist, weil andere Programme es verstehen (zumindest VLC).
... -c:v rawvideo -c:a pcm_16le -f avi - ...
Dies funktioniert genau wie die alte Version, mit dem zusätzlichen Vorteil der Kompatibilität.
Im Nachhinein bereute ich, dass ich eine Frage gestellt habe, die in vielen Situationen nicht hilfreich war, obwohl ich behaupte, dass Fragen für jeden hilfreich sein sollten. Dies macht die Antwort nützlicher.
Antwort3
Das einzige Problem mit der anderen Antwort ist, dass es pcm_s16le ist, nicht s16le. Außerdem enthält es viele redundante Parameter.
Ich würde in der Pipe PCM statt FLAC verwenden, da die Verarbeitung viel weniger Zeit in Anspruch nimmt (PCM ist Rohaudio, die Kodierung von FLAC dauert viel länger).
So würde ich es jedenfalls machen.
ffmpeg -i <input video file/stream> -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -f rawvideo -i - -vcodec <video output codec> -acodec <audio output codec> -vb <video bitrate if applicable> -ab <audio bitrate if applicable> <final-output-filename>
Das hat bei mir bei meinem letzten Versuch funktioniert, aber mein Ziel war, ffmpeg in ffplay umzuleiten, was ein etwas anderer Vorgang ist.
Beispiel:
Dies leitet ein Video von ffmpeg als Rohvideoausgabe und 16-Bit-Little-Endian-PCM an eine andere Instanz weiter (beides verlustfrei, es sei denn, Sie haben 24-Bit-PCM, dann ersetzen Sie pcm_s24le
.) Es konvertiert sie dann in der zweiten Instanz in h.264, mit der Fraunhofer-AAC-Bibliothek aus dem Android-Projekt ( libfaac
ist häufiger in ffmpeg-Builds enthalten. Sie können sie stattdessen durch dies ersetzen.)
ffmpeg -i montypythonsflyingcircus-s1e1.avi -vcodec rawvideo -acodec pcm_s16le pipe:1 | ffmpeg -i - -vcodec libx264 -acodec libfdk_aac -vb 1200k -ab 96k mpfc-s1e01-output.mkv
Wenn die Untertitel hierdurch nicht weitergeleitet werden, können Sie sie jederzeit in SRTs rippen und später wieder einfügen oder sie einfach zu den oben genannten Leitungen hinzufügen.