1. Home
  2. Writings
  3. How To Deliver Video The Right Way

How to deliver video the right way

We all HATE buffering videos, this is how you solve it.

Imagine this, you work at an ad agency and you decide to take a short break and you walk down to the closest coffee place. Your client joins you as you guys both need some fresh air. During the short trip to the coffee place you remember a video that captures the inspiration you need for a project you are working on. Based on the title of this post you probably know what is going to happed right? Buffering… This is a shitty moment for a video to either not load or buffer every two seconds.

At this day and age this should no longer be an issue. Even when we do have more time to spare than walking to a coffee place with a client, we get annoyed while waiting for any video that buffers. The content of a video is of no consequence if the delivery is not good enough to keep a user’s attention until the end.

Another excellent example is watching the Game Of thrones final episode using the local streaming provider here in Paris. The stream was janky and it buffered all the time. Most people I spoke to about this turned off the stream and pirated the episode instead. Not me though, I’m a good boy and I soldiered on.

If you are anything like me you have been silently talking to your device while reading this: “Dude, just use adaptive streaming”. You are right. Adaptive video streaming is the solution for all these problems. Maybe not so much for the Game Of Thrones issue, these guys just need to scale their servers more efficiently.

Adaptive streaming is a video delivery technique that adjusts the quality of a video stream in real time according to detected bandwidth and CPU capacity of a user.

HLS and MPEG-DASH are the two most popular formats for adaptive streaming. Adaptive video delivery requires outputting a video in different quality settings along with some additional files. Both HLS and MPEG-DASH have different approaches to the problem. The process of making all this work is tedious and complex. Most services out there do not provide an end-to-end solution for this and the ones that do a are quite costly. The adaptive video streaming paradigm is not one that many websites have conquered as it requires knowledge and hardware. Not everybody has brains and recourses like Netflix or YouTube.

First we’ll go into how adaptive streaming works and then I’ll explain exactly how to do this yourself. It’s much easier than you think once you have the knowledge and the right SaaS to do the heavy lifting.

How adaptive video delivery works

The name says it all. The stream adapts itself based on a set of rules like the user’s bandwidth, CPU load and resolution. To be able to stream adaptively you need to be able to actually stream different versions of your video. Each video variant is of different quality, has a different bitrate and potentially has a different codec or resolution. Think of it as progressive enhancement in web development.

Each video file is also joined by an index file that specifies predefined segments of the video. According to HLS these segments are usually 10 seconds long. Additionally, there is a master playlist that points to the available representations with additional information about each one. It’s pretty cool that this technology just took the spec from the M3U8 audio playlist implementation. M3U8 was originally designed for audio files, such as MP3, but nowadays it is commonly used to point media players to audio and video sources.

Dynamic Video Streaming
Dynamic Video Streaming

An adaptive streaming video player uses the playlist information to decide which of the available video variations fits the user’s network conditions, CPU load or resolution best. It can switch to another source at each 10 second segment if the network conditions change.

A bit more about HLS and MPEG-DASH

HLS

HLS was originally created by Apple to provide video for its iPhone, but now it’s a common format used across HTML5 web applications. You’ll need to encode your video with H.264 or HEVC/H.265 codecs, which can be decoded by any major browser. With HLS, the video is chopped up into 10 second intervals and sent to the user.

MPEG-DASH

MPEG-DASH is the latest HLS competitor. It was originally created to be an alternative to HLS. It has a few advantages over HLS, mainly because it is open-source, which means the media content publisher community as a whole can contribute to its changes and updates. MPEG-DASH is globally supported and codec agnostic, which means that you can encode video without worrying about codec support. It has lower latency than HLS and it supports ads.

Do it yourself

As said earlier, to deliver videos using adaptive streaming you must generate multiple video versions, add an index file per variant and add a master playlist. The formats and encoding for HLS and MPEG-DASH are different for each of these files. If you want to stream using both HLS and MPEG-DASH formats you need to double the effort for every video you want to deliver. Additionally, for MPEG-DASH, the best practice is to deliver the audio and video separately. This stuff is complex and time consuming.

As a developer it might be an interesting adventure to dust of your FFMPEG skills and create all sources yourself and make it into a fun project but for the rest of us that have to deal with scale and non-technical end users this is not an option.

Enter: Cloudinary.

Next to delivering top of the line image management Cloudinary has now also jumped on the video bandwagon and they provide a shitload of amazing features for videos.

Cloudinary created smart pre-defined streaming profiles to help you out. A streaming profile holds a set of video variation definitions with different qualities, bitrates, and codecs. For example, the one profile specifies 10 different variations ranging from extremely high quality to audio-only. You can also create custom profiles through their API.

Once you have selected a profile, you upload your video file with an eager transformation that instructs the system to generate all the required files for the requested profile in either HLS or MPEG-DASH format. If you want to deliver both formats, add two eager transformations within your upload command. Learn more about streaming profiles here.

cloudinary.v2.uploader.upload(
  'awesome.mp4',
  {
    resource_type: 'video',
    eager: [
      { format: 'm3u8', streaming_profile: 'for_in_the_metro' },
      { format: 'mpd', streaming_profile: 'for_in_the_metro' }
    ],
    eager_async: true,
    eager_notification_url: 'https://timbenniks.nl/notify',
    public_id: 'awesome'
  },
  result => console.log(result)
)

This is what the resulting stream profile going to the player looks like this:

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=558000,CODECS="avc1.66.30,mp4a.40.2",RESOLUTION=640x360
/cloudinary/video/upload/br_2m,c_limit,h_360,vc_h264:baseline:3.0,w_640/awesome.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=494000,CODECS="avc1.4d001f,mp4a.40.2",RESOLUTION=640x360
/cloudinary/video/upload/br_5500k,c_limit,h_720,vc_h264:main:3.1,w_1280/awesome.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=494000,CODECS="avc1.4d001f,mp4a.40.2",RESOLUTION=640x360
/cloudinary/video/upload/br_3500k,c_limit,h_540,vc_h264:main:3.1,w_960/awesome.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=333000,CODECS="avc1.66.30,mp4a.40.2",RESOLUTION=480x270
/cloudinary/video/upload/br_800k,c_limit,h_270,vc_h264:baseline:3.0,w_480/awesome.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=219000,CODECS="mp4a.40.2",RESOLUTION=320x180
/cloudinary/video/upload/br_192k,c_limit,h_240,w_320/awesome.m3u8

Now that you have all this in place, you just need a video player that can actually deal with HLS or MPEG-DASH. There are a couple of them out there. Cloudinary has also created one that is quite feature rich.

Somewhere in the near future I’ll talk about how you can manipulate video for responsive behavior so you only need one video file for all screen sizes and fancy effects.

For now: have fun with adaptive video streaming!