Le tutoriel ultime pour créer ses propres GIF sous GNU/Linux
- Mise à jour le 23 déc. 2024
Intro
Il y a énormément de GIF disponibles gratuitement sur internet mais il n'est pas rare de ne pas trouver celui que l'on cherche ou dans des qualités médiocres. Voici donc un guide complet que j'utilise personnelement pour créer mes propres GIF sur GNU/Linux.
Installation des outils
- Ici depuis Debian :
root@host:~# apt install imagemagick ffmpeg
Créer son GIF depuis une vidéo
Convertir la séquence vidéo en fichiers png
La première chose à faire est de convertir une séquence vidéo en plusieurs fichiers images. Ici nous capturons la séquence vidéo de 2m16s à 2m22s.
- Frames : 10 par seconde
- Résolution : 320
- Temps de début : 2:14
- Durée : 6 seconds
user@host:~$ ffmpeg -ss 2:14 -t 6 -i /movies/1988.Rambo.III.MULTI.x264.1080p.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Suppression des images inutiles
Ensuite nous supprimons les images que l'on ne souhaite pas inclure dans notre GIF.

Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 *.png myimage.gif
Résultat

Suppression des bandes noires
Dans certains films des bandes noires en haut et en bas de l'image peuvent être présentes. Voici comment les supprimer.
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 8:26 -t 9 -i /movies/2000.American.Psycho.MULTI.AC3.1080p.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Suppression des bandes noires
- On récupère les informations sur les dimensions avec la commande
identify
:
user@host:~$ identify 00039.png
00039.png PNG 320x180 320x180+0+0 8-bit sRGB 79528B 0.000u 0:00.000
- Ici nous avons une résolution de 320 sur 180 pixels. Et nous avons deux fois 25 pixels à supprimer en haut et en bas de nos images :

- Recadrage de l'image :
Nous allons passer de 180 à 130 pixels en hauteur (180-25-25=130) :
user@host:~$ magick -crop 00039.png 320x130+0+25 +repage Cropped_00039.png
- Ce qui donne :

- Pour recadrer l'ensemble de nos images :
user@host:~$ for i in 000*; do magick -crop "$i" 320x130+0+25 +repage Cropped_"$i"; done
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Cropped*.png myimage.gif
Résultat

Ajouter du texte à notre GIF
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 19:24 -t 5 -i /movies/1998.The.Big.Lebowski.MULTI.1080p.Bluray.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Ajouter du texte à une image
-font
: utiliser la commande convert -list font pour voir les polices disponibles-pointsize
: taille du texte-annotate +0+0
: position du texte'\''
: caractères d'échapement pour'
\n
: Retour à la ligne
user@host:~$ magick 00016.png -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_00016.png
- Ce qui donne :

Ajouter du texte à plusieurs images
- On copie d'abord toutes les images vers de nouveaux fichiers :
user@host:~$ for i in 000*; do cp "$i" Text_"$i"; done
- On ajoute le texte sur toutes les images que l'on souhaite (ici de l'image
00016.png
à00027.png
) :
user@host:~$ for i in 0001[6-9]*; do magick "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_"$i"; done
user@host:~$ for i in 0002[0-7]*; do magick "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 30 -stroke black -fill white -strokewidth 1 -annotate +0+0 'YOU'\''RE\nAN ASSHOLE!!!' Text_"$i"; done
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Text_*.png myimage.gif
Résultat

Police Impact
Si l'on souhaite ajouter du texte avec la police habituelle des GIF on va avoir besoin de copier la police impact depuis un poste Windows vers notre station GNU/Linux.
- Depuis un Windows récupérer la Police Impact (
C:\Windows\Fonts\impact.ttf
) :

- Créer un nouveau répertoire Windows fonts :
root@host:~# mkdir /usr/share/fonts/WindowsFonts
- Copier le fichier
impact.ttf
vers notre dossier/usr/share/fonts/WindowsFonts
nouvellement créé :
root@host:~# mv impact.ttf /usr/share/fonts/WindowsFonts/
- On lance une regenération de notre cache de polices :
user@host:~$ fc-cache --force
- Faisons un test :
user@host:~$ ffmpeg -ss 10:48 -t 2 -i /movies/1997.Batman.and.Robin.MULTi.1080p.AC3.mkv -vf fps=10,scale=320:-1 $filename%05d.png
user@host:~$ for i in 000*; do cp "$i" Text_"$i"; done
- Notez qu'on utilise maintenant l'option
-font Impact
:
user@host:~$ for i in 0000[2-7]*; do magick "$i" -font Impact -gravity south -pointsize "55" -stroke black -fill white -strokewidth 1 -annotate +0+0 'FREEZE...' Text_"$i"; done
user@host:~$ for i in 0001[0-4]*; do magick "$i" -font Impact -gravity south -pointsize "55" -stroke black -fill white -strokewidth 1 -annotate +0+0 'T'\''ES GIVRÉ!' Text_"$i"; done
user@host:~$ magick -loop 0 Text_000* myimage.gif
Résultat

Jouer avec le texte
Défilement d'un texte
On peut aussi simuler un défilement de texte.
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 16:43 -t 1 -i /movies/1993.groundhog.day.MULTI.1080p.bluray.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Ajout du texte
$a
: position du textea=-250
: position de départ du texte((a+=60))
: vitesse de défilement du texte
user@host:~$ a=-250;for i in 000*; do magick "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 35 -stroke black -fill white -strokewidth 1 -annotate -"$a"+0 'I'\''M THINKING...' Texted_${i}; ((a+=60)); echo "$a"; done
- Même chose qu'au dessus mais plus facile à lire :
a=-250
for i in 000*
do
convert "$i" -font Cantarell-Extra-Bold -gravity south -pointsize 35 -stroke black -fill white -strokewidth 1 -annotate -"$a"+0 'I'\''M THINKING...' Texted_${i}
a=$((a+60))
echo "$a"
done
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
Résultat

Texte qui tremble
On peut simuler un tremblement du texte
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 45:02 -t 2 -i /movies/1995.ace.ventura.when.nature.calls.MULTI.1080p.x264.ac3.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Ajout du texte
$posX
: position horizontale du texte$posY
: position verticale du texte
user@host:~$ for i in 000*; do posX=$RANDOM;let 'posX %= 5'; posY=$RANDOM;let 'posY %= 15'; magick "$i" -font Impact -gravity south -pointsize 40 -stroke black -fill white -strokewidth 1 -annotate +"$posX"+"$posY" 'WARRRMMM!' Texted_${i}; done
- Même chose qu'au dessus mais plus facile à lire :
for i in 000*
do
posX=$RANDOM
let 'posX %= 5'
posY=$RANDOM;
let 'posY %= 15'
convert "$i" -font Impact -gravity south -pointsize 40 -stroke black -fill white -strokewidth 1 -annotate +"$posX"+"$posY" 'WARRRMMM!' Texted_${i}
done
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
Résultat

Texte qui s'agrandit
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 4:09 -t 2 -i /movies/1991.Armour.of.God.2.1080p.x264.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Ajout du texte
a=20
: text start size((a+=3))
: text growing speed
user@host:~$ a=20; for i in 000*; do magick "$i" -font Impact -gravity south -pointsize "$a" -stroke black -fill white -strokewidth 1 -annotate +0+0 'OK!' Texted_${i}; ((a+=3)); done
- Même chose qu'au dessus mais plus facile à lire :
a=20
for i in 000*
do
convert "$i" -font Impact -gravity south -pointsize "$a" -stroke black -fill white -strokewidth 1 -annotate +0+0 'OK!' Texted_${i}
((a+=3))
done
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
Résultat

Simuler un Zoom
Intro
Les outils Imagemagick permettent de faire pas mal de choses comme de simuler un zoom. Voyons cela avec l'exemple ci-dessous.
Convertir la séquence vidéo en fichiers png
user@host:~$ ffmpeg -ss 1:00:20 -t 2 -i /movies/1994.Street.Fighter.720P.x264.AC3.mkv -vf fps=10,scale=320:-1 $filename%05d.png
Ajout du texte
- Voir ici pour plus de détails.
user@host:~$ for i in 000*; do cp "$i" Text_"$i"; done
user@host:~$ for i in 0000[7-9]*; do magick "$i" -font Impact -gravity south -pointsize "35" -stroke black -fill white -strokewidth 1 -annotate +0+0 'OF COURSE!' Text_"$i"; done
user@host:~$ for i in 0001[0-4]*; do magick "$i" -font Impact -gravity south -pointsize "35" -stroke black -fill white -strokewidth 1 -annotate +0+0 'OF COURSE!' Text_"$i"; done
Zoomer en fin de séquence
user@host:~$ a=110; b=10; for i in $(seq 20 30); do magick Text_00018.png -resize "$a"% Text_000"$i"_.png; magick -gravity center -crop 320x133+$b+0 +repage Text_000"$i"_.png Text_000"$i".png ;((a+=30)); ((b+=25)); done; rm *_.png
- Même chose qu'au dessus mais plus facile à lire :
Text_00018.png
: frame sur laquelle sera effectué le zoom, ici la dernière de la séquencea=110
: première valeur du Zoomb=10
: première valeur du décalage du cadre vers la droite$(seq 20 30)
: nombre de frames sur lequel un zoom sera effectué (ici :Text_00020.png
àText_00030.png
)((a+=30))
: incrément du zoom pour chaque frame((b+=25))
: incrément du décalage vers la droite pour chaque framerm *_.png
: suppression des fichiers temporaires
a=110
b=10
for i in $(seq 20 30); do
convert magick Text_00018.png -resize "$a"% Text_000"$i"_.png
convert -gravity center -crop 320x133+$b+0 +repage Text_000"$i"_.png Text_000"$i".png
((a+=30))
((b+=25))
done
rm *_.png
Conversion des fichiers images vers un fichier GIF
user@host:~$ magick -loop 0 Text_*.png myimage.gif
Résultat

Réduire la taille d'un GIF
Selon vers où l'on souhaite partager son GIF, la taille peut compter. Par exemple pour envoyer un GIF par MMS la taille ne doit pas dépasser 600Ko, sinon il sera soit rejeté ou automatiquement compressé par le téléphone, avec souvent une qualité aléatoire.
Voyons différentes solutions pour réduire la taille d'un GIF.
Taille avec parametres standards
user@host:~$ ffmpeg -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1 $filename%05d.png
user@host:~$ magick -loop 0 00* myimage.gif
user@host:~$ du -sh myimage.gif
2,3M myimage.gif

Utiliser palettegen
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
user@host:~$ du -sh output.gif
1,7M output.gif

- Pour plus d'informations et d'options jeter un coup d'œil ici : http://blog.pkh.me/
Compresser avec l'option fuzz
Cela va réduire la taille de notre GIF en détériorant (un peu) la qualité. On peut obtenir de très bons résultats si il n'y a pas trop de mouvements dans la séquence à compresser.
user@host:~$ magick myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
user@host:~$ du -sh result.gif
1,5M result.gif

user@host:~$ magick myimage.gif -fuzz 5% -layers Optimize result.gif
user@host:~$ du -sh result.gif
720K result.gif

Fuzz + palettegen
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" out%05d.png
user@host:~$ magick -loop 0 out000* myimage.gif; du -sh myimage.gif
user@host:~$ magick myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
1,1M result.gif

user@host:~$ magick myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
536K result.gif

Réduire la résolution
On peut aussi diminuer la résolution de notre GIF
- Passer de 320 à 240 :
user@host:~$ for i in 00*; do magick "$i" -resize 240x Scalled_$i; done
user@host:~$ magick -loop 0 Scalled_000* myimage.gif; du -sh myimage.gif
1,3M myimage.gif

Drop frames + Fuzz
On peut aussi ne prendre qu'une frame (image) sur deux.
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
user@host:~$ ffmpeg -y -ss 17:05 -t 8 -i /movies/1994.Pulp.Fiction.MULTI.mkv -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" out%05d.png
user@host:~$ magick -delay 22 -loop 0 $(ls out000* | grep -E "*[02468].png") myimage.gif; du -sh myimage.gif
1,1M myimage.gif
user@host:~$ magick myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
340K result.gif
