Image and Video Conversion with Cloudinary

By  on  

I've always been fascinated with media formats and converting both images and video from one format to another.  Media conversion allows us to play videos on devices or apps with picky media requirements and load optimized formats for faster download speed.  I've written several media-related posts sharing how to accomplish all types of media conversions using ImageMagick, ffmpeg, gifsicle, and more, but they all rely on having media conversion tools available on the host machine, knowing the best configuration flags, and the time to do the work.

Over my time using Cloudinary, I've been impressed with its ability to accomplish media format conversions with ease.  Whether it's video, audio, or image, Cloudinary has made their API easy to use and so useful that optimizing and serving converted media for your users is an afterthought.  Let's look at the ways you can use Cloudinary to deliver optimized media to the client!

Simple File Extension Modification

The easiest way to convert media formats with Cloudinary is by simply changing the file extension. Assuming I've uploaded jack-bike.jpg, I can easily serve up a different format:

<!-- Load the original format -->
<img src="https://res.cloudinary.com/david-wash-blog/image/upload/jack-bike.jpg">

<!-- Let's load a WEBP instead! -->
<img src=".../image/upload/jack-bike.webp">

The same can be done for video and audio files:

<!-- Load the original format -->
<video src="https://res.cloudinary.com/david-wash-blog/video/upload/jack-wind.mp4"></video>

<!-- Let's load a WEBM instead! -->
<video src=".../video/upload/jack-wind.webm"></video>

Since Cloudinary offers helper libraries in a dozen server-side languages, you can use those to generate the image HTML as well:

// Node.js - convert JPG to PNG
cloudinary.image('jack-wind', { format: 'png' });
// PHP - convert JPG to PNG
cl_image_tag('jack-wind', array('format' => 'png'));
# Python - convert JPG to PNG
cloudinary.CloudinaryImage('jack-wind').image( format = 'png')

The video conversion is especially useful when providing multiple sources from which the browser or device may pick from:

<!-- Cloudinary can create your video poster image too! -->
<video width="640" controls
  poster="https://res.cloudinary.com/david-wash-blog/video/upload/jack-wind.jpg">
  <source
    src=".../video/upload/jack-wind.webm"
    type="video/webm">
  <source
    src=".../video/upload/jack-wind.mp4"
    type="video/mp4">
  <source
    src=".../video/upload/jack-wind.ogv"
    type="video/ogg">
</video>

And likewise with image srcset:

<img srcset=".../image/upload/jack-bike.jpg 320w,
             .../image/upload/jack-bike.jpg 480w,
             .../image/upload/jack-bike.png 800w"
        src=".../image/upload/jack-bike.png">

You can even work between media types, like uploading an animated GIF but rendering as a MP4, like most social media sites do:

<!-- Convert an animated GIF "jack-animated" to MP4! -->
<video src=".../video/upload/jack-animated.mp4"></video>

Simple file extension modification also makes lazy loading images based on client features easy; for example, detect WEBP support or fallback:

// Detect WEBP support
async function supportsWebp() {
  if (!self.createImageBitmap) return false;
  
  const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
  const blob = await fetch(webpData).then(r => r.blob());
  return createImageBitmap(blob).then(() => true, () => false);
}

// Lazy load image formats based on WEBP support
(async () => {
  if(await supportsWebp()) {
    myImage.src = '.../image/upload/jack-bike.webp';
  }
  else { // No WEBP support, fallback to original
    myImage.src = '.../image/upload/jack-bike.png';
  }
})();

And did you know you can also detect video types the browser can play?

function supportsVideoType(type) {
  let video;

  // Allow user to create shortcuts, i.e. just "webm"
  let formats = {
    ogg: 'video/ogg; codecs="theora"',
    h264: 'video/mp4; codecs="avc1.42E01E"',
    webm: 'video/webm; codecs="vp8, vorbis"',
    vp9: 'video/webm; codecs="vp9"',
    hls: 'application/x-mpegURL; codecs="avc1.42E01E"'
  };

  if(!video) {
    video = document.createElement('video')
  }

  return video.canPlayType(formats[type] || type);
}

// Usage
if(supportsVideoType('webm') === "probably") {
  myVideo.src = '.../video/upload/jack-animated.webm';
}
else {
  myVideo.src = '.../video/upload/jack-animated.mp4';
}

And don't forget format swapping is just a single operation -- you can transform your media at the same time:

<!-- Modify the image size on the fly! -->
<img src=".../image/upload/w_300,h_300/jack-bike.jpg">

<!-- Video too! -->
<video src=".../image/upload/w_300,h_300/jack-wind.mp4"></video>

By swapping out a few characters you're able to optimize load time for all of your media!  Cloudinary supports edge media types like webm, webp, and more so you can really get aggressive with your media performance!

Get Started with Cloudinary for Free

Cloudinary has a free tier so you can get started experimenting with the ability to transform and convert your media as you need to.  They've just announced a massive upgrade to the free tier so there's all the more reason to give them a shot at no cost.  There's loads you can do with Cloudinary; here are some of my previous experiments:

You can install all of the image conversion and manipulation software you'd like, write as many connectors and endpoints as you can think of, but nothing's as easy as using Cloudinary's simple, well documented API to transform, convert, customize, and deliver optimized media.

Recent Features

  • By
    39 Shirts &#8211; Leaving Mozilla

    In 2001 I had just graduated from a small town high school and headed off to a small town college. I found myself in the quaint computer lab where the substandard computers featured two browsers: Internet Explorer and Mozilla. It was this lab where I fell...

  • By
    5 Awesome New Mozilla Technologies You&#8217;ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • By
    WordPress-Style Comment Controls Using MooTools or jQuery

    WordPress has a nice little effect on the Admin Dashboard where it shows and hides the comment control links when you mouseover and mouseout of the record's container. Here's how to achieve that effect using MooTools or jQuery. The XHTML Notice that we place the links into...

  • By
    MooTools 1.2 Tooltips: Customize Your Tips

    I've never met a person that is "ehhhh" about XHTML/javascript tooltips; people seem to love them or hate them. I'm on the love side of things. Tooltips give you a bit more information about something than just the element itself (usually...

Discussion

  1. You don’t even necessarily need to detect webp in your JS; Cloudinary can do this out-of-the-box if you use f_auto in the URL. It does require Akamai CDN Delivery.

    https://cloudinary.com/blog/transparent_webp_format_cdn_delivery_based_on_visitors_browsers

    So if you then have a jpg in your img src and inspect it in your network tab in Chrome, you will see that even though the image name has the jpg extension, its content-type is actually webp. Awesome – we don’t need to keep track of file extensions at all.

  2. Ankit

    hey David,

    Do you have a solution/API that can convert video to several images?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!