aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinePlayersPE <mineplayerspealt@gmail.com>2022-01-07 19:11:10 +0700
committerGitHub <noreply@github.com>2022-01-07 17:41:10 +0530
commit5f969a78b01f1043f62be5d4dfd170bf281e5081 (patch)
tree956b8896c7b4cb2d0ca021917798ca07cf94c93f
parent443f8de8200ae07958d78bdd163830ba22fe88b3 (diff)
downloadhypervideo-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.py62
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)