Cloudinary Blog

Get More Out of HTML5 Video Tags with Cloud-Based Video Transcoding

Get More Out of HTML5 Video Tags with Cloud-Based Video Transcoding

Once upon a time, in long forgotten browser versions, getting a video into a website required creating and embedding Flash resources. But these days, all modern browsers support HTML5, including the HTML5 video tag, which means you’ve got a built-in video player that anyone can use.

At first glance, the default HTML5 video player may not look like a fairy tale come true, but the built-in functionality packs more value than you might think. Even if you need more than what the HTML5 video tag gives you out-of-the box, you can always use a bit of CSS and Javascript to build on top of the HTML5 video tag to enhance and customize it to your heart’s content.

To complement the options available with the HTML5 video tag, Cloudinary offers a set of video transcoding and transformation capabilities, with all processing done in the cloud. The resulting output can be delivered on-the-fly, or you can prepare your video transformations eagerly beforehand, to ensure fast delivery even to the first user.

When you use the HTML5 video player together with Cloudinary’s video functionality, you’ll see that you can do some pretty cool things with very minimal code or time investment.

Delivering Compelling Video Experiences at Scale

What’s in an HTML5 video tag?

Many websites embed proprietary video players with a variety of bells and whistles, but in many cases, the basic HTML5 video tag provides everything you need to deliver videos as part of your website content. For example, completely whistle-free HTML5 video player code, enables you to:

  • Specify the width and height of the player.
  • Display or hide the HTML5 video controls, including play/pause, volume, full-screen toggle, and seek slider.
  • Set a poster image to display while the video is downloading or not playing.
  • Provide a set of videos in different formats, so that each browser can play a format it supports.
  • Include closed-caption subtitles or captions in multiple languages (great for SEO!).
  • Tell the browser whether to start downloading the video when the page loads or only when the user presses Play.
  • Control whether to automatically play the video as soon as it’s ready.
  • Decide whether to play once or in a loop.
  • Indicate if you’d like to play the video without sound (muted). For example, Facebook does this when it autoplays videos.

The following simple HTML renders a 640x480 video player with video controls. Each browser will select the video file with the most appropriate format for it (webm, mp4, or ogv). Because subtitle tracks were provided, the HTML5 video controls include a closed-captioning list of languages.

Copy to clipboard
<video width="640" height="480" poster="CloudinaryTales.jpg" controls>
 <source src="CloudinaryTales.webm" type="video/webm">
 <source src="CloudinaryTales.ogv" type="video/ogg">
 <source src="CloudinaryTales.mp4" type="video/mp4">
 <track src="subtitles-en.vtt" kind="subtitles" srclang="en" 
        label="English" default>
 <track src="subtitles-fr.vtt" kind="subtitles" srclang="fr"

You can find more details about the HTML5 video tag on the w3schools website.

Transforming and transcoding to a glass slipper fit

So now you know how easy it is to fit an HTML5 video player into your Web page.

But what about preparing and optimizing your video content fit your player?

What good is a glass slipper, if Cinderella’s foot doesn’t fit?

In other words, if your videos, or the videos your users upload, are the wrong format or wrong size for your site’s art design, if they are too heavy or too long to download, or they otherwise fail to deliver the impact needed to capture the attention of your users and keep them watching, then that convenient HTML5 video player just isn’t enough.

Formats, formats, formats

To start with, the video that you or your users want to upload, might not even be a standard Web format. Even if it is, you should have your movies available in WebM, Ogg (aka Theora), and MP4 formats, to ensure that the optimal format is delivered for each browser.

Cloudinary enables you to easily transcode your videos from a long list of possible video input formats (including non-Web formats) to all the three of the formats mentioned above. The transcoding is performed on the cloud, with no need to install any video processing software. You can transcode and deliver on-the-fly, or eagerly during the upload process.  All you need to do to transcode a video to a single format on-the-fly, is to deliver it with the new format as the extension type. For example:

The easiest way to transcode to multiple formats is  to use the cl_video_tag SDK method in your code. For example, this tiny line of code:

Copy to clipboard
Copy to clipboard
Copy to clipboard
Copy to clipboard"dog")
Copy to clipboard
Copy to clipboard

automatically generates an entire <video> HTML snippet, including automatically generating the <source> URLs for transcoding to all three formats.  And it always puts the WebM format first, since that format generally produces smaller formats, so that browsers that support it, will always deliver the smaller format.

More details about this tag below.

When you transcode video on-the-fly, the conversion may take some time the first time a user accesses it, but all subsequent requests to the same URL are delivered quickly via the CDN cache. To avoid the lag time even for your first viewer, use eager transformations to prepare your content as part of the upload process.

Optimize your HTML5 video for quick delivery

Many videos are recorded at very high quality. And especially if your site includes user-generated video content where the original quality is outside your control, it’s important to make sure you will be able to deliver those videos at an acceptable size and speed.

Delivering in the right file format and via CDN, as described in the previous section, already goes a long way towards improving delivery times. Furthermore, when Cloudinary transcodes or transforms any video, it also automatically optimizes the video for optimal Web viewing, using best practices for quality, bitrate, codecs, and more.

But, if you still want to cut the file size of the delivered video, there are lots of other steps you can take.

To control the physical size of videos uploaded to your site, you can use resize or crop the video  as an eager transformation to ensure that the videos your users upload will not exceed a maximum physical size.

For example, even if users watch your videos in full screen size, a 1280X720 frame size is generally plenty for most purposes. So, you can limit videos to this maximum size with an upload command such as the following:

Copy to clipboard
Cloudinary::Uploader.upload("my_video.mp4",:resource_type => :video,
  :eager =>   { :width => 1280, :height => 720, :crop => :scale })

You can also take advantage of eager cropping transformations to resize videos if users upload videos with aspect ratios different than that of the video player you want to include.

When relevant, you can limit the video length by trimming long videos to a certain duration of time, using the duration parameter.

In some cases, adjusting the quality and bitrate settings can also decrease file size without having a significant impact on the visually perceived quality. For example:

Changing the quality of an uploaded 9.8 MB mp4 video to 50, or changing the bitrate to 500 kilobits reduced the file size of this video to around 1 MB.

For videos that you are delivering in their original format, and with no other custom transformations, you can set the video_codec to auto, to normalize and optimize the video for web, including the audio settings.  
Alternatively, you can manually select the video_codec settings.

Capturing your audience

It’s often the little things that make the difference. You want to make sure you grab your audience’s attention and get them to press that play button.  And of-course you want them to keep watching after they start.

Grand opening

The HTML5 video player supports displaying an initial poster image, to hint to users what the video’s all about while it’s downloading or before they play it, but where does that image come from?

An easy way is to have Cloudinary automatically generate an image from a frame in your video. By default, it takes the middle frame, but you can select any other frame by specifying an offset time.   You can also select any other image in your Cloudinary image library to act as your opening poster image.

Whatever image you choose, you can apply any image transformations you want; you can zoom in, add special effects or artistic filters, overlays, and much more.

For example, for the poster image below, we use second 0:36 of this cool Edinburgh time lapse video by Betsy Weber, and we overlay a transparent movie curtain .png file along with some text.

Copy to clipboard
:poster => { :transformation => 
    [ { :width => 1850, :crop => "scale" },
      { :overlay=>"movie_curtain_overlay_new"},
      { :overlay=>"text:Courier_80_bold:Once%20upon%20a%20time...", 
         :gravity=>"north", :y=>60 },
      { :start_offset=>36 } ] }

Poster image for HTML5 video player

Thickening the plot

That opening image is just the start of the fun. There are many things you can do with the video itself, depending on your video’s purpose and audience. Here are just a few examples of what’s possible, with a single line of code:

  • Apply improvement effects to your video to adjust contrast or saturation.
  • Add fade in and fade out effects.
  • Display the video with rounded corners, or even as a circle or oval. Or show the video with a vignette effect.
  • Add overlays at specified times and locations. For example, you could add callouts to a video demonstration without the need to edit the original video.
  • Overlay video on video, such as a sign-language interpreter or a narrator for a demo.
  • Rotate a video; not only 90 degrees to allow for portrait videos, but to any angle you please.
  • Concatenate two videos, for example to include an advertisement at the start.
  • Accelerate or decelerate the play speed.

If you are accepting video uploads from users, you may want to consider defining the transformations in an upload preset, making it easier to apply your selected effects to all incoming videos.

Or you might want to allow your users to select from a list of effects, and you can apply the selected options as eager transformations, upon upload.

All for one and one for all

We’ve described a lot of things you can do with your video using Cloudinary upload and transformation functionality, and we’ve shown you how you can then play your masterpiece in the built-in video player, using the HTML5 video tag.

We already hinted earlier about the cl_video_tag SDK helper method, which you can use to  automatically generate a <video> HTML snippet. So let’s show you how it’s done, and how you can actually include almost everything we’ve talked about so far, inside a single cl_video_tag.

The cl_video_tag is can be used in all supported SDK frameworks (Ruby, PHP, Javascript, Python, Node.js, .NET, and more). The basic syntax (shown here in Ruby) is:

Copy to clipboard
cl_video_tag(public_id, options = {})

Where the public_id is the name of a video that has been uploaded to your Cloudinary account, and the options include a bunch of optional settings, such as:

  • Formats to include for the <video> sources (default webm, mp4 and ogv).
  • A poster image (default = middle frame), and any transformations to apply on that image.
  • Any transformations you want to apply to the transformed video.
  • fallback text content for (ancient) browsers that don’t support any of the output source formats.
  • any attribute of the HTML5 video tag (to customize those player options we mentioned earlier in this article).

As we mentioned previously, the cl_video_tag method call can look as simple as this:

Copy to clipboard
Copy to clipboard
Copy to clipboard
Copy to clipboard"castle_timelapse")
Copy to clipboard
Copy to clipboard

That one little line of code, applying default values, generates this:

Copy to clipboard

But as you saw from the list of options above, you can really go all out with this tag.

In the following example:

  • We use the custom poster image we talked about earlier in this post, for a theatrical opening.
  • We set our timelapse video to loop, for those who want to enjoy more than one sunrise and sunset.
  • We crop the video to 640x480 (4:3 aspect ratio) using the pad method, so that one size video player can host videos uploaded in both 4:3 and 16:9 ratios.
  • We lower the quality to 70, which decreases the file size from 17.5 MB to 8.2 MB.
  • We shorten the duration of the video to 60 seconds, resulting in a 2.9 MB file.
  • We add a fade-in effect.
  • We add a little princess overlay to our castle video for some extra cuteness points.
  • And of-course by default, we still get the video player controls and video output in all three formats.
Copy to clipboard
  :loop => true, 
  :poster => { :transformation => 
    [ { :width => 1850, :crop => "scale" },
      { :overlay=>"movie_curtain_overlay_new"},
      { :overlay=>"text:Courier_80_bold:Once%20upon%20a%20time...", 
         :gravity=>"north", :y=>60 },
      { :start_offset=>36 } ] },
  :transformation => [  
    { :crop=>"pad", :height=>480, :width=>640, :quality=>70, 
       :duration=>"60", :effect=>"fade:4000" },  
    { :overlay=>"princess_small", :height=>100, :start_offset=>"0.5", 
      :gravity=>"west", :y=>80}  

Here’s the <video> tag it generates:

Copy to clipboard
<video controls="controls" height="360" loop poster=",w_1850/l_movie_curtain_overlay_new/l_text:Courier_80_bold:Once%20upon%20a%20time...,g_north,y_60/so_36/castle_timelapse.jpg" preload="none" style="margin: 0 auto;display: block" width="640">

  <source src=",h_480,w_640,q_70,du_60,e_fade:4000/l_princess_small,h_100,so_0.5,g_west,y_80/castle_timelapse.webm" type="video/webm" />

 <source src=",h_480,w_640,q_70,du_60,e_fade:4000/l_princess_small,h_100,so_0.5,g_west,y_80/castle_timelapse.mp4" type="video/mp4" />

  <source src=",h_480,w_640,q_70,du_60,e_fade:4000/l_princess_small,h_100,so_0.5,g_west,y_80/castle_timelapse.ogv" type="video/ogg" />


And here’s the final video. Grab the popcorn!

Adding a few more magic touches to your Video Player

While every modern browser provides a media player for the HTML5 video tag with the main features we talked about above, each browser’s player looks a bit different. If you want to ensure a consistent look and feel of your browser, or if you want to add extra controls and other fancy stuff, you can do it with a bit (or a lot, depending on how adventurous you are) of CSS and Javascript on top of the built-in HTML5 video tag.

We won’t go into the details of that here, but it’s not hard to find more information on this subject.

For example, here’s one article series that walks you through the steps of building your own comprehensive YouTube application (or YourTube as this in-depth tutorial aptly calls it).

The moral of the story...

As we’ve seen, embedding a video in your website these days is as simple as adding a HTML5 video tag to your HTML page.

And outputting video that can run in all browsers, download quickly, and keep your audience watching, is as simple as a Cloudinary dynamic URL with transcoding, resizing, and manipulation parameters to make the video fit your design and your users..

Furthermore, you can generate the HTML code and the video transformation code at once, using the cl_video_tag SDK helper method.

And so, the HTML5 <video> tag and the Cloudinary cl_video_tag went off into the sunset, hand-in-hand as the perfect couple.  And they lived happily ever after.

OK, OK, that’s a bit sappy. But I think you get the idea.

You can do everything described in this post by subscribing to any of Cloudinary’s plans, including the free plan.

Cloudinary now offers a HTML5 Video Player

Want to learn more about HTML5 Video Players?

Recent Blog Posts

Maya Shavin: How I Built My Website

Besides working as a senior front-end developer at Cloudinary, I'm also a content creator, a blogger, and an open-source developer. Follow me at @mayashavin and on

In the beginning, my website,, was mainly for showcasing the status of my development projects and keeping me organized with my speaking schedule. Initially, I built it with Vue.js, later on switching to Nuxt.js (aka Nuxt) for a higher SEO score, and deployed it with Netlify. After some time, I added a blog section with Netlify CMS as the content management system (CMS). Everything was fine until I added more content and features, which led to a significant decline in the site’s performance. Also, the site design needed a modern look. So, I gave the site a makeover.

Read more
Automation Frees Up PetRescue’s Staff to Help Pets Find Their Forever Homes

As we spend more time at home, many of us are adopting pets for the joy, companionship and a surprising range of health benefits. In Australia, where our nonprofit customer PetRescue is located, there’s a shortage of pets to adopt. Last August, the Guardian reported that dog shelters in Australia emptied and adoption fees for puppies were running as high as $AUS1800.

Read more
Cloudinary and Contentful Make Modern Content Management Easier

I am pleased to share that Cloudinary and Contentful have joined forces to further streamline the creation, processing, and delivery of online content through Cloudinary’s digital asset management (DAM) solution and advanced transformation and delivery capabilities for images and video. What’s more, the partnership delivers a headless approach to DAM. By leveraging APIs for media management tasks, marketers and developers alike benefit from an integrated stack of optimized assets for optimization and automation. As a result, page loads are fast and beautiful, and at scale—with less overhead and effort.

Read more
Introducing Cloudinary's Nuxt Module

Since its initial release in October 2016 by the Chopin brothers as a server-side framework that runs on top of Vue.js, Nuxt (aka Nuxt.js) has gained prominence in both intuitiveness and performance. The framework offers numerous built-in features based on a modular architecture, bringing ease and simplicity to web development. Not surprisingly, Nuxt.js has seen remarkable growth in adoption by the developer community along with accolades galore. At this writing, Nuxt has earned over 30K stars on GitHub and 96 active modules with over a million downloads per month. And the upward trend is ongoing.

Read more
How Quality and Quantity can go Hand in Hand

When it comes to quality versus quantity, you’ll often hear people say, “It’s the quality that counts, not the quantity”. While that’s true in many situations, there are also cases where you want both quality and quantity. You may have thousands of images on your website and you want them all to look great. This is especially important if your website allows users to upload their own content, for example, to sell their own products or services. You don't want their poor quality images to reflect badly on your brand.

Read more