Wie kann ich Daten verlustfrei von und zu FFmpeg weiterleiten?

Wie kann ich Daten verlustfrei von und zu FFmpeg weiterleiten?

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 ffmpegzuffmpeg

Anforderungen durch den Fragesteller:

  • Verlustfreie Weiterleitung von einer Instanz ffmpegzu 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.ffmpegDarüber hinaus gibt es nur wenige Gründe, von „ nach“ weiterzuleiten, ffmpegwenn Sie höchstwahrscheinlich mit nur einem ffmpegProzess alles tun können, was Sie möchten.

Was die Optionen bewirken:

  • -s 1280x720 -f rawvideo– Optionen zur Beschreibung der Eingabe seit/dev/zeroist 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/zeroist kein typisches Audioformat.

  • -i /dev/zero– Der Audioeingang. Er wird in diesem Beispiel verwendet, um aus dem „Nichts“ einen Audiostream zu erzeugen.

  • -c copyStreamkopie, 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, ffmpegwelches Format für die Pipe verwendet werden soll. Nut ist ein Containerformat. ffmpeg -formatsEine 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 diepipeProtokollzur Ausgabe auf stdout. Alternativ kann die Nummer weggelassen werden (nur pipe:) 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 rawvideoCodec für das Video, den pcm_s16leAudio-Codec und nutden Wrapper von FFmpeg, um den Stream zu kodieren. nutWird 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_24leoder 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_16lesollte 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 ( libfaacist 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.

verwandte Informationen