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.
root@host:~# apt install imagemagick ffmpeg
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.
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
Ensuite nous supprimons les images que l'on ne souhaite pas inclure dans notre GIF.
user@host:~$ magick -loop 0 *.png myimage.gif
Dans certains films des bandes noires en haut et en bas de l'image peuvent être présentes. Voici comment les supprimer.
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
user@host:~$ identify 00039.png
00039.png PNG 320x180 320x180+0+0 8-bit sRGB 79528B 0.000u 0:00.000
Nous allons passer de 180 à 130 pixels en hauteur (180-25-25=130) :
user@host:~$ magick -crop 320x130+0+25 00039.png +repage Cropped_00039.png
user@host:~$ for i in 000*; do magick -crop 320x130+0+25 "$i" +repage Cropped_"$i"; done
user@host:~$ magick -loop 0 Cropped*.png myimage.gif
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
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
user@host:~$ for i in 000*; do cp "$i" Text_"$i"; done
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
user@host:~$ magick -loop 0 Text_*.png myimage.gif
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.
root@host:~# mkdir /usr/share/fonts/WindowsFonts
root@host:~# mv impact.ttf /usr/share/fonts/WindowsFonts/
user@host:~$ fc-cache --force
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
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
On peut aussi simuler un défilement de texte.
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
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
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
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
On peut simuler un tremblement du texte
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
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
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
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
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
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
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
user@host:~$ magick -loop 0 Texted_*.png myimage.gif
Les outils Imagemagick permettent de faire pas mal de choses comme de simuler un zoom. Voyons cela avec l'exemple ci-dessous.
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
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
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
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
user@host:~$ magick -loop 0 Text_*.png myimage.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.
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
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
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
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
On peut aussi diminuer la résolution de notre GIF
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
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
Contact :