Video optimization

Video content is extremely heavy, especially when compared to images, so it's essential to deliver your video content in the most optimized way.

Optimizing videos for web and mobile applications can be complex, however, with video files often very large. It can therefore result in longer upload & download times and very CPU-intensive transcoding and manipulation. The vast set of potential devices, resolutions, video formats, and video codecs makes it even more confusing.

This page describes how you can apply various optimization techniques to deliver the best quality videos with the lowest file sizes. It also outlines the default transformations applied by Cloudinary to aid the optimization.

See also: Image optimization

Default optimizations

Whenever you apply any transformation to video, Cloudinary performs the following optimizations by default:

  • Automatically selects the video codec (vc_auto). See video codec reference for the default values.
  • Applies a quality adjustment relevant to the codec. To override the default adjustments, set the quality parameter in your transformation.

How to optimize video quality

You can control the video quality with the quality parameter (q in URLs). This parameter represents a mapping between the actual low-level settings of each different video format normalized to a quality value between 1 (lowest) and 100 (highest). Reducing the quality is a trade-off between visual quality and file size. See video_codec in the Video transformations reference table for the default settings for each format.

For example, reducing the quality of the uploaded mp4 video named dog to 50 results in a file size of 1.1 MB compared to the original file size of 9.8 MB:

Ruby:
Copy to clipboard
cl_video_tag("dog", :quality=>50)
PHP:
Copy to clipboard
cl_video_tag("dog", array("quality"=>50))
Python:
Copy to clipboard
CloudinaryVideo("dog").video(quality=50)
Node.js:
Copy to clipboard
cloudinary.video("dog", {quality: 50})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().quality(50)).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {quality: 50}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {quality: 50})
React:
Copy to clipboard
<Video publicId="dog" >
  <Transformation quality="50" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" >
  <cld-transformation quality="50" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" >
  <cl-transformation quality="50">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Quality(50)).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().quality(50)).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setQuality(50)).generate("dog.mp4")

Automatic quality (q_auto)

Instead of defining a specific quality value, you can use Cloudinary's intelligent quality and encoding algorithm. The algorithm analyzes each video to decide on the optimal encoding characteristics that will produce the best visual quality while minimizing the file size.

The quality transformation parameter can be set to auto (q_auto in URLs) in order to perform automatic quality encoding. Further control of the automatic quality selection is supported as follows:

  • q_auto - The optimal balance between file size and visual quality. By default, this is the same as q_auto:good.
  • q_auto:best - Less aggressive algorithm. Generates bigger files with potentially better visual quality.
  • q_auto:good - Ensuring a relatively small file size with good visual quality. Example of a target audience: stock media sites that display videos with a high visual quality.
  • q_auto:eco - More aggressive algorithm, which results in smaller files of slightly lower visual quality. Example of a target audience: popular sites and social networks with a huge amount of traffic.
  • q_auto:low - Most aggressive algorithm, which results in the smallest files of low visual quality. Example of a target audience: sites using thumbnail preview videos that then link to higher quality videos.

Click the various quality settings below to see how the resulting file size is affected when encoding the hourglass video:

Quality: auto:low
Size: 170.27KB
auto:low auto:eco auto:good auto:best 80 100

Notes

  • Automatic quality is supported for videos using the h264, h265 and VP9 codecs.
  • Cloudinary already performs some basic content-aware encoding when delivering a transformed video. See the video_codec section of the Video transformations reference table for the default settings for each format, which includes setting quality to 70. Using q_auto overrides this default setting, producing slightly different results depending on the complexity of the video.
  • q_auto cannot be used within named transformations, however q_auto:[Mode] (e.g., q_auto:good) is supported within named transformations.

Control the quality of WEBM transcoding

In some cases, transcoding videos from mp4 to webm (VP8/9 encoding) may give a pixelated result. In these cases, you can control the final quality by setting a maximum quantization percentage (1-100 range) value:qmax in addition to a fixed quality value. This can help ensure that the video is not over-quantized.

For example, you could set the quality parameter to: "80:qmax_90" to ensure that the transcoded video is quantized no more than 90% of the maximum possible quantization. When you set a qmax value, the quality value is relative to the quantization value.

For example, if you transcode the video below to .webm format without setting a max quantization value, the quality drops fairly significantly compared to its .mp4 counterpart, but by setting the max quantization to 70, you get a better visual quality.

Ruby:
Copy to clipboard
cl_video_tag("Liverpool_vs_Roma_full", :duration=>"30", :quality=>"70:qmax_20")
PHP:
Copy to clipboard
cl_video_tag("Liverpool_vs_Roma_full", array("duration"=>"30", "quality"=>"70:qmax_20"))
Python:
Copy to clipboard
CloudinaryVideo("Liverpool_vs_Roma_full").video(duration="30", quality="70:qmax_20")
Node.js:
Copy to clipboard
cloudinary.video("Liverpool_vs_Roma_full", {duration: "30", quality: "70:qmax_20"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().duration("30").quality("70:qmax_20")).videoTag("Liverpool_vs_Roma_full");
JS:
Copy to clipboard
cloudinary.videoTag('Liverpool_vs_Roma_full', {duration: "30", quality: "70:qmax_20"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("Liverpool_vs_Roma_full", {duration: "30", quality: "70:qmax_20"})
React:
Copy to clipboard
<Video publicId="Liverpool_vs_Roma_full" >
  <Transformation duration="30" quality="70:qmax_20" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="Liverpool_vs_Roma_full" >
  <cld-transformation duration="30" quality="70:qmax_20" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="Liverpool_vs_Roma_full" >
  <cl-transformation duration="30" quality="70:qmax_20">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Duration("30").Quality("70:qmax_20")).BuildVideoTag("Liverpool_vs_Roma_full")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().duration("30").quality("70:qmax_20")).resourceType("video").generate("Liverpool_vs_Roma_full.webm");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setDuration("30").setQuality("70:qmax_20")).generate("Liverpool_vs_Roma_full.webm")

Keep in mind that the lower you set the qmax value, the higher the bitrate, and the larger the resulting file size.

If you don't supply a qmax value, then the maximum quantization is 100%, although the actual applied quantization will be determined by other factors such as the quality value you set (or your account's default quality setting), the content of the actual video, and other transformation and optimization options you include.

Bitrate control

Use the bit_rate parameter (br in URLs) for advanced control of the video bitrate. This parameter controls the number of bits used to represent the video data. By default, the br_ value uses variable bitrate (VBR), where the specified value indicates the maximum bitrate. The actual bitrate and quality are optimized according to the video content, to conserve bandwidth and storage. You can also specify a constant bitrate value (CBR): br_[value]:constant in URLs. In this case, the specified bitrate will be used even in cases where that high of a rate is not necessary for good quality viewing. When you specify a constant bitrate, the quality parameter is ignored.

bit_rate can take one of the following values:

  • An integer e.g. 120000.
  • A string supporting ‘k’ and ‘m’ (kilobits and megabits respectively) e.g. 250k or 2m.

For example, setting the maximum bitrate of the uploaded mp4 video named dog to 250 kilobits (also reducing file size down to ~550 KB):

Ruby:
Copy to clipboard
cl_video_tag("dog", :bit_rate=>"250k")
PHP:
Copy to clipboard
cl_video_tag("dog", array("bit_rate"=>"250k"))
Python:
Copy to clipboard
CloudinaryVideo("dog").video(bit_rate="250k")
Node.js:
Copy to clipboard
cloudinary.video("dog", {bit_rate: "250k"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().bitRate("250k")).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {bitRate: "250k"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {bit_rate: "250k"})
React:
Copy to clipboard
<Video publicId="dog" >
  <Transformation bitRate="250k" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" >
  <cld-transformation bitRate="250k" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" >
  <cl-transformation bit-rate="250k">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().BitRate("250k")).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().bitRate("250k")).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setBitRate("250k")).generate("dog.mp4")

Note
If you define a maximum or constant bitrate as well as a maximum quantization (qmax), and there is a conflict between these two settings, the maximum or constant bitrate will take precedence.

Adaptive bitrate streaming

Adaptive bitrate streaming is a video delivery technique that adjusts the quality of a video stream in real-time according to detected bandwidth and CPU capacity. This enables videos to start quicker, with fewer buffering interruptions, and at the best possible quality for the current device and network connection, to maximize user experience. See adaptive bitrate streaming documentation for more on how to use this with Cloudinary.

See also: How to optimize image quality

How to optimize video format

As there are many different video formats out there, each one with different characteristics and compression capabilities, choosing the right format for each one of your videos can be a tough task.

Using the format parameter (f_ in URLs) you can explicitly choose the format you'd like the video to be delivered in (e.g f_webm) based on your requirements.

Automatic format selection (f_auto)

There are a lot of formats and codecs for encoding videos, with some formats better than others at compression and reducing the file size without impairing visual quality. Since different browsers support different video formats and codecs, the best solution to save bandwidth and optimize delivery time would be to deliver the best format according to the browser used by each of your visitors.

The fetch_format parameter can be set to auto (f_auto in URLs) in order to perform automatic format and codec selection based on the requesting browser. For example, with the automatic format feature, in most cases Chrome users would receive a VP9-encoded WebM file, while Safari users would receive an HEVC-encoded MP4 file. If a browser does not support either of these formats then the video is delivered as an H.264-encoded MP4 file (which is supported by almost every browser).

For example, the uploaded video named dog scaled down to a width of 500 pixels and delivered as WebM (VP9) to Chrome browsers (482 KB), an MP4 (HEVC) to Safari browsers (520 KB), or as an MP4 (H.264) to browsers that support neither format (821 KB):

Ruby:
Copy to clipboard
cl_video_tag("dog", :width=>500, :fetch_format=>:auto, :crop=>"scale")
PHP:
Copy to clipboard
cl_video_tag("dog", array("width"=>500, "fetch_format"=>"auto", "crop"=>"scale"))
Python:
Copy to clipboard
CloudinaryVideo("dog").video(width=500, fetch_format="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.video("dog", {width: 500, fetch_format: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).fetchFormat("auto").crop("scale")).videoTag("dog");
JS:
Copy to clipboard
cloudinary.videoTag('dog', {width: 500, fetchFormat: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.video("dog", {width: 500, fetch_format: "auto", crop: "scale"})
React:
Copy to clipboard
<Video publicId="dog" >
  <Transformation width="500" fetchFormat="auto" crop="scale" />
</Video>
Vue.js:
Copy to clipboard
<cld-video publicId="dog" >
  <cld-transformation width="500" fetchFormat="auto" crop="scale" />
</cld-video>
Angular:
Copy to clipboard
<cl-video public-id="dog" >
  <cl-transformation width="500" fetch-format="auto" crop="scale">
  </cl-transformation>
</cl-video>
.Net:
Copy to clipboard
cloudinary.Api.UrlVideoUp.Transform(new Transformation().Width(500).FetchFormat("auto").Crop("scale")).BuildVideoTag("dog")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).fetchFormat("auto").crop("scale")).resourceType("video").generate("dog.mp4");
iOS:
Copy to clipboard
cloudinary.createUrl().setResourceType("video").setTransformation(CLDTransformation().setWidth(500).setFetchFormat("auto").setCrop("scale")).generate("dog.mp4")

Notes

  • This feature is also available on mobile native applications as long as the specified formats are included in the Accept Header.
  • When using automatic format selection, a derived resource is created for each format that is delivered. This could impact your total transformation counts and storage usage. To ensure best performance, even for the first users requesting each format, you may want to create the derived resources for each format in advance; either upon upload (using eager transformations) or after upload (using the explicit method).

How to optimize video sizing

The most efficient way to minimize the file size of your delivered videos and improve their performance is to resize them so they'll fit your web or mobile app-specific design.

If it suits your use-case, you can also perform the resize before you save the video to your Cloudinary account using incoming transformations, this will help save on storage space.

For details on how to resize your videos, see resizing and cropping videos.

See also: How to optimize image sizing

✔️ Feedback sent!

Rate this page: