Using nginx to build audio and video on demand service -- Based on DASH protocol

   in the previous paragraph, I studied the on-demand service under HLS protocol, which is the same as the nginx module used to build under DASH protocol introduced in this paper. You can refer to it Building an audio and video on demand server using nginx -- Based on HLS protocol 1.

1 DASH streaming media protocol

   the full name of DASH is Dynamic Adaptive Streaming Over HTTP, which is an adaptive bit rate streaming media technology. Similar to Apple's HTTP Live Streaming (HLS) technology, streaming media is played by dividing the content into small sequences of HTTP based file segments. MPEG (Moving Picture Experts Group) is an international standardization organization for audio and video compression. In order to find an alternative to HLS, MPEG-DASH standard is launched. As a streaming media transmission solution based on HTTP with adaptive bit rate, MPEG-DASH was published by ISO/IEC in 2012 and officially became an international standard.

Advantages of DASH:

  1. DASH is an international open standard defined by MPEG organization. It integrates various technologies in the industry and is supported by many companies, including Apple with HLS.
  2. Because of its openness, DASH has produced a series of open source software around it, which is conducive to the promotion of DASH technology.
  3. DASH does not specify a specific codec. It has nothing to do with the codec, that is, the content provider only needs to provide a video format without considering its compatibility.
  4. Like HLS, DASH is based on HTTP and does not need to consider the problem of firewall or proxy.
  5. DASH can easily support the switching of multi audio track, multi video track and multi caption track in playback.

At present, BiliBili, YouTube and other famous video websites using DASH protocol.

Disadvantages of DASH:

  1. Both DASH and HLS are streaming media operating in slicing mode, with a certain end-to-end delay (6~30s).
  2. At present, the market share of DASH protocol is not high, mainly the share of HLS. The support of each end for DASH depends on the integration of open source software, and the native support is not enough.

In fact, for the problem of high delay, DASH and HLS have developed their own low delay solutions. DASH protocol has DASH-LL and HLS protocol has LL-HLS2 And LHLS, which will not be discussed in this paper.

2. Build VOD service

2.1 nginx agent

   nginx is a proxy server. First, you need to build nginx service on Linux. Please refer to the specific process Installation process of nginx3 , the nginx VOD module will be used to build the VOD server. Add this module to nginx according to the installation process. The specific environment for building the VOD service is as follows:

System version: CentOS Linux release 7.9 2009(Core)
nginx version: 1.20.1
Nginx VOD module version: 1.29

2.2 nginx VOD module

  nginx VOD module is a third-party module that provides VOD (video on demand) services based on nginx. It supports the construction of on-demand services based on DASH, HDS, HLS and MSS.

Nginx VOD module download address:

During the installation and configuration of nginx, you need to use the -- add module = option to add a third-party module and compile it together. For relevant steps, please refer to the github website of the module:

github website of nginx VOD module:

The configuration parameters used when configuring nginx for compilation are as follows:

./configure --prefix=/web/webserver/nginx-vod-hls --with-http_stub_status_module --with-http_ssl_module --with-cc-opt='-O0 -gstabs+3' --with-debug --add-module=.../nginx-vod-module-1.29

After the configuration, compilation and installation are completed, you can use the keywords provided by the nginx VOD module in the nginx configuration file.

2.3 configure DASH on demand service under nginx

   local mode is used here. If you want to use mapped mode, you can refer to Using nginx to build audio and video on demand service -- Based on HLS protocol4 The mapped mode in is introduced. Here, it is assumed that the ip address of the machine deploying nginx service is

2.3.1 general configuration

In the configuration file of nginx, add the corresponding location configuration:

location /vod_dash {
    vod dash; # The protocol uses dash mode
    vod_mode local; # The access mode is specified as local mode

    vod_align_segments_to_key_frames on; # Each slice starts with a keyframe

    vod_dash_manifest_format segmenttemplate; # Using the format of fragment template in mpd manifest file
    vod_dash_profiles urn:mpeg:dash:profile:isoff-live:2011; # Specify the profile tag in the mpd manifest file

    ## DRM related configuration
    #vod_drm_enabled on;                         # Enable DRM
    #vod_drm_clear_lead_segment_count 0;         # Set all slices to be processed by DRM
    #vod_drm_upstream_location /php_proxy/;      # Specify DRM address
    #vod_drm_request_uri /dash_clear_key.php;    # Configure php address

    #Cross domain related configuration
    add_header Access-Control-Allow-Headers '*';
    add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range,Date';
    add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
    add_header Access-Control-Allow-Origin '*';

    alias /media;

## Configure the location pointing to the DRM server address
#location /php_proxy/ {
#    proxy_pass; #  The forwarding address points to the DRM server address
#    proxy_set_header Host $http_host;

After the conf file is modified, nginx needs reload to make the configuration effective.

./nginx -s reload

Another point that needs special attention here is that due to the DASH protocol, the playback address must be accessed using https to play normally.

Configure https service on nginx:
There are many redundant tutorials on the Internet.

Corresponding video file directory structure on the server:


URL playback address (https):

2.3.2 multi rate adaptive configuration

   multi bit rate adaptation refers to automatically judging the network state during video playback, playing high bit rate video when the network state is good, and playing low bit rate video when the network state is bad. Multi bit rate adaptation requires two or more corresponding video sources with different bit rates on the server.

Suppose the corresponding video file directory structure on the server:


Using nginx VOD module, you can automatically calculate the bandwidth corresponding to the video and complete the generation of the list file. You only need to splice the corresponding URL address. Multi bit rate adaptive URL playback address (https):,example0001,example0001_low,.mp4.urlset/manifest.mpd

2.4 play DASH stream with shakaplayer

   at present, the playback of DASH streaming media is not natively supported at all ends, but also needs the support of players. The more mainstream ones are Shaka player and DASH JS, this paper uses the open source Html5 player shakaplayer.

2.4.1 compiling and installing shakaplayer

  before installing shakaplayer, you need to install some tools: git v1 9+,Python v2.7 or v3.5+,Java Runtime Environment v8+,NodeJS v10+,Apache(A local web server).

Please refer to the installation instructions on the official website of shakaplayer

Installing git v1.0 9+:
The git version installed with yum is too low. You need to download it from Download the source code of the corresponding version, compile and install it.

Install Python v2 7 or v3. 5+:
You can use yum to install it. If yum is not available, you can also download it from Download the source code of the corresponding version, compile and install it.

To install the Java Runtime Environment v8 +:
jre needs from Download the corresponding version;
After decompression, establish a soft link ln - S // jre1.8.0_321/bin/java / usr / bin / Java, where // jre1.8.0_321/bin/java is the directory after decompressing the compressed package.

Please refer to the installation instructions on the official website

Installing NodeJS v10 +:
You can install nodejs using yum. If Yum is not available, you can also install nodejs from yum Download the source code of the corresponding version, compile and install it.

nodejs of yum Installation steps:
install centos-release-scl
    yum install centos-release-scl-rh
 install yum-config-manager command
    yum install yum-utils
 install RHSCL
    yum-config-manager --enable rhel-server-rhscl-7-rpms
 install nodejs
    yum install rh-nodejs10
 Enable nodejs
    scl enable rh-nodejs10 bash

Please refer to the installation instructions on the official website

To install Web Server:
You can use nginx directly here. Running Shaka player requires the support of the web server because the browser file:///url There are restrictions on applications, so you can't run Shaka player locally.

With the support of the above tools, you can install Shaka player:
Download shakaplayer at;
After decompression, enter the directory and execute Python build / all Py. After success, Shaka player will be generated in the dist directory compiled. JS file, which you need to rely on when creating a shakaplayer player in the web.

2.4.2 play DASH stream with shakaplayer

   include the js file path generated in the previous step in the html, load shakaplayer, and specify the URL playback address (https is required). The details are as follows:

<!DOCTYPE html>

    <!-- Shaka Player compiled library: -->
    <script src="/html/shaka-player-3.3.0/dist/shaka-player.compiled.js"></script>

    <video id="video" width="640" controls autoplay></video>
        // Note that the mpd manifest file played here needs to be accessed using https
        const manifestUri =

        function initApp() {
            // Install built-in polyfills to patch browser incompatibilities.

            // Check to see if the browser supports the basic APIs Shaka needs.
            if (shaka.Player.isBrowserSupported()) {
                // Everything looks good!
            } else {
                // This browser does not have the minimum set of APIs we need.
                console.error('Browser not supported!');

        async function initPlayer() {
            // Create a Player instance.
            const video = document.getElementById('video');
            const player = new shaka.Player(video);

            // //Configure DRM
            // player.configure({
            //     drm: {
            //         servers: {
            //             'org.w3.clearkey': ''
            //         }
            //     }
            // });

            // Attach player to the window to make it easy to access in the JS console.
            window.player = player;

            // Listen for error events.
            player.addEventListener('error', onErrorEvent);

            // Try to load a manifest.
            // This is an asynchronous process.
            try {
                await player.load(manifestUri);
                // This runs if the asynchronous load is successful.
                console.log('The video has now been loaded!');
            } catch (e) {
                // onError is executed if the asynchronous load fails.

        function onErrorEvent(event) {
            // Extract the shaka.util.Error object from the event.

        function onError(error) {
            // Log the error.
            console.error('Error code', error.code, 'object', error);

        document.addEventListener('DOMContentLoaded', initApp);


In this way, DASH streaming video can be played in shakaplayer.

3 DRM encryption

   DRM is digital rights management, which is used to encrypt and protect video content. Through DRM technology, the content can be prevented from being downloaded and illegally transmitted. DASH's DRM solutions include Widevine, PlayReady and ClearKey.

Widevine was originally developed by Widevine Technologies and acquired by Google in 2010. It supports a wide range of devices and browsers, such as Google browser, Android, Chromecast, etc; (commercial DRM solution)
PlayReady, developed by Microsoft, is one of the main DRM systems available and has extensive device support; (commercial DRM solution)
ClearKey is a free alternative to commercial solutions. The following example uses the DRM solution in the form of ClearKey.

3.1 general DRM configuration

3.1.1 build DRM secret key server

   here, the DRM server is built by deploying apache and php code. The role of the DRM server is to provide secret key service, generate and return the secret key required for encryption and decryption after receiving the request.

The DRM server ( here refers to the server that processes the secret key, which is not the same as the server that saved the video content ( Please pay attention to distinguish. In the example, they are deployed on different machines. According to the actual situation, the secret key service and video content service can also be placed on the same server.

Install apache and php support:
There are many deployment tutorials on the Internet, so there is no redundancy. Skip.

The following is a code example of php that can be used. According to different request methods (POST and GET), the encryption key and decryption key are provided to the requester, including the way to generate the encryption and decryption key in a logical way (of course, the simpler way can also directly use plaintext). It simply shows the process of generating the secret key from a 32-bit custom string:

if (!function_exists('hex2bin'))
    function hex2bin($str) 
        $sbin = '';
        $len = strlen($str);
        for ($i = 0; $i < $len; $i += 2) 
            $sbin .= pack('H*', substr($str, $i, 2)); // Every two characters are packed into a hexadecimal string

        return $sbin;

// Replace "-" - > "+", "__" - > "/", and perform base64 decryption
function b64url_dec($s)
    return base64_decode(str_replace(array('-', '_'), array('+', '/'), $s), true);

// After base64 encryption, replace "+" - > "-", "/" - > "", Remove "="
function b64url_enc($s)
    return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($s));

function getKey($kid)
    // TODO: update secret
    return md5('secret' . $kid, true); // Add the prefix secret and perform MD5 encryption

// TODO: add security controls and error validation

    // Request to obtain the decryption key by POST
    $req = file_get_contents('php://input');
    $req = json_decode($req);
    $type = $req->type;
    $keys = array();
    foreach ($req->kids as $kid)
        $key = b64url_enc(getKey(b64url_dec($kid)));
        $keys[] = array('k' => $key, 'kty' => 'oct', 'kid' => $kid);

    $res = array('keys' => $keys, 'type' => $type);
    header('access-control-allow-origin: *');
    // The request uses GET to obtain the encryption key
    $kid = hex2bin('0123456789abcdef0123456789abcdef'); // TODO: allocate according to media id
    $res = array(array(
        'key' => base64_encode(getKey($kid)),
        'key_id' => base64_encode($kid),
        'pssh' => array(array(
            'uuid' => '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b',
            'data' => base64_encode(hex2bin('00000001') . $kid . hex2bin('00000000'))

// Convert to json format output
echo str_replace('\\/', '/', json_encode($res));
?> form of encryption key

Encryption encryption key obtained through GET request:


Key means encryption secret key, key_id refers to the id number of the secret key. pssh is the abbreviation of Protection System Specific Header. pssh is the corresponding information that the encrypted media resources specified by the standardization committee should contain. For more details specified by the Standardization Committee, you can check it—— cenc (International Organization for Standardization) general encryption scheme for basic media files in streaming format5 . Key and key in the example_ ID and PSSH - > data are generated by hash from the user-defined string 0123456789abcdef0123456789abcdef, and the universal unique identification code uuid is a fixed value.

key value
0123456789abcdef0123456789abcdef    // Custom string
#Eg����#Eg / / packed into binary string in hexadecimal format every 2 digits (binary unreadable)
������n`2�4���         // Add the secret prefix, and then perform md5 encryption (binary unreadable)
6JDXwILoGcZuYDKGNPiXgA==        // Perform base64 encryption to obtain the key value

key_id value
0123456789abcdef0123456789abcdef    // Custom string
#Eg����#Eg / / packed into binary string in hexadecimal format every 2 digits (binary unreadable)
ASNFZ4mrze8BI0VniavN7w==            // The key is obtained by base64 encryption_ ID value

pssh->uuid value
1077efec-c0b2-4d02-ace3-3c1e52e2fb4b    // Fixed value

pssh->data value
00000001,0123456789abcdef0123456789abcdef,00000000 // Three custom strings
,#Eg����#Each string is packed according to the binary format of Eg and not connected to the hexadecimal format, and each value is connected to the binary format of Eg
AAAAAQEjRWeJq83vASNFZ4mrze8AAAAA // Perform base64 encryption to obtain the data value form of decryption key

When playing, you can carry kids information through POST request and obtain the corresponding License decryption secret key from the secret key server.

kids information carried in POST request:

{kids: ["ASNFZ4mrze8BI0VniavN7w"], type: "temporary"}

Obtained License decryption key:


k represents the encryption secret key, and kid represents the secret key label. The k in the example can be obtained by kid conversion. In fact, as long as the label corresponds to the secret key one by one.

ASNFZ4mrze8BI0VniavN7w          // Parse the json data attached to the request and get the kid value from kids
#Eg����#Eg / / "-" to "+", "" To "/", base64 decryption (binary unreadable)
������n`2�4���         // Add the prefix secret and perform MD5 encryption (binary unreadable)
6JDXwILoGcZuYDKGNPiXgA          // base64 encryption, ` + ` transfer ` - `, ` / ` transfer ` `, Remove ` = ` to get the value of k

The machine ip of the currently built DRM server is, which will be configured in the subsequent nginx configuration.

3.1.2 add DRM configuration to video content server (for encryption)

Configure and enable DRM in nginx. The purpose of adding DRM configuration here is to make the nginx VOD module encrypt the original video when slicing, and add DRM information to the list file MPD of DASH.

location /vod_dash {
    # DRM related configuration
    vod_drm_enabled on;                         # Enable DRM
    vod_drm_clear_lead_segment_count 0;         # Set all slices to be processed by DRM
    vod_drm_upstream_location /php_proxy/;      # Specify DRM address
    vod_drm_request_uri /dash_clear_key.php;    # Configure php address

# Configure the location pointing to the DRM server address
location /php_proxy/ {
    proxy_pass; #  The forwarding address points to the DRM server address
    proxy_set_header Host $http_host;

This code has been commented out in the previous nginx configuration, and you can release the comment when you need to use DRM.

After nginx is configured, the corresponding DRM information wrapped with ContentProtection field will appear in the requested DASH list file MPD (xml format) during playback.

3.1.3 add DRM configuration on the player side (for decryption)

   some configuration is also required on shakaplayer. Configure DRM information in the player's configure. The purpose of adding DRM configuration here is to decrypt the slices with the requested decryption key before shakaplayer plays each slice of the DASH stream.

    drm: {
        servers: {
            'org.w3.clearkey': ''

It should be noted that the DRM address also needs to use https. This code is commented out in the html previously loaded shakaplayer. When DRM needs to be used, just release the comment.

After the DRM configuration of DRM secret key server, video content server and player is completed, the media stream video played at this time has been encrypted by DRM. For example, the plaintext string is used for simple hash and then encryption and decryption. The security can be continuously improved by improving the complexity of hash function and adding authentication to URL.

The played media content passes through DRM. Although it does not look different in playing in the example, the downloaded and saved content slice cannot be played without DRM verification.

3.2 DRM encryption under multi bit rate adaptation

   since multi bit rate adaptation requires two or more videos to support playback under different bandwidth, for the sake of content security, each video will generally be configured with different secret keys.

3.2.1 DRM secret key server configuration

   in order to support the use of different secret keys for different videos, multiple groups of secret keys need to be configured in the DRM server. The following php code is configured with two groups of ClearKey secret keys, and two groups of secret keys are generated according to the previous rules. Secret key 1 is generated by string 0123456789abcdef0123456789abcdef, and secret key 2 is generated by string 0123456789abcdefabcdef. For simplicity,, When returning, the generated plaintext is directly used for return:


    // get liense
    $key1 = array('k' => '6JDXwILoGcZuYDKGNPiXgA', 'kty' => 'oct', 'kid' => 'ASNFZ4mrze8BI0VniavN7w');
    $key2 = array('k' => 'XHYyt3r8i4EDVtu3HoFl1g', 'kty' => 'oct', 'kid' => 'ASNFZ4kBI0VniavN76vN7w');
    $license = array('keys' => array($key1, $key2), 'type' => 'temporary');
    echo str_replace('\\/', '/', json_encode($license));
    header('access-control-allow-origin: *');
    $currentUrl = $_SERVER["REQUEST_URI"];
    // get key
    $pssh1 = array('uuid' => '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b', 'data' => 'AAAAAQEjRWeJq83vASNFZ4mrze8AAAAA');
    $encrpytion1 = array('key' => '6JDXwILoGcZuYDKGNPiXgA==', 'key_id' => 'ASNFZ4mrze8BI0VniavN7w==', 'pssh' => array($pssh1));
    $pssh2 = array('uuid' => '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b', 'data' => 'AAAAAQEjRWeJASNFZ4mrze+rze8AAAAA');
    $encrpytion2 = array('key' => 'XHYyt3r8i4EDVtu3HoFl1g==', 'key_id' => 'ASNFZ4kBI0VniavN76vN7w==', 'pssh' => array($pssh2));

    if (strpos($currentUrl, 'low') !== false) // If the URL contains the string low, use encryption1
        $encrpytion = array($encrpytion1/*, $encrpytion2*/);
        $encrpytion = array($encrpytion2);

    echo str_replace('\\/', '/', json_encode($encrpytion));


When using GET to make a request, different encryption keys will be returned according to whether a string is carried in the URL (low in the example):

The URL contains a low string, and the encryption key 1 is returned:

        "key": "6JDXwILoGcZuYDKGNPiXgA==",
        "key_id": "ASNFZ4mrze8BI0VniavN7w==",
        "pssh": [
                "uuid": "1077efec-c0b2-4d02-ace3-3c1e52e2fb4b",
                "data": "AAAAAQEjRWeJq83vASNFZ4mrze8AAAAA"

If the URL does not contain a low string, the encryption key 2 is returned:

        "key": "XHYyt3r8i4EDVtu3HoFl1g==",
        "key_id": "ASNFZ4kBI0VniavN76vN7w==",
        "pssh": [
                "uuid": "1077efec-c0b2-4d02-ace3-3c1e52e2fb4b",
                "data": "AAAAAQEjRWeJASNFZ4mrze+rze8AAAAA"

When using POST to make a request, the decryption key group will be returned uniformly:

    "keys": [
            "k": "6JDXwILoGcZuYDKGNPiXgA",
            "kty": "oct",
            "kid": "ASNFZ4mrze8BI0VniavN7w"
            "k": "XHYyt3r8i4EDVtu3HoFl1g",
            "kty": "oct",
            "kid": "ASNFZ4kBI0VniavN76vN7w"
    "type": "temporary"

3.2.2 video content server configuration

  in order for the DRM server to recognize different videos, some parameters that can recognize different videos need to be attached to the request URL to the secret key server. In nginx configuration, add $vod_suburi variable to append the video file path to the end of the request.

vod_drm_request_uri /dash_clear_key.php$vod_suburi;

In conjunction with the determination and detection of the string (low in the example) on the DRM secret key server, videos with no bit rate can be identified (example0001.mp4 and example0001_low.mp4 in the example).

After configuring the DRM server and video content server, the multi bit rate adaptive DASH streaming video can be played using the access method provided in section 2.3.2. At this time, videos with different bit rates are encrypted with different encryption keys.

4. Additional supplement: relevant contents of mpd list document

  finally, you need to know about the mpd list file. The mpd file (Media Presentation Description) of DASH is used to organize a list of various contents to be played. In essence, it is an xml file with the following structure:

Period: the complete video can be divided into multiple periods according to time, and one period can contain one or more adaptationsets;
AdaptationSet (adaptive set), an AdaptationSet can contain one or more representations, which can have different bit rates and resolutions, or different media types, such as video or audio;
Representation (media file description). Each representation describes a Segment of streaming media that can be decoded independently, including code rate, resolution, encoder and other information. A representation contains multiple segments;
Segment (slice), a segment of streaming media that is cut into according to a certain length of time.

   in the example, the nginx VOD module is used to dynamically generate the mpd manifest file by modifying the nginx configuration. Therefore, it is not necessary to manually configure the manifest file. Here is a post. The complete contents of the mpd manifest file generated after the introduction of DRM are as follows:

<?xml version="1.0"?>
        <ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
        <ContentProtection xmlns:cenc="urn:mpeg:cenc:2013" schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b" cenc:default_KID="01234567-89ab-cdef-0123-456789abcdef">
        <ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/>
        <ContentProtection xmlns:cenc="urn:mpeg:cenc:2013" schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b" cenc:default_KID="01234567-89ab-cdef-0123-456789abcdef">
  1. Using nginx to build an audio and video on demand server -- Based on HLS protocol: ↩︎

  2. Introducing LowLatency HLS: ↩︎

  3. Installation process of nginx: ↩︎

  4. Using nginx to build audio and video on demand service -- Based on HLS protocol: ↩︎

  5. ISO Common Encryption ('cenc') Protection Scheme for ISO Base Media File Format Stream Format: ↩︎

Keywords: Nginx server

Added by sherry on Wed, 23 Feb 2022 17:19:53 +0200