DRM & CDM¶
These are the config keys. For concepts, device provisioning, and the wvd/prd commands see
the DRM & CDM guide. Device files themselves live in
directories.wvds (.wvd) and directories.prds (.prd).
cdm¶
- Type:
dict· Default:{}
Maps a service tag to the CDM (Widevine/PlayReady device) to use, with a default fallback.
Resolution is case-insensitive: a per-request API override wins, then the per-service entry,
then default.
A value may also be a nested dict for advanced selection by quality, DRM system, or profile:
cdm:
EXAMPLE1:
">=1080": android_l1 # by track height
"<1080": chromecdm_l3
widevine: android_l1 # by DRM system
playready: sl3000
default: chromecdm_l3
Quality keys support 1080, >=1080, >720, <=576, <480 style comparisons; DRM keys
are widevine / playready. Quality keys are matched first, but only when a video height is
known; if the value is still a dict after that, widevine/playready are used when present,
otherwise the credential profile name, then default.
The resolved name is looked up in remote_cdm by name first. If no entry
matches, it is loaded as a local device file, in this order: <name>.prd in
directories.prds, <name>.prd in directories.wvds, then <name>.wvd in
directories.wvds.
remote_cdm¶
- Type:
list[dict]· Default:[]
A list of remote CDM server definitions. Each entry is matched by its name (referenced from
cdm), and its type selects the backend:
type |
Backend | Key fields |
|---|---|---|
decrypt_labs |
Decrypt Labs KeyXtractor | host, device_name, secret (fields) |
custom_api |
Fully YAML-configurable remote API | host (required), device, auth, endpoints, request_mapping, response_mapping, caching, timeout (fields) |
(none), Device Type: PLAYREADY |
pyplayready RemoteCdm |
host, secret, device_name, security_level (default 3000) |
| (none), otherwise | pywidevine RemoteCdm |
host, secret, device_name, device_type, system_id, security_level (default 3000) |
remote_cdm:
- name: keyxtractor
type: decrypt_labs
device_name: L1
- name: my_wv_server
host: https://cdm.example.com
secret: s3cr3t
device_name: android_l1
device_type: ANDROID
system_id: 26830
security_level: 1
For the two pywidevine/pyplayready backends, field names are read case-insensitively in both
styles: Device Type/device_type, System ID/system_id, Security Level/security_level,
Host/host, Secret/secret, Device Name/device_name.
PlayReady host needs a /playready suffix
pyplayready's RemoteCdm treats host as a base URL and appends its own endpoint paths,
so a PlayReady entry's host must include the trailing /playready segment (for example
https://cdm.example.com/playready). Without it the server returns 404 rather than a
configuration error.
decrypt_labs fields¶
| Field | Default | Notes |
|---|---|---|
host |
https://keyxtractor.decryptlabs.com |
|
device_name |
ChromeCDM |
ChromeCDM, L1, L2 (Widevine) or SL2, SL3 (PlayReady) |
secret |
from decrypt_labs_api_key |
Sent as the decrypt-labs-api-key header. An error is raised if neither is set. |
system_id |
26830 (Widevine), 0 (PlayReady) |
|
security_level |
Widevine 3; PlayReady 2000 for SL2, else 3000 |
PlayReady mode is used when device_type is PLAYREADY or device_name starts with SL.
custom_api fields¶
| Field | Type | Notes |
|---|---|---|
host |
str | Required. Base URL of the API. |
device |
dict | name, type (CHROME, ANDROID, PLAYREADY), system_id, security_level |
auth |
dict | type (default header): header uses header_name (default Authorization) and key; bearer uses bearer_token or key; basic uses username and password. custom_headers is merged in for any type. |
endpoints |
dict | get_request and decrypt_response, each {path, method, timeout} |
request_mapping |
dict | Per endpoint: param_names, static_params, conditional_params, transforms, nested_params, exclude_params |
response_mapping |
dict | Per endpoint: fields, transforms, response_types, success_conditions, error_fields, key_fields |
caching |
dict | enabled, use_vaults, check_cached_first |
legacy |
dict | Legacy mode options. |
timeout |
int | Default 30. Request timeout in seconds. |
Transforms cover base64/hex/JSON encoding and kid:key parsing. PlayReady mode is used when
device.type is PLAYREADY or the device name is SL2/SL3.
remote_cdm:
- name: my_custom
type: custom_api
host: https://cdm.example.com
device:
name: ChromeCDM
type: CHROME
system_id: 26830
security_level: 3
auth:
type: bearer
key: your-token
endpoints:
get_request:
path: /get-challenge
method: POST
decrypt_response:
path: /get-keys
method: POST
timeout: 30
decryption¶
- Type:
strordict· Default:"shaka"
Selects the tool used to physically decrypt CENC content. The value is compared
case-insensitively; "mp4decrypt" selects Bento4's mp4decrypt, and anything else
(including "shaka") selects shaka-packager. When the value is a dict, the service key is
matched case-insensitively and the default entry is the fallback.
HLS AES-128 ClearKey is decrypted in-process and ignores this setting.