I recently explained how I captured a series of screenshots and turned them into a movie. While I was working on my tweet about the write-up, I thought an animated GIF of the final movie would be a nice way to show what it was I was trying to do. So that's what I wound up doing:
To create the demo movie on Time Sink's web page, I used a looping Keyboard Maestro macro, ffmpeg, and @ScreenFlow. https://t.co/uGfUkEhFMU pic.twitter.com/iy67d0lPq9
— Rob Griffiths (@rgriff) January 19, 2017
So how did I create the animated GIF from the movie file? I know there are any number of great apps that will do this (ScreenFlow, for one), but I had another thought: While working on the animated screenshot movie (which I created using ffmpeg), I had happened to read about ffmpeg's ability to create high quality animated GIFs, so I thought I'd give that a try.
Thanks to that linked blog post, it turns out to be incredibly easy to turn bits of any video into very high quality animated GIFs. There's a simple script on the blog post that takes just two parameters—the input and output filenames—and generates a nice animated GIF. However, there are a number of settings that I wanted to tweak but are hardcoded in the script.
So I took that script and modified it so I could pass all the major settings on the command line. Using my modified script, I can make an animated GIF out of a bit of any movie with this command:
mkgif 30 640 0:05 10 input.mp4 output.gif
The parameters, in order, are for the frame rate, target pixel width, start time at which to capture (in minutes and seconds), duration to capture from that start time (in seconds), the input movie's filename, and the new animated GIF's filename. Because that's a lot of parameters, I added some really basic help to remind myself of the format; just run the script with no parameters (or any number other than six), and the help will pop up.
Here's the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/bin/bash anGIF=`basename "$0"` if [[ $# -ne 6 ]]; then echo "" echo "$anGIF requires six inputs" echo "" echo "Example: $anGIF 30 640 0:03 5 input.mp4 output.gif" echo "" echo " 30 => Frame rate" echo " 640 => Target width in pixels" echo " 0:03 => Start time in min:sec" echo " 5 => Duration from start in sec" echo " input.mp4 => Source movie file" echo " output.gif => Destination animated gif" echo "" exit 0 fi palette="/tmp/palette.png" filters="fps=$1,scale=$2:-1:flags=lanczos" ffmpeg -v warning -ss $3 -t $4 -i $5 -vf "$filters,palettegen" -y $palette ffmpeg -v warning -ss $3 -t $4 -i $5 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $6 |
Save this somewhere on your $PATH, and remember to make it executable (chmod 755 scriptname). Name it whatever you like, of course; I used mkgif. It's quite boring in operation; here's how it looked when creating the animated GIF for my tweet:
[Parsed_palettegen_2 @ 0x7f92917007a0] Dupped color: FF050305
[Parsed_palettegen_2 @ 0x7f92917007a0] Dupped color: FF292827
[Parsed_palettegen_2 @ 0x7f92917007a0] Dupped color: FF2A272B
$
Not exciting, but very effective—the final GIF in my tweet was of very good quality and about 2.5MB in size. I love it when I discover how to do something new in the midst of discovering how to do something new!