So erstellen Sie aus einem Videoteil direkt aus dem Web ein Gif aus der besten Palette

878
Matteo Italia

Ich verwende seit einiger Zeit diese paar Befehle, um ein Videosegment in ein animiertes GIF umzuwandeln und ffmpegdie beste Palette dafür zu berechnen:

ffmpeg -ss $START -i $IN_FILE -t $LENGTH -vf "fps=$FPS,scale=$WIDTH:-1:flags=lanczos,palettegen" palette.png ffmpeg -ss $START -i $IN_FILE -i palette.png -t $LENGTH -filter_complex "fps=$FPS,scale=$WIDTH:-1:flags=lanczos [x]; [x] [1:v] paletteuse" output.gif 

Dies funktioniert sehr gut für lokale Dateien, aber wenn ich anfange, Remote-URLs zu verwenden $IN_FILE, wird der erforderliche Anteil zweimal heruntergeladen - einmal für die Palettengenerierung, einmal für die eigentliche Konvertierung.

Das Herunterladen der vollständigen Datei vorab ist generell außer Frage - oft interessiere ich mich für eine sehr kleine Sequenz inmitten eines längeren Videos.

Ich habe versucht, nur den kleinen Teil mit -ssund herunterzuladen -tund in eine temporäre Datei zu speichern, ohne erneut kodieren zu müssen:

ffmpeg -ss $START -i $IN_URL -t $LENGTH -vc copy -ac none temp.mkv 

In diesem Fall vermeide ich die Bandbreitenverschwendung (nur der relevante Teil der Datei wird heruntergeladen und nur einmal), aber die Suche ist nicht mehr genau, da -ssbei der Eingabe nur die Granularität von Schlüsselbildern für das Suchen bei der Stream-Kopie vorhanden ist .

Wenn Sie theoretisch in GIF konvertieren, ist es möglich, eine exakte Suche durchzuführen und das Problem zu beheben. Es scheint jedoch keine Möglichkeit zu geben, den ursprünglichen Zeitstempel des Starts der oben generierten temporären Datei zu erhalten. Daher ist dies nicht möglich zu berechnen, wo sollte ich -ssbeim Umcodieren in gif. Ich habe versucht mit zu spielen -copy_ts, aber es hat nichts Gutes gebracht.

Die triviale Lösung besteht darin, in diesem ersten Schritt eine erneute Codierung durchzuführen (möglicherweise Anwendung der Skalierung / erneuten Abtastung im Prozess, um dies später zweimal zu vermeiden), aber ich möchte den Kosten- / Qualitätsverlust einer zusätzlichen unbrauchbaren Codierung vermeiden.

Also: Wie kann ich die beste Video-zu-GIF-Konvertierung eines kleinen Teils einer möglicherweise großen Netzwerkdatei durchführen und sie effizient abrufen (= einmal herunterladen, nur den relevanten Teil), mit präziser Suche und ohne zusätzliche Neucodierungen?

1

1 Antwort auf die Frage

1
Matteo Italia

Das Problem kann leicht gelöst werden, indem ein Filtergraph mit mehreren Ketten verwendet wird. Dadurch können wir den Such / Download / Filter nur einmal ausführen und ihn auf verschiedene Arten verarbeiten. Der gesuchte / gefilterte Stream wird sowohl dem Palettengenerator als auch dem Palettenanwendungsfilter zugeführt, der ihn zusammen mit der generierten Palette verwendet. Grafisch:

 .--> palettegen [pal]---. input / | [0:v] -> fps -> scale -> split=2 [a][b] V with `-> [b] fifo [b] -> [b] [pal] paletteuse -> out.gif precise seek 

was übersetzt in:

ffmpeg -ss $START -I $IN_URL -t $LENGTH -filter_complex "fps=$FPS,scale=$WIDTH:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" out.gif 

Beachten Sie, dass zur Verwendung desselben Streams als Eingabe für zwei separate Pipelinenzweige der splitFilter verwendet werden muss.

Edit :fifowurde dank @Gyan Kommentarhinzugefügt; Dies ist notwendig, dapalettegenvor dem Generieren der Palette bis zum Ende des Streams gewartet werden muss und derpaletteuseVerbrauch erst beginnen kann[b], wenn die Palette vorhanden ist. Wenn das Video groß genug ist, sind die Standardpuffer für[b]nicht ausreichend undffmpegwerden Frames löschen. Die Lösung ist das Hinzufügen einesfifoin der Mitte vorhandenen Puffers mit beliebiger Größe (es ist darauf zu achten, dass die Videolänge nicht überschritten wird, da das Puffern des gesamten Streams im Speicher den verfügbaren Arbeitsspeicher belasten kann).

(schamloser Plug: Dies ist der Befehl, den ich jetzt in meinem tube2gif_bot- Telegramm-Bot verwende.)


Am wichtigsten ist, dass dies eine Geschichte über das Verstehen der Befehle ist, die Sie verwenden . Der zweite Befehl, der in der Frage zitiert wurde, verwendete bereits ein komplexes Filtergraph, aber als ich es blind aus dem Web kopierte, versuchte ich nicht wirklich, die undurchsichtige Filtergraph-Syntax zu verstehen, daher kam es mir nicht so vor, als würde ich es nur ein bisschen anpassen wäre die beste Lösung gewesen.

Benutzer müssen möglicherweise die zweite Split-Kopie zwischenspeichern, da palettegen standardmäßig nur die Palette zurückgibt, nachdem der gesamte Stream analysiert wurde. paletteuse, otoh, wartet darauf, dass diese Palette mit der Verarbeitung beginnt. Wenn Sie also längere Streams verwenden möchten, puffern Sie das Bild wie folgt: [b] fifo [b]; [b] [pal] ... " Gyan vor 6 Jahren 0
@Gyan: Uh, das ist eine andere Sache, die ich nicht wusste. Ich dachte, Filter würden alle erforderlichen Pufferungen selbst erledigen. Ich repariere das sofort. Matteo Italia vor 6 Jahren 0
In neueren Versionen tun sie es bis zu einem gewissen Punkt. Aber ffmpeg ist auch eine Streaming-App. Es gibt also eine Drop-Schwelle. Gyan vor 6 Jahren 1