There are many GIFs already available on the Internet, but it's often difficult to get the one you're looking for, and some of them are of poor quality. So here's a complete tutorial on how to create your own GIFs under GNU/Linux. Everything will be done on the command line with the imagemagick and ffmpeg tools.
root@host:~# apt install imagemagick ffmpeg
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
The previous extraction cannot be perfectly precise. This is not a problem, since we can delete the images we don't want to appear in our destination GIF file.
user@host:~$ magick -loop 0 *.png myimage.gif
Some films feature black bars at the top and bottom of the image. Here's how to remove them.
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
user@host:~$ magick 00039.png -crop 320x130+0+25 +repage Cropped_00039.png
user@host:~$ for i in 000*; do magick "$i" -crop 320x130+0+25 +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
If you want to add text with the classic GIF font, you'll need to install the Impact font from a Windows system to your GNU/Linux system.
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 'YOU'\''RE MAD!' Text_"$i"; done
user@host:~$ magick -loop 0 Text_000* myimage.gif
We can simulate text movement.
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
We can simulate text shaking.
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
Zoom in on the text.
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
Imagemagick's tool allows you to do many things, such as simulate a zoom. Let's give it a try.
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
Depending on where you want to publish your GIF, size could matter. For example, if I want to send a GIF by MMS while maintaining decent quality, the size needs to be less than 600KB.
Let's see differents way to reduce our 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
This option allows you to reduce the size of the GIF while degrading quality. This gives a good level of compression when there is little movement.
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
We can also reduce the size of our GIF by lowering the resolution of the frames.
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
Even tougher, you can even try droping frames, always with the aim of reducing size as much as possible.
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 :