gifs

felix schwenzel in über wirres

ich habe eine sei­te an­ge­legt, auf der alle gifs auf­ge­lis­tet sind, die ich hier auf wir­res.net bis­her be­nutzt habe: alle gifs auf wir­res.net

ei­gent­lich nut­ze ich schon lan­ge kei­ne gifs mehr, son­dern loo­pe klei­ne vi­deo-da­tei­en (ein mp4 mit den at­tri­bu­ten autoplay loop muted play­sin­line). das klappt in fast al­len mo­der­nen brow­sern und ist ef­fek­ti­ver als gifs, die meist ein mehr­fa­ches an da­tei­grös­se mit­brin­gen. das ma­chen die gros­sen platt­for­men auch schon seit län­ge­rer zeit (ca. 2014 fing twit­ter da­mit an).

aber ich habe jetzt wie­der an­ge­fan­gen gifs zu be­nut­zen als fall­back für die vi­deo-da­tei­en im RSS-feed. da die meis­ten an­bie­ter von rss-rea­dern vi­deo-at­tri­bu­te aus­fil­tern, funk­tio­nie­ren die vi­deo­da­tei­en im feed meis­tens nicht. also gebe ich per RSS gifs, statt vi­deo-loops aus — wenn ich nicht ver­ges­se das gif-fall­back zu er­zeu­gen und hoch­zu­la­den.

ein mp4 zu ei­nem an­stän­di­gen gif um­wan­deln geht mit die­sem script ganz ein­fach (wenn ffmpeg in­stal­liert ist):

#!/usr/bin/env bash
set -euo pipefail

if [ $# -lt 1 ]; then
  echo "Usage: $0 input.mp4 [fps] [width]" >&2
  exit 1
fi

INPUT="$1"
FPS="${2:-15}"       # Default: 15 fps
WIDTH="${3:-640}"    # Default: 640px Breite

if [ ! -f "$INPUT" ]; then
  echo "Input file not found: $INPUT" >&2
  exit 1
fi

BASENAME="$(basename "$INPUT")"
NAME="${BASENAME%.*}"

# temporäre Palette
PALETTE="$(mktemp "/tmp/${NAME}_palette_XXXX.png")"
OUTPUT_GIF="${NAME}.gif"

# Palette erzeugen
ffmpeg -y -i "$INPUT" \
  -vf "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos,pa­let­te­gen" \
  "$PALETTE"

# GIF erzeugen
ffmpeg -y -i "$INPUT" -i "$PALETTE" \
  -lavfi "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos[x];[x][1:v]pa­let­teu­se" \
  "$OUTPUT_GIF"

rm -f "$PALETTE"

echo "$OUTPUT_GIF"

das script ana­ly­si­ert zu­erst die far­ben des vi­de­os und passt die (ein­ge­schränk­te) farb­pa­let­te für das gif ent­spre­chend an.

bei­spiel:

mp4 (899 kb)

schnee gif
gif (5 mb)

das schö­ne an gifs ist, dass sie (wei­ter­hin) über­all funk­tio­nie­ren. an­de­rer­seits funk­tio­nie­ren mp4s auch fast über­all, ich kann sie bei blues­ky hoch­la­den und in den meis­ten mast­o­don ci­ents wer­den sie auch be­wegt an­ge­zeigt. aber trotz­dem fand ich es (für mich) prak­tisch eine über­sicht über mei­ne ver­wen­de­ten ech­ten gifs zu ha­ben.

und kein ar­ti­kel über gifs, in dem ich nicht auf das nach wie vor gross­ar­ti­ge, 2015 ein­ge­stell­te IF WE DON'T, RE­MEM­BER ME. (iw­drm), wo ir­gend­wer mit viel ge­duld sub­til be­weg­te ein­zel­bil­der ani­mier­te und als gifs ver­öf­fent­lich­te. ich bin nach wie vor ein sehr gros­ser fan die­ser ani­ma­tio­nen.


mein work­flow um „live fo­tos“ vom ipho­ne hier zu pos­ten geht üb­ri­gens so:

  • live foto auf dem ipho­ne zu ei­ner „end­los­schlei­fe“ ma­chen
  • air­drop auf den lap­top (kommt als mp4 an)
  • mp4 in pi­xel­ma­tor öff­nen und auf ca. 1000-1500 px brei­te ska­lie­ren
  • op­ti­mier­tes jpg als pos­ter-bild spei­chern
  • mp4 in pi­xel­ma­tor als op­ti­mier­tes mp4 spei­chern (oder mit ffmpeg oder me­diacms fürs web op­ti­mie­ren)

mit kir­by baue ich dann ein fig­cap­ti­on-vi­deo-html kon­strukt das in etwa so aus­sieht:

<figure class="video">
    <a href="https://wirres.net/media/pages/articles/gifs/e4e8b3d576-1767369338/img_5687.mp4_1080_h264.mp4">
        <video 
        class="videosrc" 
        height="480" 
        width="640"
        autoplay loop muted play­sin­line
        preload="metadata" 
        poster="https://wirres.net/media/pages/articles/gifs/e213b3af88-1767369369/img_5687-960x-q70.jpg" 
        title="">
            <source 
            src="https://wirres.net/media/pages/articles/gifs/e4e8b3d576-1767369338/img_5687.mp4_1080_h264.mp4" 
            type="video/mp4">
            </video>
    </a>
    <fig­cap­ti­on>mp4 (899 kb)</fig­cap­ti­on>
</figure>

beiträge die hierher linken
6 kommentare
Herr Rau

@ix Darf ich eine technische Frage stellen? Das Skript zum Umwandeln in gif habe ich ausprobiert, funktioniert, nun hätte ich gerne noch die Option, max_colors für das Erzeugen der Palette auf einen Wert zu setzen. Ich bin völlig unerfahren bei ffmpeg, und kann vermuten, wo das hin muss, habe aber keine Ahnung von Filtergraph und Chains und der Syntax. Könntest du das noch ergänzen im Skript, oder hier die angepasste Zeile veröffentlichen? Wenn das einfach geht und nicht zu viel Arbeit macht.

ix

@herr_rau das script habe ich cursor (oder gemini?) machen lassen. das kann ich gerne nochmal fragen.

ix

@herr_rau nicht getestet, frisch aus dem LLM:

#!/usr/bin/env bash
set -euo pipefail

if [ $# -lt 1 ]; then
  echo "Usage: $0 input.mp4 [fps] [width] [max_colors]" >&2
  exit 1
fi

INPUT="$1"
FPS="${2:-15}"           # Default: 15 fps
WIDTH="${3:-640}"        # Default: 640px Breite
MAX_COLORS="${4:-256}"   # Default: 256 Farben

if [ ! -f "$INPUT" ]; then
  echo "Input file not found: $INPUT" >&2
  exit 1
fi

BASENAME="$(basename "$INPUT")"
NAME="${BASENAME%.*}"

# temporäre Palette
PALETTE="$(mktemp "/tmp/${NAME}_palette_XXXX.png")"
OUTPUT_GIF="${NAME}.gif"

echo "Erzeuge Palette mit maximal $MAX_COLORS Farben..."

# Palette erzeugen
# Hier wurde max_colors zum Filter hinzugefügt
ffmpeg -y -i "$INPUT" \
  -vf "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos,palettegen=max_colors=${MAX_COLORS}" \
  "$PALETTE"

echo "Erzeuge GIF..."

# GIF erzeugen
ffmpeg -y -i "$INPUT" -i "$PALETTE" \
  -lavfi "fps=${FPS},scale=${WIDTH}:-1:flags=lanczos[x];[x][1:v]paletteuse" \
  "$OUTPUT_GIF"

rm -f "$PALETTE"

echo "Fertig: $OUTPUT_GIF"

                                                
Herr Rau

@ix Danke, ich probier's gleich aus! (Da OBEN hätte ich das gar nicht vermutet. Ich lerne noch. Und jetzt sehe ich erst das da UNTEN.)

Herr Rau

@ix Funktioniert, und ich verstehe jetzt mehr, danke!