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

An Eye-Opening Talk: Building Apps for the Next Billion Users in Africa

William (iChuloo) Imoh, who hails from Lagos, Nigeria, recently embarked on a U.S. speaking tour, February 20-March 12, during which he powwowed with technical and product teams and communities at such renowned enterprises as Netlify, Pluralsight, Lucidchart, Twilio, and more in Salt Lake City, Dallas, Las Vegas, and San Francisco. On March 5, he gave an enlightening talk, entitled International Developers and Development: Building for the Next Billion Users at Cloudinary in Santa Clara, California. Below is a synopsis. For details, see the related slides.

Read more
The Debut of the Cloudinary Customer Advisory Board

Focus on customers has always been Cloudinary’s mantra. Because we owe them our success, we are constantly reaching out to our customers, not just for feedback on our offerings, but also for their vision, wish list, and buy-in of what Cloudinary can do to meet their needs and make them succeed. About six months ago, it occurred to us that it would be beneficial if we could meet regularly with those who are behind innovation at our key customers—executives, product gurus, developers, content managers—to swap strategies, product roadmaps, best practices, and such. In particular, we’d like to solicit actionable feedback as a foundation for our plans of product enhancements.

Read more
Media Management With the Cloudinary-Netlify CMS Integration

Static sites and the JAMstack are quickly becoming a standard for developing safe and performant websites with an optimal workflow for developers. Netlify CMS (not to be confused with the company that created it, Netlify) is an open source content management solution that works especially with static site generators such as Gatsby, Hugo, etc... enabling content storage in your Git repository along with your code for easier versioning, multichannel publishing, and direct content updates in Git.

Read more
Vitaly Friedman's Insights on Media Conferences

Vitaly Friedman is a die-hard devotee of beautiful content. Born in Minsk, Belarus, he studied Computer Science and Mathematics in Germany, unearthing in himself a passion for typography, writing, and design in the interim. After a six-year stint as a freelance designer and developer, he co-founded Smashing Magazine, a leading online publication on web design and development. You can follow SmashingMag on Twitter @SmashingMag.

Read more