Video Slideshow Generation with Cloudinary

Banner for a MediaJam post


When you have an e-commerce site or you want to add some visual customization for your users, creating a video slideshow with specific images can be a nice touch. If you have existing images and videos, all of them can be combined to make something special for your users and potentially increase your sales and user retention.

In this article, we'll walk through how to make a custom video slideshow using Cloudinary. If you don't have a Cloudinary account already, you can sign up for a free one and start adding images and videos that you can use for your website.

When you log into your account, you'll be taken to the Dashboard. From there, navigate to the Media Library. This is where you can add any images and videos you want to use.

the media library view in your Cloudinary account

Setting up the project

We'll be making a simple page to show custom videos to different users with React. To start, open a terminal (I'm using VSCode) and run:

1npx create-react-app video-generator
2cd video-generator

You can delete the CSS files and remove the associated import statements in the App.jsx and index.js files.

With your Cloudinary account and our newly created React app, we can start making custom slideshows!

Making a slideshow

In the App.jsx file, you can delete everything and just follow along here. First, we need to install the styled-components package so that we can arrange the videos on a page with some CSS-in-JS.

1npm i styled-components

Now let's import a couple of packages at the top of the App.jsx file.

1import React from "react";
2import styled from "styled-components";

Next, we can create the App component and export it.

1function App() {}
3export default App;

Let's say you have data that shows the products people look at the most frequently on your site and you want to show three videos on your home page that highlights them. We'll start by making a couple of styled-components, one to style our videos and one to contain those videos.

1const Video =`
2 height: 200px;
3 padding: 24px;
4 width: 350px;
7const VideoContainer = styled.div`
8 display: flex;
9 flex-wrap: wrap;
10 justify-content: space-between;
11 width: 100%;

With these styled-components in place, we can start working on creating the video slideshows with Cloudinary.

Defining the slideshow elements

Videos are created using this URL syntax given in the Cloudinary docs:`cloudname`/video/upload/fn_render:`global-settings`;vars_(`slide-settings`(`individual-slide`))/`global-transformations`/`template`.`ext`

You can get the cloudname from your Cloudinary console.

your cloud name in the Cloudinary console

The global-settings are general settings applied to your video, like the height and width that Cloudinary should return as well as the duration that the video should be.

The slide-settings are responsible for the settings that apply to each slide. This will include things like how long the image is shown before switching to the next one, what kind of transition is applied between slides, and how long the transition lasts.

The individual-slide section is how you add images or videos based on their public_id to your slideshow. We'll use this to add the specific images we want a little later.

The global-transformations are how you can take advantage of the regular transformations Cloudinary has available, like automatically adjusting the quality of the video so that it's optimized for your users.

The template is how we let Cloudinary know we're going to create a video slideshow. You'll need to upload the template for the slideshow.

Since video slideshow generation is a beta feature, this is the only template you can work with for now.

Slideshow with only images

With that background info on how slideshow generation works, let's start adding a few things to our React app.

Inside of the App component, we're going to add a new object with the parameters we need to pass to Cloudinary to generate our video. This will contain the height, width, video duration, slide duration, transition duration, and images you want to show in the video. We'll also create an array containing the public_id of each image we want to show in the slideshow.

1const vidVars = {
2 w: 500,
3 h: 500,
4 du: 15,
5 sdur: 3000,
6 tdur: 1500,
9const vidA = ["3dogs", "reindeer", "cat"];

Now let's add the first video using our styled-components.

1return (
2 <VideoContainer>
3 <Video controls>
4 <source
5 src={`${
6 vidVars.w
7 };h_${vidVars.h};du_${vidVars.du};vars_(sdur_${vidVars.sdur};tdur_${
8 vidVars.tdur
9 };transition_s:circlecrop;slides_(${vidA
10 .map((mediaDoc) => `(media_i:${mediaDoc})`)
11 .join(";")}))/f_auto,q_auto/slideshow_hlhpzw.mp4`}
12 type="video/mp4"
13 />
14 Your browser does not support the video tag.
15 </Video>
16 <VideoContainer>

Make sure you get the exact name of the slideshow template from your Media Library. You'll need to update the name in the URL we created. It will be something different from slideshow_hlhpzw.mp4.

We've taken advantage of template strings in JavaScript to dynamically generate the slideshow URL for us using the general video settings object we created and the array of the public IDs of our images.

If you run the app with the npm start command in your terminal, you should see something similar to this.

first video slideshow

With the first video in place, let's add a couple more arrays defining the images we want to display in the other two slideshows.

1const vidB = ["reindeer", "3dogs", "dessert"];
3const vidC = ["beach-boat", "3dogs", "reindeer"];

Now that we know the images we're going to show, let's go ahead and add the other two videos using the styled component.

1<Video controls>
2 <source
3 src={`${
4 vidVars.w
5 };h_${vidVars.h};du_${vidVars.du};vars_(sdur_${vidVars.sdur};tdur_${
6 vidVars.tdur
7 };transition_s:circlecrop;slides_(${vidB
8 .map((mediaDoc) => `(media_i:${mediaDoc})`)
9 .join(";")}))/f_auto,q_auto/slideshow_hlhpzw.mp4`}
10 type="video/mp4"
11 />
12 Your browser does not support the video tag.
14<Video controls>
15 <source
16 src={`${
17 vidVars.w
18 };h_${vidVars.h};du_${vidVars.du};vars_(sdur_${vidVars.sdur};tdur_${
19 vidVars.tdur
20 };transition_s:circlecrop;slides_(${vidC
21 .map((mediaDoc) => `(media_i:${mediaDoc})`)
22 .join(";")}))/f_auto,q_auto/slideshow_hlhpzw.mp4`}
23 type="video/mp4"
24 />
25 Your browser does not support the video tag.

Now that you have all three videos in your app, you should see something like this in your browser.

all three slideshows in the flexbox

This is how we handle slideshow generation with just images, but we do have the option to include videos within our slideshows as well.

Slideshow with images and videos

Adding a video to the slideshow means we change a few settings in the URL we generate.

Instead of using media_i:public_id, we'll have to use media_v:public_id;type_s:video. This will tell Cloudinary that the asset we're using is a video and it will be handled accordingly.

We'll add an object with two arrays, one containing the images and the other containing the videos, to our App component.

1const vidD = {
2 images: ["reindeer", "sample"],
3 videos: ["elephants", "sea-turtle"],

Lastly, we'll add one more <Video> to the component.

1<Video controls>
2 <source
3 src={`${
4 vidVars.w
5 };h_${vidVars.h};du_${vidVars.du};vars_(sdur_${vidVars.sdur};tdur_${
6 vidVars.tdur
7 };transition_s:circlecrop;slides_(${vidD.images
8 .map((mediaDoc) => `(media_i:${mediaDoc})`)
9 .join(";")}${vidD.videos
10 .map((mediaDoc) => `(media_v:${mediaDoc};type_s:video)`)
11 .join(";")}))/f_auto,q_auto/slideshow_hlhpzw.mp4`}
12 type="video/mp4"
13 />
14 Your browser does not support the video tag.

Completed code

You can take a look at the complete code in this CodeSandbox or clone the GitHub repo!


Working with videos can be tricky, but Cloudinary does make it easier. Keep in mind that this is a beta feature, so it'll likely change a bit later.


Software Team Lead

Milecia is a senior software engineer, international tech speaker, and mad scientist that works with hardware and software. She will try to make anything with JavaScript first.