ExpressPlay - Widevine and Playready

1
Prerequisites: you need ExpressPlay API key to proceed with this tutorial.

You can find detailed instructions on how to create ExpressPlay API key here.
You also might find helpful the ExpressPlay REST API reference.

2
Generate key identifier and content encryption key.

Here are shell commands you can run manually to generate key identifier (kid) and content encryption key. First, let's export the API key as an environment variable (please replace the value with your ExpressPlay API key):

export API_KEY=123456789,23bc012e34de56e7a8bd6b05e7f0aaa1

Run ExpressPlay Key management service API request to generate kid and content encryption key:

curl -X POST 'https://api.service.expressplay.com/keystore/keys?customerAuthenticator='"$API_KEY"'&kek=11111111111111111111111111111111'

Here the kek param is a Key Encryption Key used to encrypt the stored encryption keys. You can provide any value of 16 bytes length for it formatted as a 32-byte hex string.
An example of response JSON is listed below:

{
  "kid": "6B6801FE59DA030104702C69F1A7D46A",
  "kekId": "#1.952241B0259652B68A8CAE2BE819DFA3390CDB35",
  "ek": "61A9D3B082AAB5A918EBB86461DA475BD80CA4A83CEA16B6",
  "k": "F1234560F6A7DE822574BF2F8190F6CD",
  "lastUpdate": "2021-09-22T22:42:48Z"
}

You'll need to use two values from this response on the next step: kid (key identifier) and k (key for content encryption).

3
Create Qencode API request JSON with encryption params

Use cenc_drm object to specify encryption params for Widevine and Playready

Here's an example of cenc_drm JSON object you need to add to your API request in order to enable Widevine and Playready DRM encryption:

"cenc_drm": {
  "key": "F1234560F6A7DE822574BF2F8190F6CD",
  "key_id": "6B6801FE59DA030104702C69F1A7D46A",
  "pssh": "CAESEAABAgMEBQYHCAkKCwwNDg8aCmludGVydHJ1c3QiASo=",
  "la_url": "https://pr.service.expressplay.com/playready/RightsManager.asmx"
}

You can use the same values for pssh and la_url as shown in the example above.

Full example of Qencode API request JSON with cenc_drm encryption params is shown below:

{
  "query": {
    "source": "https://nyc3.digitaloceanspaces.com/qencode/bbb_30s.mp4",
    "format": [
      {
        "output": "advanced_dash",
        "destination": {
          ...
        },
        "stream": [
          {
            "size": "852x480",
            "audio_bitrate": "128"
          },
          {
            "size": "1280x720",
            "audio_bitrate": "320"
          },
          {
            "size": "1920x1080",
            "audio_bitrate": "320"
          }
        ],
        "cenc_drm": {
          "key": "F1234560F6A7DE822574BF2F8190F6CD",
          "key_id": "6B6801FE59DA030104702C69F1A7D46A",
          "pssh": "CAESEAABAgMEBQYHCAkKCwwNDg8aCmludGVydHJ1c3QiASo=",
          "la_url": "https://pr.service.expressplay.com/playready/RightsManager.asmx"
        }
      }
    ]
  }
}

Use fps_drm object to specify encryption params for Fairplay

Here's an example of fps_drm JSON object you need to add to your API request in order to enable Fairplay DRM encryption:

"fps_drm" : {
  "key" : "F1234560F6A7DE822574BF2F8190F6CD",
  "iv" : "00000000000000000000000000000000",
  "key_url" : "skd://6B6801FE59DA030104702C69F1A7D46A"
}

The iv param is an Initialization Vector for encryption and can be any number of 16 bytes fixed length. It will be needed later as well when generating ExpressPlay tokens for playback.
The key_url param is concatenated from the 'skd://' url prefix and the key_id value obtained on the step #2 described above.

Full example of Qencode API request JSON with cenc_drm encryption params is shown below:

{
  "query": {
    "source": "https://nyc3.digitaloceanspaces.com/qencode/bbb_30s.mp4",
    "format": [
      {
        "output": "advanced_hls",
        "destination": {
          ...
        },
        "stream": [
          {
            "size": "852x480",
            "audio_bitrate": "128"
          },
          {
            "size": "1280x720",
            "audio_bitrate": "320"
          },
          {
            "size": "1920x1080",
            "audio_bitrate": "320"
          }
        ],
        "fps_drm" : {
          "key" : "F1234560F6A7DE822574BF2F8190F6CD",
          "iv" : "00000000000000000000000000000000",
          "key_url" : "skd://6B6801FE59DA030104702C69F1A7D46A"
        }
      }
    ]
  }
}

4
Requesting an ExpressPlay token for playback

Requesting an ExpressPlay token for Widevine:

An example of ExpressPlay API call for token request is shown below:

curl -X GET 'https://wv-gen.service.expressplay.com/hms/wv/token?customerAuthenticator='"$API_KEY"'&errorFormat=json&kid=6B6801FE59DA030104702C69F1A7D46A&contentKey=F1234560F6A7DE822574BF2F8190F6CD&useHttps=true'

ExpressPlay API will respond with a license URL including the token like this:

https://wv.service.expressplay.com/hms/wv/rights/?ExpressPlayToken=BQAdp7z9KdoAJDdhOTE4Yjc4LWZmNGYtNGEwZi1hOTU2LWQyODQ3ZmQwYWIxOAAAAGAef3G1vnu3sh0CgqpxPsFx5feA4GIpCWebwSfQu4MCF0rLOnw9889LPhZF8xgnZNmnLNsl2JvdhJh1jIttOymHOy2Fqwt-42S6rvM_eXQ31Nvgbjacgo4wxvqT272ePVP-x38wb3-V55YvDuOeV8peDv0TSQ

Requesting an ExpressPlay token for Fairplay:

An example of ExpressPlay API call for token request is shown below:

curl -X GET 'https://fp-gen.service.expressplay.com/hms/fp/token?customerAuthenticator='"$API_KEY"'&errorFormat=json&kid=6B6801FE59DA030104702C69F1A7D46A&kek=11111111111111111111111111111111&iv=00000000000000000000000000000000&useHttps=true'

ExpressPlay API will respond with a license URL including the token like this:

https://fp.service.expressplay.com/hms/fp/rights/?ExpressPlayToken=BgAdp6z9KbgAJDdhOTE4Yjc4LWZmNGYtNGEwZi1hOTU2LWQyODQ3ZmQwYWIxOAAAAGBm_cktj4E20aRnfnKD2qr8G7muvaJ668isMokmaXzMVkupS8vDoF1CHkytw0mp8dE-YMNuItn_8nljUordcRwzVMla1GRZPpOBIwW_M5GN0kO7L1z0-Ir6JjlNWTikj3J_mjclFJs9SrPeypqSRjr9OhAYJQ

The URL you've received should be passed to a player as a license URL.

5
Testing playback in Qencode player

To configure your player for playback of the content encrypted with ExpressPlay DRM you need to provide the following settings:

  • Widevine Url: you should specify the URL received on step 4 of this tutorial.

Here's an example of configuring Qencode Player:

var params = {
    licenseKey: "f223fb50-8d26-6b9e-637c-eb62a5e79edb",
    videoSources: {
        src: "https://yourserver.com/content/playlist.mpd",
        keySystems: {
            'com.widevine.alpha': "https://wv.service.expressplay.com/hms/wv/rights/?ExpressPlayToken=BQAdp7z9KdoAJDdhOTE4Yjc4LWZmNGYtNGEwZi1hOTU2LWQyODQ3ZmQwYWIxOAAAAGAef3G1vnu3sh0CgqpxPsFx5feA4GIpCWebwSfQu4MCF0rLOnw9889LPhZF8xgnZNmnLNsl2JvdhJh1jIttOymHOy2Fqwt-42S6rvM_eXQ31Nvgbjacgo4wxvqT272ePVP-x38wb3-V55YvDuOeV8peDv0TSQ",
        },
    },
}

qPlayer('my_player', params, function() { 
    // optional callback function after player is loaded   
    console.log("Player is loaded");                                    
});