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:

  1. 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.

  2. 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 ffmpeg

.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.gif

And 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:

    image=( out*.png )
    MAX=${#image[*]}
    echo $MAX
    for i in ${image[*]}
    do
        num=${i:5:3} # grab the digits
        compliment=$(printf '%04d' $(echo 2*$MAX-$num+1 | bc))
        echo $num $i $compliment
        ln $i out$compliment.png
    done

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.