I recently read about DASH (Dynamic Adaptive Streaming over HTTP) and an implementation of this standard in a video player from google here. If you haven’t heard of DASH before, check out this intro video (until 1:31). So I made it my goal for one day to learn as much about it as possible. I came quite far and reached the goal I set myself for this one day. It turned out, that even though it’s widely used, there is little documentation for real beginners. This is one thing that I want to change with my posts.I will now try and explain how you can get a good start into the DASH-Environment. As there is so much to talk about, I had to split my small guide/tutorial/howto into two parts:
You can find a complete overview of the tutorial with all the resources and examples mentioned in the posts here: http://halcyon.ch/halcyon_dash/
#1 – Get started with DASH [LINK]
In this part of the tutorial, we take a closer look at what DASH is and how we work with it. We then will mainly set up the DASH environment. We also take a look on how to install MP4Box and x264. We then encode our first video to the DASH-Format and make it available as a stream.
#2 – Display a DASH stream (Shaka-Player) [LINK]
In the second part, we will take a closer look on how we can access these streams. We will do this with the dart.js and the Shaka-Player.
Summarized, the DASH standard gives the opportunity that the client can switch automatically between the representation of the video. So the client can easily switch between the codec and the language for example. This is as mentioned in the video above very important when you don’t have a stable data connection so. So the quality and the codec of the video can be dynamically changed by the client (the video player). For this to work you have to encode the content in different resolutions and bitrates.
The documentation gives the following examples for resolutions and bitrates:
- 1920×1080, 5.0 Mbit/s
- 1920×1080, 3.0 Mbit/s
- 1280×720, 2.0 Mbit/s
- 1280×720, 1.0 Mbit/s
- 854×480, 750 kbit/s
- 640×360, 350 kbit/s
To encode your content in these different resolutions and bitrate you can use DASHEncoder or x256 (ffmpeg). To make your content ready to stream, you then have to generate a DASH manifest and the actual segments. You could use the DASHEncoder for that as well, but I’m going to use MP4Box in this tutorial.
If you think, that you already heard of such a standard, you’re not wrong. Last year Apple announced that their approach for this problem is Apple HLS. This is already implemented in the modern web browsers like Chrome, Microsoft Edge or Safari.
The goal of this two-part tutorial will be different video players that handle our own DASH-Stream.
Create our own DASH-Stream with MP4Box
To create the DASH-Stream we mainly need these two things:
- Dash Manifest (the file in the red solid rectangle)
- Dash Files (the files in the green solid rectangle)
Another product from the progress will be the differently encoded videos (the file in the green dashed rectangle). To show you better on how this all works I created the following graphic. This might help to understand the following steps a bit more. (click on the image to get a better version)
First of all we have to install both x264 and MP4Box. If you have already done this (respect!) then you can skip the following steps.
Installing the MP4Box proved to be quite tricky. This is why I wrote another blog post on how to set it up on a Mac environment. You can find my step-by-step guide here: Compile and install GPAC/MP4Box on Mac. If you need some more information about how MP4Box works with DASH, you can visit the following documentation: https://gpac.wp.mines-telecom.fr/mp4box/dash/.
We use x264 (ffmpeg) to encode our original source video to the 264 file, which will help us to create the DASH files. I struggled quite a lot to install the right version of x264. Well, one that could handle MP4-files. So I ended up with building it from source via homebrew. If you haven’t installed homebrew yet, then do so now or find another possibility to install x264.
I used the following command to do the installation and it took quite some time to complete but it worked in the end:
brew install ffmpeg --build-from-source
After the installation has finished you can try the following to check if it worked:
encode source file with x264
We will use x264 to encode our original video. I uploaded the original video I used if you want to use it to do the following steps here: link (squirrel). With x264 we can set different resolutions and bitrates according to which video we want to create. But the output won’t be a video itself, it will be a .264 we then can use with the MP4Box to encode and segment for DASH. The command I used to create that .264 file is the following:
x264 --output intermediate_2400k.264 --fps 24 --preset slow --bitrate 2400 --vbv-maxrate 4800 --vbv-bufsize 9600 --min-keyint 48 --keyint 48 --scenecut 0 --no-scenecut --pass 1 --video-filter "resize:width=1280,height=720" squirrel_video.mp4
With this intermediate_2400k.264 file we now can go to the MP4Box. The output of the command with x264 should look something like this:
lavf [info]: 1920x1080p 0:1 @ 516000/17197 fps (cfr) resize [info]: resizing to 1280x720 x264 [info]: using SAR=1/1 x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2 x264 [info]: profile Main, level 3.1 x264 [info]: frame I:15 Avg QP:23.89 size:118965 x264 [info]: frame P:199 Avg QP:27.13 size: 25938 x264 [info]: frame B:474 Avg QP:32.46 size: 3769 x264 [info]: consecutive B-frames: 5.2% 3.5% 15.7% 75.6% x264 [info]: mb I I16..4: 1.6% 0.0% 98.4% x264 [info]: mb P I16..4: 1.7% 0.0% 0.0% P16..4: 85.1% 0.0% 0.0% 0.0% 0.0% skip:13.2% x264 [info]: mb B I16..4: 0.5% 0.0% 0.0% B16..8: 19.4% 0.0% 0.0% direct: 7.9% skip:72.2% L0:28.4% L1:49.6% BI:22.0% x264 [info]: final ratefactor: 24.80 x264 [info]: direct mvs spatial:98.7% temporal:1.3% x264 [info]: coded y,uvDC,uvAC intra: 88.4% 83.1% 53.0% inter: 16.5% 6.9% 0.0% x264 [info]: i16 v,h,dc,p: 29% 24% 33% 14% x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 18% 16% 9% 6% 14% 12% 11% 7% 7% x264 [info]: i8c dc,h,v,p: 46% 20% 23% 10% x264 [info]: Weighted P-Frames: Y:4.0% UV:0.0% x264 [info]: kb/s:2436.98 encoded 688 frames, 114.51 fps, 2436.98 kb/s
encode the video for DASH with MP4Box
We now first add our newly created intermediate_2400k.264 file to the MP4Box. Remember that we only converted the video so far. But you would add the audio stream here now too.
MP4Box -add intermediate_2400k.264 -fps 24 output_squirrel.mp4
When you execute the command it then creates a video which has got the settings from the intermediate_2400k.264 file. This video is now the base we use for the DASH-File. You can repeat this step with all the different resolutions and bitrates you want for your DASH-Stream.
Now we have to create the DASH manifest (MPD file) and the individual segment files. The DASH manifest keeps track of all the different resolutions and bitrates you have in your stream. It also contains a list of the segments to each of the different resolutions and bitrates. We can create that file and the segments in one go like that:
MP4Box -dash 4000 -frag 4000 -rap -segment-name segment_ output_squirrel.mp4
This is it. We now converted our video to the desired resolution and bitrate. Also, we have created the necessary manifest, which is needed for the stream itself. In your folder, you should have something like this:
In the next part of the tutorial, we will connect to the DASH-Stream with different video players.