Cloudinary Blog

Three Tips for Faster, Easier Video Delivery

Three Tips for Faster, Easier Video Delivery

Videos make websites more engaging and lively, promising audience “stickiness” and return visits. However, research studies show that slow startup or playback stalls of videos often leads to visitor loss. In fact, Akamai found that after a two-second delay, each additional second of stalling could cost you a 6-percent depletion of audience.

Not surprisingly, the major factor that accounts for poor video performance on the web is file size because video files probably take up the most bandwidth on your website. For slow network connections, videos might play back faster than they can be downloaded, causing stalls. By optimizing videos for both file size and quality, you reduce the to-be-downloaded content for the same user experience, delivering faster playback with fewer stalls.

This post shows you how to leverage Cloudinary to reduce video file size yet still retain a high quality with only three simple tips. That is, you set Cloudinary parameters to resize the video dimensions, optimize the compression, and add codec settings for the optimum video format.


Sign up for Cloudinary free today!


Resizing Video Dimensions

Oftentimes, raw videos are of a larger file size than is required for an ideal user experience. Even though many mobile devices can record videos in a 4K resolution, very few devices can actually replay 4K videos with that resolution. Resizing videos to 1080p, 720p, or even less pixels saves millions of pixels per frame, concurrently generating gratifyingly smaller files.

Take a 30 seconds long, 1280 pixels wide, and 720 pixels high video that weighs in at 25 MB. Resizing it to 960x540 produces a 10.7 MB video that’s 60-percent smaller. Plus, the video would start playing four times faster!

Resizing videos requires reencoding, which Cloudinary automatically handles once you’ve added a width (w) parameter to the video URL. For example, resizing this video with the w_960 parameter on Cloudinary—

Ruby:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", :end_offset=>"30")
PHP v1:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", array("end_offset"=>"30"))
PHP v2:
Copy to clipboard
(new VideoTag('rbsp_launch_720p_gz9zfm.mp4'))
  ->videoEdit(VideoEdit::trim()->endOffset(30));
Python:
Copy to clipboard
CloudinaryVideo("rbsp_launch_720p_gz9zfm").video(end_offset="30")
Node.js:
Copy to clipboard
cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().endOffset("30")).videoTag("rbsp_launch_720p_gz9zfm");
JS:
Copy to clipboard
cloudinary.videoTag('rbsp_launch_720p_gz9zfm', {endOffset: "30"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30"})
React:
Copy to clipboard
<Video publicId="rbsp_launch_720p_gz9zfm" >
  <Transformation endOffset="30" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rbsp_launch_720p_gz9zfm" >
  <cld-transformation endOffset="30" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rbsp_launch_720p_gz9zfm" >
  <cl-transformation end-offset="30">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().EndOffset("30")).BuildVideoTag("rbsp_launch_720p_gz9zfm")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().endOffset("30")).resourceType("video").generate("rbsp_launch_720p_gz9zfm.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setEndOffset("30")).generate("rbsp_launch_720p_gz9zfm.mp4")

—generated this resized version, which loads and starts playing much faster:

Ruby:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", :end_offset=>"30", :width=>960, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", array("end_offset"=>"30", "width"=>960, "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new VideoTag('rbsp_launch_720p_gz9zfm.mp4'))
  ->videoEdit(VideoEdit::trim()->endOffset(30))
  ->resize(Resize::scale()->width(960));
Python:
Copy to clipboard
CloudinaryVideo("rbsp_launch_720p_gz9zfm").video(end_offset="30", width=960, crop="scale")
Node.js:
Copy to clipboard
cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", width: 960, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().endOffset("30").width(960).crop("scale")).videoTag("rbsp_launch_720p_gz9zfm");
JS:
Copy to clipboard
cloudinary.videoTag('rbsp_launch_720p_gz9zfm', {endOffset: "30", width: 960, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", width: 960, crop: "scale"})
React:
Copy to clipboard
<Video publicId="rbsp_launch_720p_gz9zfm" >
  <Transformation endOffset="30" width="960" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rbsp_launch_720p_gz9zfm" >
  <cld-transformation endOffset="30" width="960" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rbsp_launch_720p_gz9zfm" >
  <cl-transformation end-offset="30" width="960" crop="scale">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().EndOffset("30").Width(960).Crop("scale")).BuildVideoTag("rbsp_launch_720p_gz9zfm")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().endOffset("30").width(960).crop("scale")).resourceType("video").generate("rbsp_launch_720p_gz9zfm.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setEndOffset("30").setWidth(960).setCrop("scale")).generate("rbsp_launch_720p_gz9zfm.mp4")

Optimizing Video Compression

Video quality is paramount. If compressing videos, that is, combining pixels, for faster video delivery compromises their quality, that’s a lost cause. A common solution is to compress videos with a tool that also ensures that the quality degradation after compression is imperceptible. An example is free and open-source FFmpeg, which does the job by adjusting the Constant Rate Factor with the crf parameter while encoding videos: the higher the crf value, the more the compression. By default, FFmpeg sets crf=23. In general, values up to 28 are perfectly acceptable for the web.

An impressive alternative is Cloudinary, which automatically optimizes quality while compressing videos in all transformation tasks. All you need to do is add the vc_auto parameter to the video URL. See these two examples:

Ruby:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", :end_offset=>"30", :video_codec=>"auto")
PHP v1:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", array("end_offset"=>"30", "video_codec"=>"auto"))
PHP v2:
Copy to clipboard
(new VideoTag('rbsp_launch_720p_gz9zfm.mp4'))
  ->transcode(Transcode::videoCodec(VideoCodec::auto()))
  ->videoEdit(VideoEdit::trim()->endOffset(30));
Python:
Copy to clipboard
CloudinaryVideo("rbsp_launch_720p_gz9zfm").video(end_offset="30", video_codec="auto")
Node.js:
Copy to clipboard
cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", video_codec: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().endOffset("30").videoCodec("auto")).videoTag("rbsp_launch_720p_gz9zfm");
JS:
Copy to clipboard
cloudinary.videoTag('rbsp_launch_720p_gz9zfm', {endOffset: "30", videoCodec: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", video_codec: "auto"})
React:
Copy to clipboard
<Video publicId="rbsp_launch_720p_gz9zfm" >
  <Transformation endOffset="30" videoCodec="auto" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rbsp_launch_720p_gz9zfm" >
  <cld-transformation endOffset="30" videoCodec="auto" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rbsp_launch_720p_gz9zfm" >
  <cl-transformation end-offset="30" video-codec="auto">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().EndOffset("30").VideoCodec("auto")).BuildVideoTag("rbsp_launch_720p_gz9zfm")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().endOffset("30").videoCodec("auto")).resourceType("video").generate("rbsp_launch_720p_gz9zfm.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setEndOffset("30").setVideoCodec("auto")).generate("rbsp_launch_720p_gz9zfm.mp4")

Ruby:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", :end_offset=>"30", :width=>960, :video_codec=>"auto", :crop=>"scale")
PHP v1:
Copy to clipboard
cl_video_tag("rbsp_launch_720p_gz9zfm", array("end_offset"=>"30", "width"=>960, "video_codec"=>"auto", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new VideoTag('rbsp_launch_720p_gz9zfm.mp4'))
  ->transcode(Transcode::videoCodec(VideoCodec::auto()))
  ->videoEdit(VideoEdit::trim()->endOffset(30))
  ->resize(Resize::scale()->width(960));
Python:
Copy to clipboard
CloudinaryVideo("rbsp_launch_720p_gz9zfm").video(end_offset="30", width=960, video_codec="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", width: 960, video_codec: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().endOffset("30").width(960).videoCodec("auto").crop("scale")).videoTag("rbsp_launch_720p_gz9zfm");
JS:
Copy to clipboard
cloudinary.videoTag('rbsp_launch_720p_gz9zfm', {endOffset: "30", width: 960, videoCodec: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("rbsp_launch_720p_gz9zfm", {end_offset: "30", width: 960, video_codec: "auto", crop: "scale"})
React:
Copy to clipboard
<Video publicId="rbsp_launch_720p_gz9zfm" >
  <Transformation endOffset="30" width="960" videoCodec="auto" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="rbsp_launch_720p_gz9zfm" >
  <cld-transformation endOffset="30" width="960" videoCodec="auto" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="rbsp_launch_720p_gz9zfm" >
  <cl-transformation end-offset="30" width="960" video-codec="auto" crop="scale">
  </cl-transformation>
</cl-video>
.NET:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().EndOffset("30").Width(960).VideoCodec("auto").Crop("scale")).BuildVideoTag("rbsp_launch_720p_gz9zfm")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().endOffset("30").width(960).videoCodec("auto").crop("scale")).resourceType("video").generate("rbsp_launch_720p_gz9zfm.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setEndOffset("30").setWidth(960).setVideoCodec("auto").setCrop("scale")).generate("rbsp_launch_720p_gz9zfm.mp4")

After transformation, the file size of the 1280-pixel-wide video drops from 25 MB to 4.1 MB, an 84-percent reduction. The 10.7-MB, 960-pixel-wide video takes up only 2.3 MB, 78.5 percent less than before. Both videos start up faster with more content in the buffer, rendering stalls during playbacks less likely.

You must be wondering: how has the video quality changed? As a rule, quality is measured with these three tests:

  • The Structural SIMilarity (SSIM) index
  • The Peak Signal-to-Noise Ratio (PSNR)
  • The Video Multimethod Assessment Fusion (VMAF) metric

The following table shows the values of the two example videos above:

Dimensions SSIM PSNR VMAF
1280x720
    0.985
    45.4
    89.6
960x540
    0.985
    45.1
    88.8

All the values fall within the acceptable limits, testifying to the fact that size reduction along with compression only minimally impacts the visual quality of the videos. Still, do test your post-compression videos to ensure that their quality meets your standards.

Identifying the Optimum Video Format

Finally, pinpoint a video format that best satisfies your requirements. The tests described in the preceding section were on H.264 MP4, an old yet popular format that works on almost all browsers. WebM with its VP8 and VP9 encodings are newer formats that deliver similar quality with smaller-sized videos. However, those two formats don’t work on certain browsers.

Reencoding videos with Cloudinary requires only changing vc_auto in the URL to vc_vp8, vc_vp9, or vc_h265. Cloudinary’s optimization capabilities for video delivery are at least 50-percent smaller in file size. Notwithstanding the negligible improvement in startup time, more video is in the buffer at startup, further reducing the probability of stalls.

Summing Up

As explained in this post, Cloudinary can, with these three simple, intuitive tips, downsize a video from 25 MB to 1.7 MB, 93% smaller, with no perceptible loss in visual quality. The time savings in downloads and startup in addition to fewer stalls during playbacks are all too obvious and significant. Do give those helpful features a try with your video delivery.

Note
For an even deeper dive into faster video delivery, view Doug's analysis here


Doug Sillars Doug Sillars s a freelance mobile performance expert, having helped thousands of developers speed up their mobile apps and websites. A Google Developer Expert and the author of O’Reilly’s “High Performance Android Apps”. Doug has spoken at developer conferences in the US and Europe, and blogs regularly at  dougsillars.com. You can also find him at @dougsillars on Twitter.

About Cloudinary

Cloudinary provides easy-to-use, cloud-based media management solutions for the world’s top brands. With offices in the US, UK and Israel, Cloudinary has quickly become the de facto solution used by developers and marketers at major companies around the world to streamline rich media management and deliver optimal end-user experiences.

For more information, visit www.cloudinary.com or follow us on Twitter


Further Reading on Video Manipulation

Recent Blog Posts

Creating an API With Python Flask to Upload Files to Cloudinary

Code

Cloudinary offers SDKs for many programming languages and frameworks. Even though it also offers an Upload API endpoint for both back-end and front-end code, most developers find the SDKs very helpful. If you're working with a powerful back-end framework like Python Flask, you'll be happy to hear that a Python SDK is now available.
This tutorial walks you through the process of building an API to upload images to Cloudinary. You can also upload other file types, including video and even nonmedia files, with the API.

Read more
How to Use the Cloudinary Media Editor Widget

At Cloudinary, we manage the entire pipeline of media assets for thousands of customers of varying sizes from numerous verticals.

As part of our commitment to support the entire flow of media assets, we are now introducing an intuitive media editing widget: an out­-of­-the-­box, interactive UI providing your users with a set of common image editing actions for immediate use on your website or web app. The widget is interactive and simple, built on Cloudinary's transformation capabilities, and requiring only a few lines of code to integrate. Afterwards, you can seamlessly and effortlessly add content to your site or app with no need for in-house image editing capabilities.

Read more
Shoppable Video Is Becoming Popular in E-Commerce

As pandemic restrictions necessitated, many shopping trips in 2020 took place outside the traditional brick-and-mortar store, or at least void of the physical aisle-browsing experience. Same-day curbside pickup became a safe and convenient alternative, and e-commerce transactions skyrocketed as consumers shopped online. In fact, Digital Commerce 360 estimates that, compared to 2019, e-commerce transactions grew by more than 40% last year.

Read more
Enhance Your Travel Site With Cloudinary in Anticipation of a Return to New Normal

Read more
The Benefits of Headless DAMs

Headless is not a buzzword anymore. In fact, the concept of headless architecture is gaining momentum due to the flexibility it offers for composing new experiences and for tackling the undue complexity of an ever-evolving technology stack. That’s because while the evolution of the martech landscape has enabled disruptive, digital innovations, the approach of buying point solutions for solving specific challenges can expose companies to the complicated nature of new technologies, systems, and platforms.

Read more