From 8c8c9368baa6ad8b74394ab7182375ef57164113 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 29 Jan 2026 10:34:03 -0700 Subject: [PATCH] fix(manifests): correct DRM type selection for remote PlayReady CDMs HLS: Filter segment keys by CDM type during aria2c merge phase to prevent incorrect Widevine selection when using PlayReady-only CDMs. The merge phase now uses filter_keys_for_cdm() before get_supported_key(), matching the pattern used in initial licensing. DASH: Extend PlayReady CDM detection to include remote CDMs with is_playready attribute, not just native PlayReadyCdm instances. This ensures correct DRM extraction order from init_data when using remote PlayReady CDMs. --- unshackle/core/manifests/dash.py | 3 ++- unshackle/core/manifests/hls.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/unshackle/core/manifests/dash.py b/unshackle/core/manifests/dash.py index 438351b..fd51557 100644 --- a/unshackle/core/manifests/dash.py +++ b/unshackle/core/manifests/dash.py @@ -468,7 +468,8 @@ class DASH: track.data["dash"]["segment_durations"] = segment_durations if init_data and isinstance(track, (Video, Audio)): - if isinstance(cdm, PlayReadyCdm): + prefers_playready = isinstance(cdm, PlayReadyCdm) or (hasattr(cdm, "is_playready") and cdm.is_playready) + if prefers_playready: try: track.drm = [PlayReady.from_init_data(init_data)] except PlayReady.Exceptions.PSSHNotFound: diff --git a/unshackle/core/manifests/hls.py b/unshackle/core/manifests/hls.py index 85ec245..2f3dd1f 100644 --- a/unshackle/core/manifests/hls.py +++ b/unshackle/core/manifests/hls.py @@ -591,7 +591,11 @@ class HLS: segment_keys = getattr(segment, "keys", None) if segment_keys: - key = HLS.get_supported_key(segment_keys) + if cdm: + cdm_segment_keys = HLS.filter_keys_for_cdm(segment_keys, cdm) + key = HLS.get_supported_key(cdm_segment_keys) if cdm_segment_keys else HLS.get_supported_key(segment_keys) + else: + key = HLS.get_supported_key(segment_keys) if encryption_data and encryption_data[0] != key and i != 0 and segment not in unwanted_segments: decrypt(include_this_segment=False)