A good[ish] website
Web development blog, loads of UI and JavaScript topics
Here’s a little guide on how to convert large animated gifs into lighter videos. We’re going to do that with ffmpeg command line tool, or with HandBrake that provides a nice graphical user interface.
Graphics Interchange Format, invented in the late 80s, still persisting in our daily lives. Technologically speaking gifs are in the same club with Macintosh II, Windows 1, and floppy disc.
The technology behind animated gifs is old and clunky, a remnant of the 90s clipart and guestbooks internet. Gif is an extremely inefficient way to pack video, where as the static gif image is pretty good format for showing graphical shapes with few colors. But gifs were never meant to handle anything else than simple graphics.
Videos can act like gifs and have a much effective compression algorithm, videos also don’t need to be fully loaded to start the playback.
"Old tech" does not necessarily equal bad, we still use hammers for example. I guess gifs are good because:
img
tagIf we’d like to use a video instead of a gifs, the video replacement should more-or-less fill this criteria.
HTML5 video. Here’s the video formats commonly in use in the web and the browser support:
Edge | IE | Firefox | Chrome | Safari | Opera | |
---|---|---|---|---|---|---|
WebM | Yep ✅ | Nope 🚫 | Yep ✅ | Yep ✅ | Nope 🚫 | Yep ✅ |
Ogg | Yep ✅ | Nope 🚫 | Yep ✅ | Yep ✅ | Nope 🚫 | Yep ✅ |
mp4 | Yep ✅ | Yep ✅ | Yep ✅ | Yep ✅ | Yep ✅ | Yep ✅ |
Unsurprisingly mp4 is the most supported one. But, it’s not open source nor royalty free. What that means is: although you can freely upload mp4 videos to internet without worrying about royalties, but the companies implementing mp4 to their products need to pay a royalty fee. If I understand right, for instance, Linux distributions do not support mp4 out the box, because of the fees. Here’s an SO thread if you want to dig more into it.
Imgur for example has their own little gifv thingy, that in reality is just a muted video, which auto-plays and loops. The main format behind it is WebM and mp4 as fallback.
HandBrake provides a nice graphical user interface for compressing, converting, and resizing videos. It’s open source, has solid defaults, and is easy to use. You can also drill into the nitty gritty of the setting if you want more control.
Download HandBrake at handbrake.fr.
There’s a great command line tool: ffmpeg that’ll convert pretty much anything to any format. The above mentioned HandBrake uses ffmpeg under the hood.
Ffmpeg is bolted pretty deeply into the system, on Mac it needs the Command Line tools to function. You might know this error if you’ve ever installed ffmpeg:
Error: Xcode alone is not sufficient on Catalina.
Install the Command Line Tools:
xcode-select --install
Go ahead and add the Command Line Tools from xCode:
$ xcode-select --install
When done, install the actual ffmpeg:
$ brew install ffmpeg
Upgrading ffmpeg can be done with upgrade
command:
$ brew upgrade ffmpeg
Test that ffmpeg is actually installed in your system:
$ ffmpeg -version
There’s a lot of ways to using ffmpeg, it’s a bit like tuning a rocket engine. Here’s the best combination of options I’ve found so far, it seems to work pretty well:
$ ffmpeg \
-i test-gif.gif \
-movflags faststart \
-pix_fmt yuv420p \
-vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" \
test-output.mp4
Here’s what’s happening line-by-line:
-i
inputtest-gif.gif
in this case.-movflags
-pix_fmt
Pixel format-vf
filtergraph-filter:v
) which in this case is using a crop filter: "crop=trunc(iw/2)*2:trunc(ih/2)*2"
, in which the iw stands for "input width" and ih stands for "input height". This math operation: iw/2*2, makes sure that the video’s dimensions are divisible by 2, because an MP4 video using H.264 just needs that. See the cropping examples in the ffmpeg docs for more.Additional option:
-b:v
bitrate500K
to start with.When converting gifs to videos the quality settings doesn’t matter too much, because gifs are usually pretty shitty looking to start with. Try playing around with the bitrate to get a good weight/quality ratio:
$ ffmpeg \
-i test-gif.gif \
-movflags faststart \
-pix_fmt yuv420p \
-vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" \
-b:v 500K \ test-output.mp4
The originally 1.2MB gif file turned into 32KB mp4:
The below one is done with -c:v 50K
, it weighs only 16K but starts look pretty knackered.
I wrapped that into a simple function:
function videoConverter() {
local default_format="mp4"
local input=$1
local output=$2
# Bail if no input given
if [ -z $input ]; then
echo "Usage: gif_to_vid input.gif"
exit
fi
# Replace .gif with .mp4
local generated_file_name=${input/.gif/.$default_format}
# If output is empty, use the generated filename
local output_file=${output:-$generated_file_name}
ffmpeg \
-i $input \
-movflags faststart \
-pix_fmt yuv420p \
-vf "crop=trunc(iw/2)*2:trunc(ih/2)*2" \
$output_file
}
Usage:
$ videoConverter some-file.gif
That will create some-file.mp4
, because mp4 is set as the default format. Or give the output as the second param if you want to use another file format, or want to otherwise rename the output file:
$ videoConverter some-file.gif some-other-name.webm
ℹ️ ffmpeg will prompt you if the output file exists.
The same script can convert videos to gifs, too. It doesn’t really care what you throw at it, ffmpeg is doing its magic:
$ videoConverter video-file.mp4 a-gif-file.gif
HTML5 video syntax for a gif-like video:
<video autoplay loop muted playsinline src="/videos/some-vid.mp4">
<p>Your browser doesn’t supporting this video format</p>
</video>
For browsers to autoplay videos, they need to have muted
and playsinline
attributes, and of course the autoplay
attr.
If you want to use WebM videos, mp4 can be added as a fallback by using multiple source
elements. Browser will pick up the first format it supports, so the order matters:
<video autoplay loop muted playsinline>
<source src="/videos/some-vid.webm" type="video/webm" />
<source src="/videos/some-vid.mp4" type="video/mp4" />
<p>Your browser doesn’t supporting this video format</p>
</video>
Also, noteworthy video element attributes that I’ve excluded from the above example:
preload="metadata"
poster="img.jpg"
Here’s few handy GifCams and screen recorders:
Comments would go here, but the commenting system isn’t ready yet, sorry.