Animierte GIF-Vorschauen auf der CLI automatisieren
Erstellen Sie für jede Datei in einem Videoverzeichnis ein kurzes GIF und behalten Sie deren
relativen Pfad im Ausgabeverzeichnis bei. Das folgende Bash-Skript zeigt die ersten drei Sekunden
mit 10 fps, bewahrt vorhandene Dateien und gibt einen Fehlerstatus zurück, wenn eine Konvertierung
fehlschlägt. Zwei Videos namens demo.mp4 in unterschiedlichen Ordnern erhalten
separate Vorschauen.
Linux-Werkzeuge einrichten
Verwenden Sie Bash, GNU findutils und coreutils sowie FFmpeg mit ffprobe.
Die Beispiele sind für Linux und ein Dateisystem mit Unterscheidung von Groß- und Kleinschreibung
sowie Hardlink-Unterstützung ausgelegt. Natives macOS und PowerShell wurden für diese Anleitung
nicht getestet. Verwenden Sie gewöhnliche SDR-Videos mit quadratischen Pixeln. HDR-Tonemapping und
die Korrektur anamorpher Videos erfordern eine separate Filterkonfiguration.
Diese Beispiele wurden mit FFmpeg 6.1.1 auf Ubuntu 24.04 und FFmpeg n9.0.1 auf Linux getestet.
Unter Ubuntu oder Debian installieren Sie die Werkzeuge mit:
sudo apt-get update && sudo apt-get install ffmpeg bash findutils coreutils
Das FFmpeg-Paket für Ubuntu enthält die Medienwerkzeuge. Prüfen Sie die in Ihrer Shell verfügbaren Versionen:
bash --version
ffmpeg -version
ffprobe -version
GIF wählen, wenn das Ziel es erfordert
GIF eignet sich für eine Illustration in Endlosschleife in der Dokumentation oder für ein System, das Bilder akzeptiert, aber keine Videos einbetten kann. Es hat eine begrenzte Farbpalette und keinen Ton. Ein GIF kann deutlich größer sein als seine MP4-Quelle. Vergleichen Sie daher die tatsächlichen Dateien, bevor Sie es für Webvorschauen nutzen. Unterstützt Ihr Ziel Videos, kann ein kurzer Videoclip bessere Qualität bei geringerer Dateigröße bieten. Googles Vergleich von GIF und Video veranschaulicht den möglichen Größenunterschied.
Eine einzelne begrenzte Vorschau erstellen
Legen Sie ein Video namens input.mp4 in Ihr Arbeitsverzeichnis und führen Sie
dann Folgendes aus:
(
if [[ -e ./preview.gif || -L ./preview.gif ]]; then
printf 'Refusing existing output: ./preview.gif\n' >&2
exit 1
fi
ffmpeg -hide_banner -loglevel error -nostdin -n -xerror -abort_on empty_output \
-t 3 -i ./input.mp4 -map 0:v:0 \
-vf "fps=10,scale='min(320,iw)':-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse" \
-t 3 -frames:v 30 -loop 0 -f gif ./preview.gif
)
Dies wählt den ersten Videostream aus, begrenzt die Breite auf 320 Pixel, ohne kleinere Eingaben zu
vergrößern, und erstellt ein GIF in Endlosschleife. Die eingabeseitige Option
-t 3 begrenzt den Abschnitt, der an die Filter übergeben wird.
Ausgabedauer und Frame-Obergrenze beschränken die Vorschau auf höchstens drei Sekunden und
30 Frames. Kurze Eingaben erzeugen kürzere Vorschauen. Beachten Sie die
Regeln für Eingabe- und Ausgabeoptionen von FFmpeg.
Die Aufteilung sendet die skalierten Frames sowohl an palettegen als auch an
paletteuse: Der eine Filter erstellt eine Palette aus dem Clip, der andere
wendet sie an. Die Eingabe zu begrenzen ist wichtig, da eine Palette für das gesamte Video die
Ausgabe verzögern und mehr Zwischenspeicherung erfordern würde. Die
Dokumentation der Palettenfilter beschreibt die verfügbaren
Einstellungen für Farben und Dithering.
Die Shell-Prüfung meldet eine vorhandene Datei preview.gif als Fehler;
-n weist FFmpeg ebenfalls an, sie nicht zu überschreiben. Manche
FFmpeg-Versionen können bei verweigertem Überschreiben null zurückgeben, daher reicht der Status
allein hier nicht aus. -nostdin deaktiviert interaktive Eingaben. Schlägt
die Konvertierung nach dem Erstellen der Datei fehl, kann ein unvollständiges GIF zurückbleiben.
Das folgende Batch-Skript verhindert, dass Teilausgaben im Ziel erscheinen, indem es zunächst in
eine temporäre Datei konvertiert.
Untersuchen Sie ein erfolgreiches Ergebnis mit:
ffprobe -v error -select_streams v:0 -count_frames \
-show_entries stream=width,height,nb_read_frames:format=duration,size \
-of json ./preview.gif
Bei einer Eingabe von mindestens drei Sekunden sind 30 Frames und eine Dauer von
3.000000 Sekunden zu erwarten. Öffnen Sie auch das GIF: Metadaten zeigen
nicht, ob die gewählte Anfangsszene sinnvoll ist.
Das Verzeichnis als Batch verarbeiten und Dateinamen erhalten
Speichern Sie dieses vollständige Skript als gif-previews.sh. Es verarbeitet
rekursiv reguläre Dateien mit der Endung .mp4, unabhängig von Groß- und
Kleinschreibung und ohne symbolischen Links zu folgen. Es hängt .gif
an den vollständigen relativen Dateinamen an: Aus videos/team/demo.mp4 wird
gifs/team/demo.mp4.gif. Die beibehaltene Erweiterung unterscheidet auf dem unterstützten
Dateisystem auch demo.mp4 von demo.MP4.
#!/usr/bin/env bash
set -euo pipefail
if (( $# > 2 )); then
printf 'Usage: bash gif-previews.sh [video-directory] [output-directory]\n' >&2
exit 1
fi
VIDEO_DIR=${1:-./videos}
OUTPUT_DIR=${2:-./gifs}
command -v ffmpeg >/dev/null
# Resolve both directory arguments from the caller's working directory.
start_dir=$PWD
cd -P -- "$VIDEO_DIR"
VIDEO_DIR=$PWD
cd -P -- "$start_dir"
mkdir -p -- "$OUTPUT_DIR"
cd -P -- "$OUTPUT_DIR"
OUTPUT_DIR=$PWD
cd -P -- "$VIDEO_DIR"
work=$(mktemp -d -- "$OUTPUT_DIR/.gif-preview.XXXXXX")
trap 'rm -rf -- "$work"' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
# Finish discovery first so a failed find cannot look like an empty successful batch.
find . -type f -iname '*.mp4' -print0 > "$work/files"
if [[ ! -s "$work/files" ]]; then
printf 'No MP4 files found.\n' >&2
exit 1
fi
generated=0
failed=0
while IFS= read -r -d '' video; do
output="$OUTPUT_DIR/${video#./}.gif"
if [[ -e "$output" || -L "$output" ]]; then
printf 'Refusing existing output: %q\n' "$output" >&2
failed=$((failed + 1))
continue
fi
if mkdir -p -- "${output%/*}" &&
ffmpeg -hide_banner -loglevel error -nostdin -y -xerror -abort_on empty_output \
-t 3 -i "$video" -map 0:v:0 \
-vf "fps=10,scale='min(320,iw)':-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse" \
-t 3 -frames:v 30 -loop 0 -f gif "$work/preview.gif" &&
ln -T -- "$work/preview.gif" "$output"; then
printf 'Generated: %q\n' "$output"
generated=$((generated + 1))
else
printf 'Failed: %q\n' "$video" >&2
failed=$((failed + 1))
fi
# Unlink the temporary name before reuse: published files share its inode.
rm -f -- "$work/preview.gif"
done < "$work/files"
printf 'Generated: %d; failed: %d\n' "$generated" "$failed"
if (( failed > 0 )); then
exit 1
fi
Führen Sie es aus dem Verzeichnis aus, das Ihren Ordner videos enthält:
bash gif-previews.sh ./videos ./gifs
Das Skript erhält Leerzeichen, Zeilenumbrüche, führende Bindestriche und literale Prozentzeichen
in Dateinamen. Die Ermittlung mit Nullzeichen als Trennzeichen hält jeden Dateinamen intakt.
Durch -nostdin kann FFmpeg die Eingabe der Schleife nicht konsumieren.
Ermittlung und Konvertierung laufen im selben physisch aufgelösten Eingabeverzeichnis, auch wenn
das Verzeichnisargument einen symbolischen Link gefolgt von .. enthält.
Vorhandene Ziele zählen als Fehler; sie werden nie stillschweigend übersprungen oder ersetzt.
Die Konvertierung verwendet -y nur für die private temporäre Datei.
GNU ln -T stellt ein fertiges GIF im Ziel bereit, ohne ein Ziel zu ersetzen,
das während der Konvertierung entsteht. Das temporäre Verzeichnis liegt im Ausgabedateisystem,
damit Hardlinks funktionieren können. Verwenden Sie einen Ausgabeverzeichnisbaum, den Sie
kontrollieren, ohne symbolisch verknüpfte Unterverzeichnisse oder verschachtelte Einhängepunkte.
Ein Batch mit gemischten Ergebnissen behält erfolgreiche GIFs und setzt die Verarbeitung nach
Fehlern einzelner Dateien fort. Anschließend endet er mit Status 1. Ein leeres Eingabeverzeichnis
führt ebenfalls zum Ende mit Status 1. Ein erneuter Durchlauf mit demselben Ausgabeverzeichnisbaum
meldet vorhandene Dateien als Fehler. Wählen Sie ein neues Ausgabeverzeichnis, um den gesamten
Batch erneut zu erzeugen. Bei gewöhnlichen Fehlern und Unterbrechungen werden temporäre Dateien
entfernt. Ein erzwungenes Beenden oder Stromausfall kann jedoch ein verstecktes Verzeichnis
.gif-preview.* hinterlassen.
Größen- und Qualitätsbudget anpassen
Beginnen Sie mit den Einstellungen für drei Sekunden, 320 Pixel und 10 fps und prüfen Sie
repräsentative Clips. Kleinere Abmessungen verringern Details; eine niedrigere Bildrate macht
Bewegungen weniger flüssig. Den Clip zu kürzen spart oft mehr als die Farbabstimmung. Wenn Sie
Bildrate oder Dauer ändern, aktualisieren Sie beide Werte für -t
und die Obergrenze für -frames:v gemeinsam. Für zwei Sekunden mit 8 fps
verwenden Sie eine Obergrenze von 16.
Das standardmäßige Dithering von paletteuse verbessert Farbverläufe, kann aber
sichtbares Rauschen hinzufügen. Ein Vergleich mit der dokumentierten Einstellung
dither=bayer an Ihrem eigenen Videomaterial lohnt sich. Diese Einstellungen
wägen Details, Bewegung und Farbtreue gegen die Dateigröße ab. Keine davon verspricht, dass GIF
einen Videocodec übertrifft.
Fehler in einem Batch diagnostizieren
- Vorhandene Ausgabe: Wählen Sie ein neues Ausgabeverzeichnis oder entfernen Sie gezielt nur die Vorschauen, die Sie erneut erzeugen möchten. Geänderte Qualitätseinstellungen überschreiben keine alten Ergebnisse.
- Ungültiges Video oder kein Videostream: Untersuchen Sie die genannte Quelldatei mit
ffprobe. Eine beschädigte Datei durch Umbenennen mit der Endung.mp4zu versehen, repariert sie nicht. Das Skript prüft den Vorschauabschnitt, nicht die Unversehrtheit des gesamten Videos. - Keine Frames oder ein ungeeigneter Anfang: Sehr kurze oder ungewöhnliche Eingaben können ohne Vorschau bleiben; das Skript wertet eine leere Ausgabe als Fehler. Ein schwarzer Anfang erfordert einen anderen Abschnitt.
- Dateisystem- oder Speicherfehler: Prüfen Sie freien Speicherplatz, Ausgabeberechtigungen und die Hardlink-Unterstützung. Reduzieren Sie bei großen Quelldateien Abschnittslänge und Abmessungen. Eine Cliplänge von höchstens drei Sekunden ist keine feste Obergrenze für den Speicherbedarf des Decoders oder die Ausführungszeit.
Nutzen Sie die ausgegebenen Dateipfade, um Fehler zu untersuchen. Prüfen Sie anschließend die erfolgreichen GIFs, bevor Sie sie in Ihren Medienkatalog aufnehmen.
