Le tutoriel ultime pour créer ses propres GIF sous GNU/Linux

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

  • Sur 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.

Remove unwanted frames

Conversion des fichiers images vers un fichier GIF

user@host:~$ convert -loop 0 *.png myimage.gif

Résultat

Sylvester Stallone dans Rambo III qui met son bandeau rouge

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
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:~$ convert -crop 320x130+0+25 00039.png +repage Cropped_00039.png
  • Ce qui donne :
  • Pour recadrer l'ensemble de nos images :
user@host:~$ for i in 000*; do convert -crop 320x130+0+25 "$i" +repage Cropped_"$i"; done

Conversion des fichiers images vers un fichier GIF

user@host:~$ convert -loop 0 Cropped*.png myimage.gif

Résultat

Christian Bale dans American Psycho en train de rigoler

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:~$ convert 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 :
Jeff Bridges dans The Big Lebowski, t'es un sale con!

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 convert "$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 convert "$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:~$ convert -loop 0 Text_*.png myimage.gif

Résultat

Jeff Bridges dans le film The Big Lebowski, t'es un sale con!

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) :
Windows Fonts Directory Impact
  • 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 convert "$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 convert "$i" -font Impact -gravity south -pointsize "55" -stroke black -fill white -strokewidth 1 -annotate +0+0 'T'\''ES GIVRÉ!'  Text_"$i"; done
user@host:~$ convert -loop 0 Text_000* myimage.gif

Résultat

Batman : Freeze, t'es givré!

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 texte
  • a=-250 : position de départ du texte
  • ((a+=60)) : vitesse de défilement du texte
user@host:~$ 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+=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:~$ convert -loop 0 Texted_*.png myimage.gif

Résultat

Bill Murray dans le film Un jour sans fin, je réfléchis

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
  • $posX : position verticale du texte
user@host:~$ 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
  • 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:~$ convert -loop 0 Texted_*.png myimage.gif

Résultat

Jim Carrey dans Ace Ventura en Afrique, Warm!!

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 convert "$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:~$ convert -loop 0 Texted_*.png myimage.gif

Résultat

Jackie Chan dans Opération Condor, OK!

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 convert "$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 convert "$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 convert 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
  • 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équence
    • a=110 : première valeur du Zoom
    • b=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 frame
    • rm *_.png : suppression des fichiers temporaires
a=110
b=10
for i in $(seq 20 30); do 
	convert convert 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:~$ convert -loop 0 Text_*.png myimage.gif

Résultat

Street Fighter the movie Mr Bison Raul Julia Of Course!

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:~$ convert -loop 0 00* myimage.gif
user@host:~$ du -sh myimage.gif
2,3M    myimage.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda

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
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda

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:~$ convert myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
user@host:~$ du -sh result.gif
1,5M    result.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif
user@host:~$ du -sh result.gif
720K    result.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda

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:~$ convert -loop 0 out000* myimage.gif; du -sh myimage.gif
user@host:~$ convert myimage.gif -fuzz 2% -layers Optimize result.gif; du -sh result.gif
1,1M    result.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
536K    result.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda

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 convert "$i" -resize 240x Scalled_$i; done
user@host:~$ convert -loop 0 Scalled_000* myimage.gif; du -sh myimage.gif
1,3M	myimage.gif
Samuel L. Jackson dans Pulp Fiction, en train de boire du soda

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:~$ convert -delay 22 -loop 0 $(ls out000* | grep -E "*[02468].png") myimage.gif; du -sh myimage.gif
1,1M	myimage.gif
user@host:~$ convert myimage.gif -fuzz 5% -layers Optimize result.gif; du -sh result.gif
340K	result.gif
Samuel L. Jackson in Pulp Fiction, dans Pulp Fiction, en train de boire du soda
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :