Cloudinary Blog

Easily Generating Video Preview Clips with Cloudinary

How to Generate Video Preview Clips

Before deciding whether to watch a movie, you would likely check out its reviews and ratings on sites such as Rotten Tomatoes, IMDB, or Metacritic. You’re not alone. Online reviews figure prominently as a factor that influences viewers’ decisions on which movies to see. In addition, filmmakers always produce trailers to be shown as previews that showcase the highlights of their movies in the hope of stirring a buzz and anticipation for the debut.

Toward that end, suppose you as an app developer are tasked with generating a preview clip for a playlist of videos. Do take advantage of Cloudinary, a cloud-based, end-to-end solution for uploading, storing, transforming, optimizing, and delivering images and videos, with which you can manage media by way of a simple process. You can then focus on your primary tasks.

The Process

In this article, I’ll show you how to create video preview clips in two simple steps with Cloudinary.

Step 1: Upload the Video

In the console, click the Media Library tab and then click My File in the pane that opens. Drag and drop the video file to the pane.

Alternatively, click Browse in the My File pane and select and open the video file in your file system.

Upload

Tip: Embed the upload widget in your app to enable quick video upload from multiple channels.

Step 2: Build the Clip

Animated previews for any videos, including films, are often eye-catching and captivating. Because time is of the essence, you might want to produce multiple previews with different themes for various audiences.

The following procedure creates an approximately four-and-a-half-minute-long clip from a video, which stars a bunny.

Ruby:
cl_video_tag("bb_bunny")
PHP:
cl_video_tag("bb_bunny")
Python:
CloudinaryVideo("bb_bunny").video()
Node.js:
cloudinary.video("bb_bunny")
Java:
cloudinary.url().videoTag("bb_bunny");
JS:
cloudinary.videoTag('bb_bunny').toHtml();
jQuery:
$.cloudinary.video("bb_bunny")
React:
<Video publicId="bb_bunny" >

</Video>
Angular:
<cl-video public-id="bb_bunny" >

</cl-video>
.Net:
cloudinary.Api.UrlVideoUp.BuildVideoTag("bb_bunny")
Android:
MediaManager.get().url().resourceType("video").generate("bb_bunny.mp4");
iOS:
cloudinary.createUrl().setResourceType("video").generate("bb_bunny.mp4")

  1. Specify the duration (in seconds) of the preview video, for example, du_20.
  2. Specify the desired dimension (in pixels) of the preview video, for example w_400.
  3. Specify the first video section (so for start_offset) and the last one (eo for end_offset).
  4. Assign a name (public_id) for the videos to be concatenated with the overlay video parameter l_video.
  5. Activate the flag fl_layer_apply, which concatenates a section of the video on to another video by means of the offset parameters.
  6. Set splice so that Cloudinary concatenates the video section instead of adding it as an overlay.

Afterwards, perform the above six steps for the other sections of the video that contain the remaining scenes of the preview video. No overlays are necessary. It’s a cinch.

There you have it: a 20-second preview video:

Ruby:
cl_video_tag("bb_bunny", :transformation=>[
  {:width=>400, :duration=>"20", :crop=>"scale"},
  {:overlay=>"video:bb_bunny", :start_offset=>"3", :end_offset=>"7"},
  {:start_offset=>"0", :flags=>["layer_apply", "splice"], :width=>400, :crop=>"scale"},
  {:overlay=>"video:bb_bunny", :start_offset=>"25", :end_offset=>"30"},
  {:start_offset=>"4", :flags=>["layer_apply", "splice"], :width=>400, :crop=>"scale"},
  {:overlay=>"video:bb_bunny", :start_offset=>"240", :end_offset=>"280"},
  {:start_offset=>"8", :flags=>["layer_apply", "splice"], :width=>400, :crop=>"scale"}
  ])
PHP:
cl_video_tag("bb_bunny", array("transformation"=>array(
  array("width"=>400, "duration"=>"20", "crop"=>"scale"),
  array("overlay"=>"video:bb_bunny", "start_offset"=>"3", "end_offset"=>"7"),
  array("start_offset"=>"0", "flags"=>array("layer_apply", "splice"), "width"=>400, "crop"=>"scale"),
  array("overlay"=>"video:bb_bunny", "start_offset"=>"25", "end_offset"=>"30"),
  array("start_offset"=>"4", "flags"=>array("layer_apply", "splice"), "width"=>400, "crop"=>"scale"),
  array("overlay"=>"video:bb_bunny", "start_offset"=>"240", "end_offset"=>"280"),
  array("start_offset"=>"8", "flags"=>array("layer_apply", "splice"), "width"=>400, "crop"=>"scale")
  )))
Python:
CloudinaryVideo("bb_bunny").video(transformation=[
  {'width': 400, 'duration': "20", 'crop': "scale"},
  {'overlay': "video:bb_bunny", 'start_offset': "3", 'end_offset': "7"},
  {'start_offset': "0", 'flags': ["layer_apply", "splice"], 'width': 400, 'crop': "scale"},
  {'overlay': "video:bb_bunny", 'start_offset': "25", 'end_offset': "30"},
  {'start_offset': "4", 'flags': ["layer_apply", "splice"], 'width': 400, 'crop': "scale"},
  {'overlay': "video:bb_bunny", 'start_offset': "240", 'end_offset': "280"},
  {'start_offset': "8", 'flags': ["layer_apply", "splice"], 'width': 400, 'crop': "scale"}
  ])
Node.js:
cloudinary.video("bb_bunny", {transformation: [
  {width: 400, duration: "20", crop: "scale"},
  {overlay: "video:bb_bunny", start_offset: "3", end_offset: "7"},
  {start_offset: "0", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: "video:bb_bunny", start_offset: "25", end_offset: "30"},
  {start_offset: "4", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: "video:bb_bunny", start_offset: "240", end_offset: "280"},
  {start_offset: "8", flags: ["layer_apply", "splice"], width: 400, crop: "scale"}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
  .width(400).duration("20").crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("3").endOffset("7").chain()
  .startOffset("0").flags("layer_apply", "splice").width(400).crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("25").endOffset("30").chain()
  .startOffset("4").flags("layer_apply", "splice").width(400).crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("240").endOffset("280").chain()
  .startOffset("8").flags("layer_apply", "splice").width(400).crop("scale")).videoTag("bb_bunny");
JS:
cloudinary.videoTag('bb_bunny', {transformation: [
  {width: 400, duration: "20", crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), startOffset: "3", endOffset: "7"},
  {startOffset: "0", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), startOffset: "25", endOffset: "30"},
  {startOffset: "4", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), startOffset: "240", endOffset: "280"},
  {startOffset: "8", flags: ["layer_apply", "splice"], width: 400, crop: "scale"}
  ]}).toHtml();
jQuery:
$.cloudinary.video("bb_bunny", {transformation: [
  {width: 400, duration: "20", crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), start_offset: "3", end_offset: "7"},
  {start_offset: "0", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), start_offset: "25", end_offset: "30"},
  {start_offset: "4", flags: ["layer_apply", "splice"], width: 400, crop: "scale"},
  {overlay: new cloudinary.Layer().publicId("video:bb_bunny"), start_offset: "240", end_offset: "280"},
  {start_offset: "8", flags: ["layer_apply", "splice"], width: 400, crop: "scale"}
  ]})
React:
<Video publicId="bb_bunny" >
  <Transformation width="400" duration="20" crop="scale" />
  <Transformation overlay="video:bb_bunny" startOffset="3" endOffset="7" />
  <Transformation startOffset="0" flags={["layer_apply", "splice"]} width="400" crop="scale" />
  <Transformation overlay="video:bb_bunny" startOffset="25" endOffset="30" />
  <Transformation startOffset="4" flags={["layer_apply", "splice"]} width="400" crop="scale" />
  <Transformation overlay="video:bb_bunny" startOffset="240" endOffset="280" />
  <Transformation startOffset="8" flags={["layer_apply", "splice"]} width="400" crop="scale" />
</Video>
Angular:
<cl-video public-id="bb_bunny" >
  <cl-transformation width="400" duration="20" crop="scale">
  </cl-transformation>
  <cl-transformation overlay="video:bb_bunny" start-offset="3" end-offset="7">
  </cl-transformation>
  <cl-transformation start-offset="0" flags={{["layer_apply", "splice"]}} width="400" crop="scale">
  </cl-transformation>
  <cl-transformation overlay="video:bb_bunny" start-offset="25" end-offset="30">
  </cl-transformation>
  <cl-transformation start-offset="4" flags={{["layer_apply", "splice"]}} width="400" crop="scale">
  </cl-transformation>
  <cl-transformation overlay="video:bb_bunny" start-offset="240" end-offset="280">
  </cl-transformation>
  <cl-transformation start-offset="8" flags={{["layer_apply", "splice"]}} width="400" crop="scale">
  </cl-transformation>
</cl-video>
.Net:
cloudinary.Api.UrlVideoUp.Transform(new Transformation()
  .Width(400).Duration("20").Crop("scale").Chain()
  .Overlay(new Layer().PublicId("video:bb_bunny")).StartOffset("3").EndOffset("7").Chain()
  .StartOffset("0").Flags("layer_apply", "splice").Width(400).Crop("scale").Chain()
  .Overlay(new Layer().PublicId("video:bb_bunny")).StartOffset("25").EndOffset("30").Chain()
  .StartOffset("4").Flags("layer_apply", "splice").Width(400).Crop("scale").Chain()
  .Overlay(new Layer().PublicId("video:bb_bunny")).StartOffset("240").EndOffset("280").Chain()
  .StartOffset("8").Flags("layer_apply", "splice").Width(400).Crop("scale")).BuildVideoTag("bb_bunny")
Android:
MediaManager.get().url().transformation(new Transformation()
  .width(400).duration("20").crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("3").endOffset("7").chain()
  .startOffset("0").flags("layer_apply", "splice").width(400).crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("25").endOffset("30").chain()
  .startOffset("4").flags("layer_apply", "splice").width(400).crop("scale").chain()
  .overlay(new Layer().publicId("video:bb_bunny")).startOffset("240").endOffset("280").chain()
  .startOffset("8").flags("layer_apply", "splice").width(400).crop("scale")).resourceType("video").generate("bb_bunny.mp4");
iOS:
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation()
  .setWidth(400).setDuration("20").setCrop("scale").chain()
  .setOverlay("video:bb_bunny").setStartOffset("3").setEndOffset("7").chain()
  .setStartOffset("0").setFlags("layer_apply", "splice").setWidth(400).setCrop("scale").chain()
  .setOverlay("video:bb_bunny").setStartOffset("25").setEndOffset("30").chain()
  .setStartOffset("4").setFlags("layer_apply", "splice").setWidth(400).setCrop("scale").chain()
  .setOverlay("video:bb_bunny").setStartOffset("240").setEndOffset("280").chain()
  .setStartOffset("8").setFlags("layer_apply", "splice").setWidth(400).setCrop("scale")).generate("bb_bunny.mp4")
, complete with shots that highlight the fetching parts of the video.

Bonus Step: Remove the Audio

Depending on the context in which the preview video is shown, the associated audio might not apply. In that case, remove the audio by adding the ac_none parameter to the URL, like this:

https://res.cloudinary.com/demo/video/upload/w_400,du_72/l_video:bb_bunny,so_3,eo_7/so_0,fl_layer_apply.splice,w_400/l_video:bb_bunny,so_25,eo_30/so_4,fl_layer_apply.splice,w_400/l_video:bb_bunny,so_240,eo_290/so_8,fl_layer_apply.splice,w_400/ac_none/w_400/bb_bunny.mp4

A Cinch Indeed

As promised, the process calls for no coding at all. You could, however, polish up the preview clip, as follows:

  • Add text or an image overlay with a UI tip, such as “Click to play the full preview.”

  • Add an image to the end of the video with a suggestion or catchy message, for example, “Coming soon to a cinema near you.”

  • Add a quick flash between sections as a hint on what’s coming up in the clip!

Note
Videos spliced together must share the same width and height. To achieve that uniformity, set the size-transformation parameters.

Conclusion

For simplicity, this tutorial employs URLs to illustrate the Cloudinary capabilities in question. Do check out Cloudinary’s many useful libraries:

PHP, Ruby, Ruby, JavaScript, iOS, Android, and others.

For details on trimming videos, check out the Trimming Videos section of the Cloudinary documentation.

Again, creating video preview clips with Cloudinary is painless, intuitive, and efficient. Have a try!

Recent Blog Posts

10 Website Videos Mistakes and How to Solve Them

It should come as no surprise that video use on the internet is exploding. You can see the dramatic growth of video on the average site in this SpeedCurve blog post.

With the growth in video comes greater bandwidth use, which is not only costly for your IT budget, but for your visitors as well. Beyond the expense, there is the user experience to consider. The heavier the page, the longer it will take to load, and the greater likelihood visitors will abandon your site. Page load speed is also an important factor in SEO ranking, so clearly video is something we need to take seriously and get right. Video is challenging, presenting terms still unfamiliar to developers - like codecs, bitrate and adaptive bitrate streaming. As a result, mistakes are being made in video implementation.

Read more
Android Data Saver: Optimizing Mobile Data Usage with Cloudinary

Over the life of a mobile device, the cost of a cellular data plan often exceeds that of the device itself. To optimize data usage and purge useless data on their mobile devices, users can enable Data Saver from Android 7.0 (API level 24). To do so, users toggle Data Saver in quick settings under the Notification shade or under Settings > Data usage. With Data Saver enabled, apps that aren't whitelisted cannot use cellular data in the background. They are also directed to consume less data while active.

Read more
Introducing the Cloudinary Upload Widget v2

At Cloudinary, we manage the entire pipeline of media assets for thousands of customers of varying sizes from numerous verticals. Cloudinary is an end-to-end solution for all your image and video needs, including upload, storage, administration, manipulation, optimization and dynamic delivery.

Read more
Convert an Image to a 3D Canvas With Cloudinary

Note
This post was cowritten with Daniel Mendoza.
Note
This post was cowritten with Daniel Mendoza.
Note

Famed American poet Henry David Thoreau once said, “This world is but a canvas to our imagination.” And, like your imagination, the transformations you can apply to images with Cloudinary are practically endless. You can even render any flat image to appear three-dimensional and framed on a canvas.

Read more
Mobile Optimization: Optimize Your Mobile-Web User Experience

TL;DR

We live in a visual world, often while on the go, and consumers expect media-rich web content. Accordingly, the loading speed of images and videos is a big factor in user experience. To optimize customer satisfaction with your mobile content, you must focus on the quality, format, and size of your digital assets. With Cloudinary, optimization is simple, not only enhancing your mobile web and app performance, but also upping your SEO game and boosting customer experience.

Read more