ExpressPlay - Widevine and Playready
1Prerequisites: 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.
2Generate 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).
3Create 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"
}
}
]
}
}
4Requesting 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.
5Testing 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");
});