JAVASCRIPT

How to build your own Youtube – Part 9


Introduction: If you missed the earlier parts, in this series we are covering how to build your own YouTube clone, Click here.

Note: You need to have at least some prior experience with client-side Javascript frameworks  and Node.js to get the most out of this tutorial.

In the previous post, we looked at Audio Frequency Control, Video Effects such as Adding Visual Noise, Removing small motion shifts, Fading in and out, Calibrating contrast, Controlling brightness, Balancing Saturation, Regulating Gamma, Applying Vignette, Adjusting Volume.

In this post, we’ll look at Adaptive bitrate streaming – HLS and MPEG-DASH, creating  mpd and streaming files with various transformations, creating an mpd master playlist file, creating animated GIFs and webP files and delivering  animated GIFs and webP files.

Adaptive bitrate streaming – HLS and MPEG-DASH

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.

For example, as a video begins to download, the client can play the first few seconds of the movie at a low quality to get started quickly. When the user’s video buffer is full and assuming CPU utilization is low, the client player may switch to a higher quality stream to enhance the viewing experience. If the buffer later drops below certain levels, or CPU utilization jumps above certain thresholds, the client may switch to a lower quality stream.

At the start of the streaming session, the client software downloads a master playlist file containing the metadata for the various sub-streams that are available. The client software then decides what to download from the available media files, based on predefined factors such as device type, resolution, current bandwidth, size, etc.

To deliver videos using adaptive streaming, you need multiple copies of your video prepared at different resolutions, qualities, and data rates. These are called video representations (also sometimes known as variants). You also need index and streaming files for each representation. The master file references the available representations, provides information required for the client to choose between them, and includes other required metadata, depending on the delivery protocol.

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

  1. HTTP Live Streaming (HLS)
  2. Dynamic Adaptive Streaming over HTTP (MPEG-DASH)

To deliver videos using HLS or MPEG-DASH Adaptive Streaming:

  1. Select a predefined streaming profile
  2. Upload your video with an eager transformation including the selected streaming profile and format
  3. Deliver the video

Note: If you have a special use-case that does not enable you to use the built-in streaming profiles to automatically generate the master playlist file and all the relevant representations, you can still have Cloudinary create the index and streaming files for each streaming transformation (representation) that you define, and then you can create the master playlist file manually. For details, see Manually creating representations and master files

Step 1: 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 the hd 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 2: Upload 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 below encodes the big_buck_bunny.mp4 video to HLS format using the full_hd streaming profile like so:

Using Cloudinary Node.js library

You can also request several encodings and formats at once like so:

You can encode an already uploaded video using:

Step 3: Deliver the Video

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).

For example, the delivery code for the video that was uploaded in Step 2 above is:

Note: Not all browsers and mobile devices natively support MPEG-DASH and HLS. For example, DASH is natively supported in Chrome (including Android 4.0+), Internet Explorer 11 on Windows 8.1, and many SmartTVs. HLS is supported on all Apple devices, Safari, and the latest versions of the Android browser and Chrome.

To ensure that your encoded video can stream in all environments, make sure to embed relevant client players in your application. (There are a number of open source and closed source solutions available.)

Guidelines for Adaptive Streaming

  • For small videos, where all of the derived files combined are less than 60 MB, you can deliver the transformation URL on-the-fly (instead of as an eager transformation), but this should be used only for demo or debugging purposes. In a production environment, it’s recommend to always eagerly transform your video representations.
  • The adaptive streaming files for small videos (where all of the derived files combined are less than 60 MB) are derived synchronously if you do not set the asynch parameter. Larger videos are prepared asynchronously. Notification (webhook) of completion is sent to the eager_notification_url parameter.
  • By default, video sampling is per 2 seconds. You can define a custom sampling rate by specifying it as a chained transformation prior to the streaming profile. For example (in Ruby):

  • All the generated files are considered derived files of the original video. For example, when performing invalidate on a video, the corresponding derived adaptive streaming files are also invalidated.
  • If the profile you select includes any representations larger resolution than the original, those representations will not be created. However, at minimum, one representation will be created.
  • If the aspect ratio of the original video does not match the aspect ratio of the selected video, then the c_lpad cropping transformation is applied to make the video fit the required size. If you don’t want to use this cropping method, use a base transformation to crop the video to the relevant aspect ratio.
  • If you prepare streaming for a lower-level profile, and then in the future, you want to prepare the same video with a higher-level profile, the new high-quality representations will be created, while any already existing representations that match will be reused.

Creating representations and master files manually

If you have a special use-case that does not enable you to use the built-in streaming profiles to automatically generate master playlist file and all the relevant representations, you can still have Cloudinary create the index and streaming files for each streaming transformation you define, and then you can create the master playlist file manually.

Step 1: Upload your video with eager transformations for each desired representation

When you upload your video, provide eager transformations for each representation (resolution, quality, data rate) that you want to create. Also make sure to define the format for each transformation as .m3u8 (HLS) or .mpd (DASH) in a separate component of the chain.

When you define the format of your transformation as .m3u8 or .mpd, Cloudinary automatically generates the following derived files:

  • A fragmented video streaming file (.ts1 or .mp4dv)
  • An index file (.m3u8 or .mpd) of references to the fragments
  • For DASH only: an audio stream file (.mp4da)

Using Node.js

Note: It is possible to create adaptive streaming transformations on the fly, but recommended to you create all the required transformations eagerly when uploading the original video file or explicitly, so that there is no delay when first accessed by your users.

Step 2: Manually create the master playlist file

If you are not using streaming profiles, you need to create your master playlist file manually.

HLS Master Playlist (m3u8)

Each item in the m3u8 master index file points to a Cloudinary dynamic manipulation URL, which represents the pair of auto-generated m3u8 index and ts video files that were created in the preceding step.

For example, the following m3u8 master playlist file contains information on 2 versions of the dog.mp4 video, one high resolution suitable for iPhone 4s and the other lower resolution suitable for iPhone 1s:

MPEG-DASH Master Playlist

The .mpd master file is an XML document. For details on creating the .mpd master file, see: The Structure of an MPEG-DASH MPD.

Creating animated GIF and animated WebP

Animated gifs are very popular. Most times, they are needed for illustrations and demo purposes. There are tools out there that can be used to create animated GIFs and WebP. Cloudinary provides the ability to create animated GIFs from your videos.

A perfect scenario would be you building a software that can create animated GIFs and WebPs using Cloudinary as your backend processing suite! Don’t worry, we won’t tell your boss you’re using Cloudinary :smile:

Cloudinary supports 2 formats for delivering your videos as animated images: GIF and WebP. There are a quite a few advantages to using the WebP format including:

  • WebP supports 24-bit RGB color with an 8-bit alpha channel, compared to GIF’s 8-bit color and 1-bit alpha.
  • WebP supports both lossy and lossless compression (a single animation can combine lossy and lossless frames), well-suited to animated images created from real-world videos. GIF only supports lossless compression.
  • WebP requires fewer bytes than GIF, ranging from 64% smaller for Animated GIF converted to lossy WebP, to 19% smaller for lossless WebP.

The disadvantage is that whereas animated GIFs are universally supported, WebP is only supported by the Chrome and Opera web browsers.

Delivering Animated GIFs

Delivering an animated GIF that is generated from an uploaded video is as simple as changing the file extension of the URL to .gif. Yes, it’s that simple!!! :smile:

Video

Simply changed the extension to .gif and here we have this below:

http://res.cloudinary.com/unicodeveloper/video/upload/v1467870012/p6nzh9ver40gymlboskb.gif

animated gif

Converting a video to animated GIF is normally done while resizing and cropping to match your site (usually scaling down). By default, the resulting animated GIF is generated from the whole video (up to 400 frames, at up to 10 frames per second) and is the same duration as the original video no matter how many frames are sampled. The resulting animated GIFs can also be further manipulated like any other image uploaded to Cloudinary.

To control which frames are taken from the original video and the speed that they are displayed, use the video_sampling and delay parameters.

The video_sampling parameter (vs in URLs) determines which frames to sample from the original video and can take one of the following values:

  • Integer – The total number of frames to sample from the original video. The frames are spread out over the length of the video, e.g. 25 samples one frame every 4%.
  • String – A float with an s appended representing the number of seconds between each frame to sample from the original video. e.g. 2.3s samples one frame every 2.3 seconds.

The delay parameter (dl in URLs) is used to set the time delay between the individual frames of the animated GIF, in milliseconds.

Examples of generating an animated GIF from the uploaded mp4 video named dog:

  1. Using a sample of 20 frames from the original video and setting a delay of 200 milliseconds between the frames of the resulting animated GIF, which is scaled down to a width of 300 pixels can be done like so:

where vs_25 refers to the video_sampling parameter, dl_200 refers to the delay parameter and w_300 refers to the width of the gif.

Using the Node.js library, it will look like so:

2. Sampling one frame every 1.1 seconds from the original video and setting a delay of 100 milliseconds between the frames of the resulting animated GIF, which is scaled down to a width of 200 pixels can be done like so:

here the vs was in seconds, video_sampling one frame every 1.1 seconds

Using the Node.js library it will look like so:

Delivering Animated WebP files

Delivering an animated WebP that is generated from an uploaded video is similar to generating an animated GIF as described above, except that you also need to enable the awebp and animated flags (fl_awebp and fl_animated in URLs).

For example, generating an animated WebP from the uploaded mp4 video named dog, using a sample of 10 frames from the original video and setting a delay of 100 milliseconds between the frames of the resulting animated WebP, which is also scaled down to a width of 250 pixels will be done like so:

Using the Node.js library, it will look like so:

Note that you can also create animated images from videos together with the auto format and the animated flag parameters (f_auto and fl_animated in URLs). Adding these parameters will deliver an animated WebP to browsers that support the format, and fall back to delivering an animated GIF to browsers that don’t support the format. See this blog post on animated WebP for more information.

For example, to deliver an animated WebP of the mp4 video named dog to supported browsers, but fall back to animated GIF for unsupported browsers:

Using the Node.js library, it will look like so:

Conclusion 

In this post, we have looked at Adaptive bitrate streaming – HLS and MPEG-DASH, creating  MPD and streaming files with various transformations, creating an MPD master playlist file, creating animated GIFs and webP files and delivering  animated GIFs and webP files.

In the next and final post, we’ll add the number of views and the ability for users to comment on Yourtube

The source code for this project is on GitHub.

If you have any questions or observations, please drop your thoughts in the comment section below :smile:

 

PROSPER OTEMUYIWA

About PROSPER OTEMUYIWA

Food Ninja, Code Slinger, Technical Trainer, Accidental Writer, Open Source Advocate and Developer Evangelist.