Skip to content

Create Simple Slideshows at Scale With Cloudinary’s Video Solution

In a previous post I discussed adding motion to your pictures using the zoompan effect. This effect enables you to make the most out of your pictures by turning images into videos for a quick and easy way to boost customer engagement and enhance visual experiences.

Cloudinary has some other features up its sleeve to help you generate your own video content at scale, saving you time and money. In this article, we’ll walk through how to create simple slideshows from existing images and crossfade transitions, and introduce you to our new video generation feature, which is a bit more complex but provides greater flexibility.

If all you’ve got to work with are images, you can string a number of them together to create a slideshow. Spice up your video by adding fun crossfade transition effects to move seamlessly between the images.

Imagine you’re developing a website for a real estate agent and are looking to entice potential buyers to view a property. By presenting the photos of the property as a slideshow, you can show off all the selling points in one visual experience, without requiring the buyer to click from one image to the next.

You can even add your branding as intro and outro slides. Here’s an example:

Loading code examples

Breaking this down, you can see that the base video is a blank video, which enables us to fade in from black at the start and gives us a video asset type to hang our images off:

Loading code examples

  • du_1.1 means play for a duration of 1.1 seconds
  • ar_16:9,c_fill,w_400 crops the video to a width of 400 pixels with an aspect ratio of 16:9. Notice that we use the same transformation for all our slideshow images too, as when concatenating assets they must have the same dimensions.

For each of the images in the slideshow we add this type of transformation:

fl_splice:transition_(name_radial;du_1.5),l_docs:room1/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
  • fl_splice:transition_(name_radial;du_1.5),l_docs:room1 concatenates the image with public ID docs/room1 to the previous asset using the radial transition for 1.5 seconds.
  • du_6.0 makes the image display for 6.0 seconds.
  • ar_16:9,c_fill,w_400 crops the image to a width of 400 pixels with an aspect ratio of 16:9, as previously discussed.
  • fl_layer_apply indicates the end of the transformations to be applied to the image.

Here’s the full URL, broken up for readability:

https://res.cloudinary.com/demo/video/upload/du_1.1/ar_16:9,c_fill,w_400/
fl_splice:transition_(name_fade;du_1.0),l_docs:citc-intro/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
fl_splice:transition_(name_radial;du_1.5),l_docs:room1/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
fl_splice:transition_(name_pixelize;du_1.5),l_docs:room2/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
fl_splice:transition_(name_hlslice;du_1.5),l_docs:room3/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
fl_splice:transition_(name_vertopen;du_1.5),l_docs:room4/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
fl_splice:transition_(name_radial;du_1.5),l_docs:citc-outro/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/
docs/empty.mp4

Notice all the different types of transition you can use — and there are many more! Try them out using this demo.

Once you’re happy with your slideshow, you can use the same template to sell many different properties. Just create a script to replace the public IDs of the images with the relevant ones for each of the properties. For maximum automation, use tags and/or structured metadata to group images belonging to a property, then create a query to return all the relevant public IDs.

You can find an example in this GitHub repo. It uses the client-side list feature to return a JSON response of all assets with a particular tag. Random transitions are used between the images. Here’s the part of the code that creates the URL:

const buildUrl = () => {

  // REPLACE THE RANDOM STRINGS IN THESE PUBLIC IDs 
  // WITH THE UPLOADED ONES AFTER RUNNING SETUP:
  const emptyVideoPublicId = 'empty_lzglfg.mp4';
  const introPublicId = 'citc-intro_wswhtj';
  const outroPublicId = 'citc-outro_nkjysl';

  const allTransitions = [
    'fade', 'wipeleft', 'wiperight', 'wipeup', 'wipedown', 'slideleft', 'slideright', 'slideup', 'slidedown', 'circlecrop', 'rectcrop', 'distance', 'fadeblack', 'fadewhite', 'radial', 'smoothleft', 'smoothright', 'smoothup', 'smoothdown', 'circleopen', 'circleclose', 'vertopen', 'vertclose', 'horzopen', 'horzclose', 'dissolve', 'pixelize', 'diagtl', 'diagtr', 'diagbl', 'diagbr', 'hlslice', 'hrslice', 'vuslice', 'vdslice', 'hblur', 'fadegrays', 'wipetl', 'wipetr', 'wipebl', 'wipebr', 'squeezeh', 'squeezev'
  ];

  // Start of the URL
  let slideshowUrl = `https://res.cloudinary.com/${cloudinary.config().cloud_name}/video/upload/du_1.1/ar_16:9,c_fill,w_400/fl_splice:transition_(name_fade;du_1.0),l_${introPublicId}/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/`;

  for (let publicId of publicIds) {

    // Pick a random transition
    const transition = allTransitions[Math.floor(Math.random() * allTransitions.length)];

    // Replace forward slashes with colons
    publicId = publicId.replace(/\//g, ':');

    // Append the asset to the URL
    slideshowUrl += `fl_splice:transition_(name_${transition};du_1.5),l_${publicId}/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/`;
  }

  // Append the outro and the rest of the URL
  slideshowUrl += `fl_splice:transition_(name_radial;du_1.5),l_${outroPublicId}/du_6.0/ar_16:9,c_fill,w_400/fl_layer_apply/${emptyVideoPublicId}`;

  return slideshowUrl;
};
Code language: JavaScript (javascript)

So far, we’ve seen how to create simple slideshows using transformation parameters to concatenate images with crossfade transitions. A slightly more complex way to achieve the same result is by using the video generation feature (currently in Beta). This feature has the advantage of a built-in mechanism for variables, allowing for an easier way to automate video creation at scale. It also supports the use of GL transitions, a more comprehensive library of transitions than the crossfade ones.

Video creation starts with a manifest_json that describes the video content in terms of tracks, clips and effects. For example, here’s a manifest_json that produces a video similar to the simple slideshow one with crossfade transitions:

{
    "type": "video",
    "width": 400,
    "height": 225,
    "duration": 34,
    "fps": 30,
    "vars": {
        "pic1": "docs/room1",
        "pic2": "docs/room2",
        "pic3": "docs/room3",
        "pic4": "docs/room4"
      },
    "tracks": [
      {
        "width": 400,
        "height": 225,
        "x": 0,
        "y": 0,
        "clipDefaults": {
          "clipDuration": 4000,
          "transitionDuration": 1500
        },
        "clips": [
          {
            "media": [
              "docs/empty",
              "video",
              "upload"
            ],
            "type": "video",
            "clipDuration": 500,
            "transformation": "c_fill",
            "transitionDuration": 1000,
            "transition": "fade"
          },
          {
            "media": [
              "docs/citc-intro",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill",
            "transition": "radial"
          },
          {
            "media": [
              "{{pic1}}",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill",
            "transition": "pixelize"
          },
          {
            "media": [
              "{{pic2}}",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill",
            "transition": "windowslice"
          },
          {
            "media": [
              "{{pic3}}",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill",
            "transition": "doorway"
          },
          {
            "media": [
              "{{pic4}}",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill",
            "transition": "radial"
          },
          {
            "media": [
              "docs/citc-outro",
              "image",
              "upload"
            ],
            "type": "image",
            "transformation": "c_fill"
          }
        ]
      }
    ]
  }
Code language: JSON / JSON with Comments (json)

This has one track with seven media clips, the first being the blank video as before, which this time isn’t strictly required, but included to make it similar to the previous simple slideshow. The other clips are the intro, outro and four pictures of the property, as before.

Notice that the public IDs of the property pictures are using variables (pic1, pic2, pic3, and pic4), allowing us to swap in any pictures we like from our product environment.

The easiest way to turn this manifest into a video is to save it as CltManifest.json, zip it up and upload it to your Cloudinary product environment (see Create a CLT template file for detailed instructions). Then, you just need to deliver the template as a video format (for example, change the extension to .mp4):

Loading code examples

To set the variables to use different pictures, use fn_render:vars, for example, fn_render:vars_(pic1_prop12-pic1;pic2_prop12-pic2;pic3_prop12-pic3;pic4_prop12-pic4), where prop12-pic1 is the public ID of the first picture and we’re assigning it to the pic1 variable, prop12-pic2 is the public ID of the second picture, and so on.

Note:

There’s currently a limitation that the public IDs can’t contain forward slashes.

Here’s the slideshow with new pictures:

Loading code examples

We’ve only scratched the surface of the video generation feature. You can use it for much more than simple slideshows. Find out everything you need to know in the docs.

It’s good to know that once you’ve created your slideshow, you can still apply further transformations to it in the usual way. For example, let’s add an audio track that will last for 33 seconds and fade out for the last three seconds (l_audio:docs:bg-music/du_33.0,e_fade:-3000/fl_layer_apply), plus optimize it for fast delivery (f_auto/q_auto):

Loading code examples

In summary, video content can be expensive and time-consuming to produce, but with Cloudinary’s solutions for generating your own video content at scale, you can strengthen your marketing campaigns and provide enhanced visual experiences in no time.

Back to top

Featured Post