Skip to content

DRM API

Auto-generated reference for the DRM systems: Widevine, PlayReady, ClearKey, and related helpers. For configuring DRM as a user, see DRM & CDM Setup.

ClearKey

ClearKey(key, iv=None)

AES-128 ClearKey (HLS) DRM system.

Give the IV where possible. If you do not give an IV, unshackle sets it to of the same bit-size as the content key.

warn_clear

warn_clear(reason)

Warn once per track that unshackle passed a segment through undecrypted.

decrypt

decrypt(path)

Decrypt a Track with AES-128 ClearKey (HLS) DRM.

from_m3u_key classmethod

from_m3u_key(m3u_key, session=None)

Load a ClearKey from an M3U(8) Playlist's EXT-X-KEY.

Parameters:

Name Type Description Default
m3u_key Key

A Key object parsed from a m3u(8) playlist using the m3u8 library.

required
session Optional[Session]

Optional HTTP session used to request external URIs with. Useful to set headers, proxies, cookies, and so forth.

None

ClearKeyCENC

ClearKeyCENC(kids, laurl=None, content_keys=None, **kwargs)

W3C EME ClearKey (org.w3.clearkey) DRM System over MPEG-CENC tracks.

Distinct from the HLS AES-128 ClearKey class: a license server gives the keys here as a JWK Set keyed by KID, and the media is standard CENC (decrypted with shaka-packager/mp4decrypt KID:KEY pairs, same as Widevine).

kid property

kid

Get first Key ID, if any.

Exceptions

KIDNotFound

Bases: Exception

KID (Encryption Key ID) was not found.

CEKNotFound

Bases: Exception

CEK (Content Encryption Key) for KID was not found in License.

EmptyLicense

Bases: Exception

License returned no Content Encryption Keys.

to_dict

to_dict()

Serialise this DRM instance for export/import (KIDs + license URL).

unshackle stores the content keys once at the export's track level, and does not duplicate them here.

get_license_challenge

get_license_challenge()

Assemble the W3C EME ClearKey JSON license request for the unkeyed KIDs.

get_content_keys

get_content_keys(*, licence, session=None)

Get Content Keys for this DRM Instance from a ClearKey license server.

The licence param is a function. unshackle gives it the W3C JSON license request as challenge. It may return the JWK Set license as a dict, JSON str, or bytes. If it returns None and the manifest gave a Laurl, unshackle POSTs the challenge there directly instead.

decrypt

decrypt(path)

Decrypt a Track with ClearKey DRM (standard CENC). Args: path: Path to the encrypted file to decrypt Raises: EnvironmentError if the required decryption executable could not be found. ValueError if unshackle has not yet downloaded the track. SubprocessError if the decryption process returned a non-zero exit code.

mp4decrypt_key_args

mp4decrypt_key_args()

Build the mp4decrypt --key arguments for every content key.

decrypt_with_mp4decrypt

decrypt_with_mp4decrypt(path)

Decrypt using mp4decrypt

decrypt_with_shaka_packager

decrypt_with_shaka_packager(path)

Decrypt with shaka-packager

MonaLisa

MonaLisa(ticket, aes_key, device_path, **kwargs)

MonaLisa DRM System.

Unlike Widevine/PlayReady, MonaLisa does not use a challenge/response flow with a license server. Instead, the service API gives the PSSH value (ticket) directly, and a WASM module extracts the content keys locally.

Decryption has two stages: 1. ML-Worker binary: Removes MonaLisa encryption layer (bbts -> ents) 2. AES-ECB decryption: Final decryption with the service-supplied content key

Initialise MonaLisa DRM.

Parameters:

Name Type Description Default
ticket Union[str, bytes]

PSSH value from service API (base64 string or raw bytes).

required
aes_key Union[str, bytes]

AES-ECB content key for second-stage decryption (hex string or bytes).

required
device_path Path

Path to the CDM device file (.mld).

required
**kwargs Any

Additional metadata stored in self.data.

{}

Raises:

Type Description
TicketNotFound

If ticket/PSSH is empty.

KeyExtractionFailed

If content key extraction fails.

kid property

kid

Get the Key ID.

key property

key

Get the content key as hex string.

pssh property

pssh

Get the raw PSSH/ticket value as a string.

Returns:

Type Description
str

The raw PSSH value as a base64 string.

content_id property

content_id

Extract the Content ID from the PSSH for display.

The PSSH contains an embedded Content ID at bytes 21-75 with format: H5DCID-V3-P1-YYYYMMDD-HHMMSS-MEDIAID-TIMESTAMP-SUFFIX

Returns:

Type Description
Optional[str]

The Content ID string if extractable, None otherwise.

content_keys property

content_keys

Get content keys in the same format as Widevine/PlayReady.

Returns:

Type Description
dict[UUID, str]

Dictionary mapping KID to the content key hex string.

Exceptions

TicketNotFound

Bases: Exception

Raised when the caller gives no PSSH/ticket data.

KeyExtractionFailed

Bases: Exception

Raised when content key extraction from the ticket fails.

WorkerNotFound

Bases: Exception

Raised when the ML-Worker binary is not found.

DecryptionFailed

Bases: Exception

Raised when segment decryption fails.

extract_keys

extract_keys()

Extract keys from the ticket using the MonaLisa CDM.

from_ticket classmethod

from_ticket(ticket, aes_key, device_path)

Make a MonaLisa DRM instance from a PSSH/ticket.

Parameters:

Name Type Description Default
ticket Union[str, bytes]

PSSH value from service API.

required
aes_key Union[str, bytes]

AES-ECB content key for second-stage decryption.

required
device_path Path

Path to the CDM device file (.mld).

required

Returns:

Type Description
MonaLisa

MonaLisa DRM instance with extracted keys.

decrypt_segment

decrypt_segment(segment_path)

Decrypt a single segment using two-stage decryption.

Stage 1: ML-Worker binary (bbts -> ents) Stage 2: AES-ECB decryption (ents -> ts)

Parameters:

Name Type Description Default
segment_path Path

Path to the encrypted segment file.

required

Raises:

Type Description
WorkerNotFound

If ML-Worker binary is not available.

DecryptionFailed

If decryption fails at any stage.

decrypt

decrypt(_path)

MonaLisa uses per-segment decryption during download, through the on_segment_downloaded callback. When the caller calls this method, unshackle has already decrypted the media and muxed it into a container.

Parameters:

Name Type Description Default
_path Path

Path to the file (ignored).

required

PlayReady

PlayReady(pssh, kid=None, pssh_b64=None, **kwargs)

PlayReady DRM System.

extract_kids_from_pssh_b64

extract_kids_from_pssh_b64(pssh_b64)

Extract all KIDs from base64-encoded PSSH data.

to_dict

to_dict()

Serialise this DRM instance for export/import (PSSH + KIDs).

unshackle stores the content keys once at the export's track level, and does not duplicate them here.

extract_keys_from_cdm

extract_keys_from_cdm(cdm, session_id)

Extract keys from CDM session with cross-library compatibility.

Parameters:

Name Type Description Default
cdm Cdm

CDM instance

required
session_id bytes

Session identifier

required

Returns:

Type Description
dict

Dictionary mapping KID UUIDs to hex keys

detect_revocation staticmethod

detect_revocation(text)

Return the decoded error string if a revocation HRESULT is present, else None.

Reads the code from the raw SOAP body (0x8004C065) or from an exception message that carries it, so this method covers any service.

decrypt

decrypt(path)

Decrypt a Track with PlayReady DRM. Args: path: Path to the encrypted file to decrypt Raises: EnvironmentError if the required decryption executable could not be found. ValueError if unshackle has not yet downloaded the track. SubprocessError if the decryption process returned a non-zero exit code.

mp4decrypt_key_args

mp4decrypt_key_args()

Build the mp4decrypt --key arguments for every content key.

decrypt_with_mp4decrypt

decrypt_with_mp4decrypt(path)

Decrypt using mp4decrypt

decrypt_with_shaka_packager

decrypt_with_shaka_packager(path)

Decrypt with shaka-packager (original method)

Widevine

Widevine(pssh, kid=None, **kwargs)

Widevine DRM System.

pssh property

pssh

Get Protection System Specific Header Box.

kid property

kid

Get first Key ID, if any.

kids property

kids

Get all Key IDs from PSSH, falling back to the externally provided KID.

Exceptions

PSSHNotFound

Bases: Exception

PSSH (Protection System Specific Header) was not found.

KIDNotFound

Bases: Exception

KID (Encryption Key ID) was not found.

CEKNotFound

Bases: Exception

CEK (Content Encryption Key) for KID was not found in License.

EmptyLicense

Bases: Exception

License returned no Content Encryption Keys.

from_track classmethod

from_track(track, session=None)

Get PSSH and KID from within the Initiation Segment of the Track Data. It also tries to get PSSH and KID from other track data like M3U8 data as well as through FFprobe.

Make a Widevine DRM System object from a track's information. Use this method only when a PSSH cannot be given directly. It is rare to need to use this.

You can give your own requests.Session to use custom headers and more.

Raises:

Type Description
PSSHNotFound

If the PSSH was not found within the data.

KIDNotFound

If the KID was not found within the data or PSSH.

from_init_data classmethod

from_init_data(init_data)

Get PSSH and KID from within Initialization Segment Data.

Use this method only when a PSSH cannot be given directly. It is rare to need to use this.

Raises:

Type Description
PSSHNotFound

If the PSSH was not found within the data.

KIDNotFound

If the KID was not found within the data or PSSH.

to_dict

to_dict()

Serialise this DRM instance for export/import (PSSH + KIDs).

unshackle stores the content keys once at the export's track level, and does not duplicate them here.

get_content_keys

get_content_keys(cdm, certificate, licence)

Make a CDM Session and get Content Keys for this DRM Instance. The certificate and license params are functions. unshackle gives them the challenge and the session ID.

get_NF_content_keys

get_NF_content_keys(cdm, certificate, licence)

Make a CDM Session and get Content Keys for this DRM Instance. The certificate and license params are functions. unshackle gives them the challenge and the session ID.

decrypt

decrypt(path)

Decrypt a Track with Widevine DRM. Args: path: Path to the encrypted file to decrypt Raises: EnvironmentError if the required decryption executable could not be found. ValueError if unshackle has not yet downloaded the track. SubprocessError if the decryption process returned a non-zero exit code.

mp4decrypt_key_args

mp4decrypt_key_args()

Build the mp4decrypt --key arguments for every content key.

decrypt_with_mp4decrypt

decrypt_with_mp4decrypt(path)

Decrypt using mp4decrypt

decrypt_with_shaka_packager

decrypt_with_shaka_packager(path)

Decrypt with shaka-packager (original method)

drm_from_dict

drm_from_dict(data)

Reconstruct a Widevine/PlayReady/ClearKeyCENC DRM instance from its to_dict() form.

Rebuilds the PSSH from the stored base64 (KIDs for ClearKey, which has no PSSH) and re-injects any saved content keys so the resulting object can decrypt without contacting a license server.