mirror of
https://github.com/yt-dlp/yt-dlp
synced 2024-12-26 21:59:08 +01:00
[fd/dash] support DASH SEA (AES-128-CBC) decryption
This commit is contained in:
parent
e0ce6eed92
commit
bd62cdba1a
1 changed files with 28 additions and 13 deletions
|
@ -8,7 +8,7 @@ from . import get_suitable_downloader
|
|||
from .fragment import FragmentFD
|
||||
from ..networking import Request
|
||||
from ..networking.exceptions import RequestError
|
||||
from ..utils import update_url_query, urljoin
|
||||
from ..utils import remove_start, traverse_obj, update_url_query, urljoin
|
||||
|
||||
|
||||
class DashSegmentsFD(FragmentFD):
|
||||
|
@ -54,6 +54,25 @@ class DashSegmentsFD(FragmentFD):
|
|||
if extra_param_to_segment_url:
|
||||
extra_query = urllib.parse.parse_qs(extra_param_to_segment_url)
|
||||
|
||||
hls_aes = fmt.get('hls_aes', {})
|
||||
if hls_aes:
|
||||
decrypt_info = {'METHOD', 'AES-128'}
|
||||
key = hls_aes.get('key')
|
||||
if key:
|
||||
key = binascii.unhexlify(remove_start(key, '0x'))
|
||||
assert len(key) in (16, 24, 32), 'Invalid length for HLS AES-128 key'
|
||||
decrypt_info['KEY'] = key
|
||||
iv = hls_aes.get('iv')
|
||||
if iv:
|
||||
iv = binascii.unhexlify(remove_start(iv, '0x').zfill(32))
|
||||
decrypt_info['IV'] = iv
|
||||
uri = hls_aes.get('uri')
|
||||
if uri:
|
||||
if extra_query:
|
||||
uri = update_url_query(uri, extra_query)
|
||||
decrypt_info['URI'] = uri
|
||||
ctx['decrypt_info'] = decrypt_info
|
||||
|
||||
fragments_to_download = self._get_fragments(fmt, ctx, extra_query)
|
||||
|
||||
if real_downloader:
|
||||
|
@ -65,8 +84,11 @@ class DashSegmentsFD(FragmentFD):
|
|||
|
||||
args.append([ctx, fragments_to_download, fmt])
|
||||
|
||||
if 'dash_cenc' in info_dict and not info_dict['dash_cenc'].get('key'):
|
||||
self._get_clearkey_cenc(info_dict)
|
||||
cenc_key = traverse_obj(info_dict, ('dash_cenc', 'key'))
|
||||
cenc_key_ids = traverse_obj(info_dict, ('dash_cenc', 'key_ids'))
|
||||
clearkey_laurl = traverse_obj(info_dict, ('dash_cenc', 'laurl'))
|
||||
if not cenc_key and cenc_key_ids and clearkey_laurl:
|
||||
self._get_clearkey_cenc(info_dict, clearkey_laurl, cenc_key_ids)
|
||||
|
||||
return self.download_and_append_fragments_multiple(*args, is_fatal=lambda idx: idx == 0)
|
||||
|
||||
|
@ -95,18 +117,11 @@ class DashSegmentsFD(FragmentFD):
|
|||
'fragment_count': fragment.get('fragment_count'),
|
||||
'index': i,
|
||||
'url': fragment_url,
|
||||
'decrypt_info': ctx.get('decrypt_info', {'METHOD': 'NONE'}),
|
||||
}
|
||||
|
||||
def _get_clearkey_cenc(self, info_dict):
|
||||
def _get_clearkey_cenc(self, info_dict, laurl, key_ids):
|
||||
dash_cenc = info_dict.get('dash_cenc', {})
|
||||
laurl = dash_cenc.get('laurl')
|
||||
if not laurl:
|
||||
self.report_error('No Clear Key license server URL for encrypted DASH stream')
|
||||
return
|
||||
key_ids = dash_cenc.get('key_ids')
|
||||
if not key_ids:
|
||||
self.report_error('No requested CENC KIDs for encrypted DASH stream')
|
||||
return
|
||||
payload = json.dumps({
|
||||
'kids': [
|
||||
base64.urlsafe_b64encode(bytes.fromhex(k)).decode().rstrip('=')
|
||||
|
@ -128,7 +143,7 @@ class DashSegmentsFD(FragmentFD):
|
|||
k = key.get('k')
|
||||
if k:
|
||||
try:
|
||||
dash_cenc['key'] = base64.urlsafe_b64decode(f'{k}==').hex()
|
||||
dash_cenc.update({'key': base64.urlsafe_b64decode(f'{k}==').hex()})
|
||||
info_dict['dash_cenc'] = dash_cenc
|
||||
return
|
||||
except (ValueError, binascii.Error):
|
||||
|
|
Loading…
Reference in a new issue