diff options
author | MinePlayersPE <mineplayerspealt@gmail.com> | 2022-01-07 19:11:10 +0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-07 17:41:10 +0530 |
commit | 5f969a78b01f1043f62be5d4dfd170bf281e5081 (patch) | |
tree | 956b8896c7b4cb2d0ca021917798ca07cf94c93f | |
parent | 443f8de8200ae07958d78bdd163830ba22fe88b3 (diff) | |
download | hypervideo-pre-5f969a78b01f1043f62be5d4dfd170bf281e5081.tar.lz hypervideo-pre-5f969a78b01f1043f62be5d4dfd170bf281e5081.tar.xz hypervideo-pre-5f969a78b01f1043f62be5d4dfd170bf281e5081.zip |
[Nexx] Support 3q CDN (#2213)
Closes #1637
Authored by: MinePlayersPE
-rw-r--r-- | yt_dlp/extractor/nexx.py | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/yt_dlp/extractor/nexx.py b/yt_dlp/extractor/nexx.py index 8aceebd49..c9eab46a9 100644 --- a/yt_dlp/extractor/nexx.py +++ b/yt_dlp/extractor/nexx.py @@ -12,6 +12,7 @@ from ..utils import ( ExtractorError, int_or_none, parse_duration, + traverse_obj, try_get, urlencode_postdata, ) @@ -220,6 +221,65 @@ class NexxIE(InfoExtractor): return formats + def _extract_3q_formats(self, video, video_id): + stream_data = video['streamdata'] + cdn = stream_data['cdnType'] + assert cdn == '3q' + + q_acc, q_prefix, q_locator, q_hash = stream_data['qAccount'], stream_data['qPrefix'], stream_data['qLocator'], stream_data['qHash'] + protection_key = traverse_obj( + video, ('protectiondata', 'key'), expected_type=str) + + def get_cdn_shield_base(shield_type=''): + for secure in ('', 's'): + cdn_shield = stream_data.get('cdnShield%sHTTP%s' % (shield_type, secure.upper())) + if cdn_shield: + return 'http%s://%s' % (secure, cdn_shield) + return f'http://sdn-global-{"prog" if shield_type.lower() == "prog" else "streaming"}-cache.3qsdn.com/' + (f's/{protection_key}/' if protection_key else '') + + stream_base = get_cdn_shield_base() + + formats = [] + formats.extend(self._extract_m3u8_formats( + f'{stream_base}{q_acc}/files/{q_prefix}/{q_locator}/{q_acc}-{stream_data.get("qHEVCHash") or q_hash}.ism/manifest.m3u8', + video_id, 'mp4', m3u8_id=f'{cdn}-hls', fatal=False)) + formats.extend(self._extract_mpd_formats( + f'{stream_base}{q_acc}/files/{q_prefix}/{q_locator}/{q_acc}-{q_hash}.ism/manifest.mpd', + video_id, mpd_id=f'{cdn}-dash', fatal=False)) + + progressive_base = get_cdn_shield_base('Prog') + q_references = stream_data.get('qReferences') or '' + fds = q_references.split(',') + for fd in fds: + ss = fd.split(':') + if len(ss) != 3: + continue + tbr = int_or_none(ss[1], scale=1000) + formats.append({ + 'url': f'{progressive_base}{q_acc}/uploads/{q_acc}-{ss[2]}.webm', + 'format_id': f'{cdn}-{ss[0]}{"-%s" % tbr if tbr else ""}', + 'tbr': tbr, + }) + + azure_file_distribution = stream_data.get('azureFileDistribution') or '' + fds = azure_file_distribution.split(',') + for fd in fds: + ss = fd.split(':') + if len(ss) != 3: + continue + tbr = int_or_none(ss[0]) + width, height = ss[1].split('x') if len(ss[1].split('x')) == 2 else (None, None) + f = { + 'url': f'{progressive_base}{q_acc}/files/{q_prefix}/{q_locator}/{ss[2]}.mp4', + 'format_id': f'{cdn}-http-{"-%s" % tbr if tbr else ""}', + 'tbr': tbr, + 'width': int_or_none(width), + 'height': int_or_none(height), + } + formats.append(f) + + return formats + def _extract_azure_formats(self, video, video_id): stream_data = video['streamdata'] cdn = stream_data['cdnType'] @@ -384,6 +444,8 @@ class NexxIE(InfoExtractor): formats = self._extract_azure_formats(video, video_id) elif cdn == 'free': formats = self._extract_free_formats(video, video_id) + elif cdn == '3q': + formats = self._extract_3q_formats(video, video_id) else: self.raise_no_formats(f'{cdn} formats are currently not supported', video_id) |