Using Cloudinary’s Fetch API to convert an animated GIF to a video

I like animated GIFs, like most people these days I think, but they are really heavy, hurting the performance of web pages, and consuming data plans faster than should be needed. So we need to convert them to videos, which are much lighter, for the same visual result. Let’s use Cloudinary.

You need a Cloudinary account to try all of this, but no fear, its free plan is really confortable for personnal use or just testing: signup for Cloudinary.

The animations in this post are animated GIFs provided by Giphy and obviously converted by Cloudinary.

Cloudinary has been providing animated GIFs to video conversion for a while, as this 4 years old blog post shows: Reduce size of animated GIFs, automatically convert to WebM and MP4.

Here is the simple process it described:

First upload the animated GIF to Cloudinary, so that it is available at this URL:

https://res.cloudinary.com/demo/image/upload/kitten_fighting.gif

Then, change the file extension at the end of the URL to ask Cloudinary to convert it into WebM or MP4 video:

https://res.cloudinary.com/demo/image/upload/kitten_fighting.webm
https://res.cloudinary.com/demo/image/upload/kitten_fighting.mp4

Easy! Magical!

But I want my publication process to be even easier, not requiring any upload (manual or automated) of my digital assets.

That’s why I find Cloudinary’s Fetch API awesome!

You can also use Cloudinary’s Auto-Upload, which provides a lot more features, but I like to keep things simple, and my master pristine images are hosted on my site anyway. Actually, my Jekyll-Cloudinary plugin uses the Fetch API to provide simple and efficient responsive images to Jekyll users.

So, how can we use the Fetch API to convert animated GIFs to videos?

Let’s say the pristine animated GIF is located at https://example.com/anim.gif.

The simple Fetch API URL to serve this image though Cloudinary, but untouched, would be this:

https://res.cloudinary.com/<cloud_name>/image/fetch/https://example.com/anim.gif

<cloud_name> should be replaced by your own cloud_name.

If we try to replace .gif with .mp4 at the end of this URL, like in the 4 years old Cloudinary post, it won’t work, because Cloudinary will try to fetch a video located at https://example.com/anim.mp4, which doesn’t exist.

The solution is to use the explicit format conversion parameter (f_) you can set in your Fetch URL, before the pristine image URL:

https://res.cloudinary.com/<cloud_name>/image/fetch/f_mp4/https://example.com/anim.gif

So, we can replace this:

<img src="https://example.com/anim.gif" alt="an animation">

With this:

<video autoplay loop muted playsinline>
  <source src="https://res.cloudinary.com/<cloud_name>/image/fetch/f_webm/https://example.com/anim.gif" type="video/webm">
  <source src="https://res.cloudinary.com/<cloud_name>/image/fetch/f_mp4/https://example.com/anim.gif" type="video/mp4">
  <p>Your browser doesn't support HTML5 video, <a href="https://example.com/anim.gif">download the animated GIF</a>.</p>
</video>

Don’t put an <img> tag with the animated GIF as the fallback, it would be downloaded anyway, even if the browser supports and shows the video.

Be careful, the transformation can take some time if the animated GIF is really heavy, so you might have to consider uploading it and perform the transformation asynchronously, without using the Fetch API.

I didn’t find any of this explained in Cloudinary documentation, maybe because it mixes images and videos.

One more thing…

If you want to dive deeper in this topic, you can discover how — in the near future — animated GIFs converted to videos could be better loaded in <img> tags, with Colin Bendell’s post in the 2017 edition of Performance (Advent) Calendar: Evolution of <img>: Gif without the GIF.

Additional resources

If you want to share an error or suggest an enhancement of this content, please edit the source on Github.