Wie erstelle ich mit ffmpeg schnell animierte GIFs in niedriger Qualität?

Wie erstelle ich mit ffmpeg schnell animierte GIFs in niedriger Qualität?

Wir generieren viele Miniatur-GIFs, deren Qualität bei weitem nicht so wichtig ist wie die Zeit, die zum Generieren benötigt wird. Das Generieren hochwertiger GIFs mit ffmpeg ist sehr gut beschrieben, aber ich habe nicht viel Glück damit, herauszufinden, wie ich so schnell wie möglich GIFs mit niedriger Qualität generieren kann.

Die Palettenberechnung nimmt mit dem folgenden Befehl (aus der Multi-Chain-Filtergraph-Antwort hier entnommen) den größten Teil der Ausführungszeit in Anspruch:So erstellen Sie effizient ein Best-Palette-GIF aus einem Videoausschnitt direkt aus dem Web):

ffmpeg -y -threads 8 -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter_complex "fps=24,scale=150:-1:flags=fast_bilinear,split=2 [a][b]; [a] palettegen [pal] fifo [b]; [b] [pal] paletteuse" output.gif

Die Ausführungszeit dieses Befehls mit 1000 Frames beträgt etwa 72 Sekunden. Davon entfallen etwa 67 Sekunden auf den Palettendurchgang, und dann rast es in etwa 5 Sekunden durch die eigentliche GIF-Generierung. Ich würde die gesamte Ausführungszeit gerne so weit wie möglich verkürzen und bin bereit, viel Bildqualität für die Geschwindigkeit zu opfern.

Antwort1

Ihre Verwendung der palettegen/ paletteuse-Filter verlangsamt den Befehl. Der einfache Weg, ein GIF in geringerer Qualität zu erhalten, wäre:

ffmpeg -f image2 -i "frames.%04d.jpg" output.gif

Mit zusätzlicher Skalierung:

ffmpeg -f image2 -i "frames.%04d.jpg" -vf scale=150:-1 output.gif

Sie können auch Frames im Ausgabe-GIF löschen, d. h. die Frames abtasten, sodass nicht alle verarbeitet werden. Um beispielsweise nur eine Ausgabe mit 1 FPS zu erhalten, verwenden Sie einen fpsFilter:

ffmpeg -i "frames.%04d.jpg" -vf "fps=fps=1,scale=150:-1" output.gif

Antwort2

Meine Aufgabe war es, die Zeit zu reduzieren, die zum Generieren eines animierten GIFs benötigt wurde, das so nah wie möglich an 30 Frames lang und 150 Pixel breit ist. Die meisten Sequenzen, die wir generieren, sind weniger als 1000 Frames lang. Wir hatten eine Sequenz mit 15.000 Frames und unsere Renderknoten brauchten17 Minutenum dieses GIF mit ca. 30 Bildern zu erstellen, was unannehmbar langsam ist.

Wir haben ffmpeg als Demultiplexer und als Pipe zu Imagemagick verwendet. Nach mehreren Stunden des Experimentierens bin ich zu folgenden Schlussfolgerungen gekommen:

  • Die Anzahl der Eingabebilder, die ffmpeg verarbeiten soll, beträgtBEI WEITEMdie wirkungsvollste Eingabe in Bezug auf die Ausführungsgeschwindigkeit. Wenn die Verwendung des Concat-Demuxers zum Überspringen von Eingabe-Frames eine Option ist, wird dies den größten Leistungsunterschied bewirken. Indem ich jeden 5. Frame nahm, konnte ich die Gesamtberechnungszeit auf1 Minute 45 Sekundenmit hochwertiger Lanczos-Neuskalierung und Palettenberechnung pro Frame.Die Generierung unserer 30-Frame-Vorschau-Miniaturansicht dauert jetzt weniger als 1 Sekunde.

  • Der Skalierungsalgorithmus war der nächste Faktor, der die Leistung am meisten beeinträchtigte (aber mit großem Abstand an zweiter Stelle). Die Verwendung von fast_bilinear anstelle von lanczos sparte 150 Sekunden Rechenzeit über alle 15.000 Frames.

  • Die am wenigsten einflussreiche Variable war die Palettenberechnung, und diese variierte je nach Skalierungsalgorithmus. Bei über 15.000 Frames mit Lanczos sparten wir etwa 17 Sekunden Ausführungszeit, wenn wir die Palettenberechnung eliminierten. Mit fast_bilinear sparten wir etwa 75 Sekunden Ausführungszeit.

Da der Skalierungsalgorithmus und die Palettenberechnung vernachlässigbar waren, haben wir sie letztendlich auf höchster Qualität belassen. Wir haben unsere Berechnungszeit von 17 Minuten auf unter 1 Sekunde reduziert, hauptsächlich indem wir ffmpeg angewiesen haben, das Lesen der Eingabedateien zu überspringen.

WICHTIGSTE ERKENNTNIS: ÜBERSPRINGEN VON EINGABEFRAMES vs. ÜBERSPRINGEN VON AUSGABEFRAMES

Der Grund, warum unser Prozess so lange dauerte, ist, dass Frame-Dropping die Ausführungszeit bei Verwendung des Image2-Demuxers nicht verbessert. Wenn Sie mit dem -rFlag und dem fpsFilter herumspielen, beeinflussen Sie die Anzahl der Frames, die im endgültigen GIF erscheinen, aber ffmpeg scheint trotzdem etwas mit allen 15.000 Eingabe-Frames zu tun.

Die einzige Möglichkeit, die ich gefunden habe, um ffmpeg dazu zu bringen, Eingabe-Frames zu überspringen, ist die Verwendung des concatDemuxers.

So erzeuge ich jetzt durch Überspringen von Eingabeframes in weniger als einer Sekunde hochwertige animierte GIF-Miniaturansichten auf meiner Entwicklungsmaschine:

# create text file which describes the ~30 input frames we want ffmpeg to process
seq -f "file 'left_frames.%04g.jpg'" 10000 500 25000 > tmp.txt

# generate the animated gif using ffmpeg only
ffmpeg -f concat -i tmp.txt -filter_complex "scale=150:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" output.gif

verwandte Informationen