Part 1:
The following is from my initial experiences with building animated gifs, and it’s pretty rough. Further down there’s a better explanation that includes a simple script to make do the conversion.
Converting video’s to animated GIF’s
So, converting a video to an animated gif is semi-easy, but mostly not. Here’s how it goes:
Make sure you have the following tools install:
ffmpeg
gifsicle
Both of which can be gotten via “sudo apt-get install <name>”.
Now for the fun part! For whatever reason, the built in video -> .gif convertion function of ffmpeg is super garbage. So, instead we do things a little bit better:
First, we split apart every single frame of the video into it’s own gif frame, with an appropriate file name to put it in the correct order.
Second, we use gifsicle to combine all these .gif frames into a single animated gif.
Here’s the command to split up the video into the gif frames:
ffmpeg -i file_to_be_input.mp4 out%04d.gif
Note the weird name specified for the output gif. For whatever reason, this seems to be important. It apparently makes sure each frame has the correct/appropriate number.
Alright, now you’ve got this big long list of individual frames, but no animated gif :( NEVER FEAR, all shall be well. To combine them into a single animated gif, this is the command:
gifsicle --delay=4 --loop *.gif > anim.gif
This will combine every “.gif” file in the current working directory into a single animated gif, in the order of the file name (lowest is first frame, highest is last frame).
Also note the --delay=4
option. What this option is doing is specifying the
delay in miliseconds between frames. I found that for a ~25 fps video, which
most video is, this will produce a reasonably “normal speed” gif.
For further gif awesomeness, you can shrink the size of your gif using the
imagemagick
software package (also installable via apt-get). The command to
remember is:
convert -layers Optimize input.gif output_optimized.gif
And that’s all. I was able to shrink a gif from 8mb to 2.1mb by doing this.
Converting Video to .gif (Continued)
So, after fidling with that a bunch more, I found out some interesting things:
The first is that you don’t need gifsicle at all. Imagemagick is able to do all of the necessary operations (and seems to be able to do them better!). To combine the composite frames into a .gif, use the following:
convert -delay 4 out*.gif anim.gif
However, this is actually not the only improvement. After messing around with this some more, I found a way to produce even higher quality (yet larger) .gifs. The only different step is instead of telling ffmpeg to export the frames as .gif’s, have it export them as .png’s. This lets Imagemagick handle the conversion to .gif, and it does a much better job of making the .gif look nice. The only thing is that it produces much larger .gif’s. Here is a comparison:
.gif converted via imagemagick
Notice that while the imagemagick .gif looks better, the one created by ffmpeg is half as big. This may be relevant info if you’re trying to upload a file to say, imgur, which has a 5mb limit on .gifs.
To actually do this, switch your ffmpeg line from this:
ffmpeg -i $1 out%04d.gif
to this:
ffmpeg -i $1 out%04d.png
Now FFMPEG will output high quality .png’s as the individual frames. Then, you’ll also have to change the imagemagick line to this:
convert -delay 4 out*.png anim.gif
In the end, this is what the whole script looks like:
#!/bin/bash # NOTE: the "$1" in the line below this means "command line argument #1 is # inserted here". If you're running these manually, replace the $1 with # the name of your video file. ffmpeg -i $1 out%04d.png # Extracts each frame of the video as a single gif convert -delay 4 out*.png anim.gif # Combines all the frames into one very nicely animated gif. convert -layers Optimize anim.gif optimized_output.gif # Optimizes the gif using imagemagick # vvvvv Cleans up the leftovers rm out* rm anim.gifAnd that’s how you convert a video to a .gif file!
Further Details on Converting Video to .GIF
So, after EVEN MOAR messing around with .gifs and videos, I have found a
nice and easy way to also do reverse .gifs! This script needs to be run
between the ffmpeg
step and the convert
step:
Btw, this is where I found this script though I’ve done a lot of adapting it to my needs.
Anyway, here’s an explanation of what the above is doing:
Here’s an abstract look at what it acomplishes.
For a set of files named
out*.png
it counts how many there are, then copys them in reverse order, renaming them sequentially, continuing with the numbering of the existing photos.So, if we had 5 frames named like so:
out0001.png out0002.png out0003.png out0004.png out0005.png
Then it would create the following:
out0001.png out0002.png out0003.png out0004.png out0005.png out0006.png <- Is actually a renamed out0005.png out0007.png <- renamed out0004.png out0008.png <- renamed out0003.png out0009.png <- etc out0010.png
What this does is make the .gif go forwards, then backwards (then it loops, continuing to go backwards then forwards). So you get a nice smooth effect. Sometimes it’s nice!
Resize .gif while making this conversion
You can also resize the gif that you create automatically. Like so:
convert -delay 4 out*.png -resize %50 anim.gif
This’ll resize it to %50 of it’s previous size, maintaining the aspect ratio.