How to Deliver a Smooth Playback without Interruptions (Buffering)

By  on  
Cloudinary

There's only one thing worse than no internet:  unreliable internet.  The frustration I feel when one page loads quickly, then the next very slow (if at all), and then a mixture is unmanageable.  Like...throw your device across the room frustrating.  This slowness is most apparent when trying to play media, more specifically video where it's visually janky and the sound is getting cut off and you're seething with fury.

Last week I wrote about HTML5 Video Best Practices and the awesome utilities provided by Cloudinary to place optimized and configurable videos within your site.  Cloudinary lets you customize the video poster, video controls, and even apply filters and transformations to the video itself.  Taking a deeper look, you can even control the bitrate and codecs levels, allowing for better customization of video delivery.

Uploading a Video

You can upload a video within the Cloudinary website but let's have some fun and use the Cloudinary Node.js API to upload a video:

cloudinary.uploader.upload('sample-video.mp4', function(result) {
  // Callback
  console.log('result: ', result);
}, {
  public_id: 'sample-video',
  resource_type: 'video'
});

Cloudinary provides PHP, Python, and a host of other API libraries.  Once  the video is uploaded, you can call the following method to retrieve the video's optimal HTML string:

cloudinary.video('sample-video');

/*
<video poster='http://res.cloudinary.com/david-wash-blog/video/upload/sample-video.jpg'>
    <source src='http://res.cloudinary.com/david-wash-blog/video/upload/sample-video.webm' type='video/webm'>
    <source src='http://res.cloudinary.com/david-wash-blog/video/upload/sample-video.mp4' type='video/mp4'>
    <source src='http://res.cloudinary.com/david-wash-blog/video/upload/sample-video.ogv' type='video/ogg'>
</video>
*/

Manipulating Video Quality & Bit Rate

Depending on the device, browser, traffic load, length of video, or a range of other variables, you may want to be able to modify the quality or bit rate of a video on your site.  Though quality and bit rate are two separate manipulations, remember that the higher the bit rate, the higher the quality.

Let's first set a desired quality:

cloudinary.video('sample-video', { quality: 50 });

Setting desired bit rate is just as easy:

cloudinary.video('sample-video', { bit_rate: '250k' });

The API is so easy to use, no surprises!

Adaptive Bitrate Streaming - HLS and MPEG

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.

Cloudinary can automatically generate and deliver all of these files from a single original video, transcoded to either or both of the following protocols:

  • HTTP Live Streaming (HLS)
  • Dynamic Adaptive Streaming over HTTP (MPEG-DASH)

Setting up streaming is a multistep (but easy) process -- let's have a look at how to make that happen!

Step One:  Select a Streaming Profile

Cloudinary provides a collection of predefined streaming profiles, where each profile defines a set of representations according to suggested best practices.

For example, the 4k profile creates 8 different representations in 16*9 aspect ratio, from extremely high quality to audio only, while the sd profile creates only 3 representations, all in 4:3 aspect ratio. Other commonly used profiles include thehd and full_hd profiles.

To view the full list of available predefined streaming profiles and the settings for each representation, see Predefined streaming profiles.

Step Two:  Upload Your Video with an Eager Transformation Including the Streaming Profile and Format

A single streaming profile is comprised of many derived files, so it can take a while for Cloudinary to generate them all. Therefore, when you upload your video (or later, explicitly), you should include eager, asynchronous transformations with the required streaming profile and video format.

You can even eagerly prepare your videos for streaming in both formats and you can include other video transformations as well. However, make sure the streaming_profile is provided as a separate component of chained transformations.

For example, this upload command encodes the big_buck_bunny.mp4 video to HLS format using the full_hdstreaming profile:

cloudinary.uploader.upload("big_buck_bunny.mp4", 
        function(result) {console.log(result); }, 
        { resource_type: "video", 
        eager: [
            { streaming_profile: "full_hd", format: "m3u8" }],                                   
        eager_async: true,
        eager_notification_url: "http://mysite/notify_endpoint",
        public_id: "bb_bunny"});

Step Three:  Video Delivery

After the eager transformation is complete, deliver your video using the .m3u8 (HLS) or .mpd (MPEG-DASH) file format (extension) and include the streaming_profile (sp_<profilename>) and other transformations exactly matching those you provided in your eager transformation (as per the URL that was returned in the upload response).

cloudinary.video("bb_bunny.m3u8", {streaming_profile: "hd"})

Being able to change bit rate and quality on the fly is an awesome capability.  Sure, you could use your own utilities to generate files at various bit rates and qualities but that seems like a waste of time and energy when Cloudinary makes it so easy.  And when you can stream via Cloudinary as well?  What a bonus. When you add the ability to optimize and transform imagery, generate waveform images, remove photo backgrounds, tag images, and automate image updates,  using Cloudinary is an easy decision for multi-purpose media management!

Recent Features

  • By
    fetch API

    One of the worst kept secrets about AJAX on the web is that the underlying API for it, XMLHttpRequest, wasn't really made for what we've been using it for.  We've done well to create elegant APIs around XHR but we know we can do better.  Our effort to...

  • By
    CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

Incredible Demos

  • By
    Create a Dynamic Table of Contents Using MooTools 1.2

    You've probably noticed that I shy away from writing really long articles. Here are a few reasons why: Most site visitors are coming from Google and just want a straight to the point, bail-me-out ASAP answer to a question. I've noticed that I have a hard time...

  • By
    CSS Animations Between Media Queries

    CSS animations are right up there with sliced bread. CSS animations are efficient because they can be hardware accelerated, they require no JavaScript overhead, and they are composed of very little CSS code. Quite often we add CSS transforms to elements via CSS during...

Discussion

    Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!