|
|
@ -1294,6 +1294,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|
|
|
'401': {'ext': 'mp4', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'av01.0.12M.08'},
|
|
|
|
'401': {'ext': 'mp4', 'height': 2160, 'format_note': 'DASH video', 'vcodec': 'av01.0.12M.08'},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'vtt')
|
|
|
|
_SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'vtt')
|
|
|
|
|
|
|
|
_POTOKEN_EXPERIMENTS = ('51217476', '51217102')
|
|
|
|
|
|
|
|
|
|
|
|
_GEO_BYPASS = False
|
|
|
|
_GEO_BYPASS = False
|
|
|
|
|
|
|
|
|
|
|
@ -3703,6 +3704,13 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|
|
|
def _extract_player_responses(self, clients, video_id, webpage, master_ytcfg, smuggled_data):
|
|
|
|
def _extract_player_responses(self, clients, video_id, webpage, master_ytcfg, smuggled_data):
|
|
|
|
initial_pr = None
|
|
|
|
initial_pr = None
|
|
|
|
if webpage:
|
|
|
|
if webpage:
|
|
|
|
|
|
|
|
experiments = traverse_obj(master_ytcfg, (
|
|
|
|
|
|
|
|
'WEB_PLAYER_CONTEXT_CONFIGS', ..., 'serializedExperimentIds', {str}, {lambda x: x.split(',')}, ..., {str}))
|
|
|
|
|
|
|
|
if all(x in experiments for x in self._POTOKEN_EXPERIMENTS):
|
|
|
|
|
|
|
|
self.report_warning(
|
|
|
|
|
|
|
|
'Webpage contains broken formats (poToken experiment detected). Ignoring initial player response')
|
|
|
|
|
|
|
|
master_ytcfg = self._get_default_ytcfg()
|
|
|
|
|
|
|
|
else:
|
|
|
|
initial_pr = self._search_json(
|
|
|
|
initial_pr = self._search_json(
|
|
|
|
self._YT_INITIAL_PLAYER_RESPONSE_RE, webpage, 'initial player response', video_id, fatal=False)
|
|
|
|
self._YT_INITIAL_PLAYER_RESPONSE_RE, webpage, 'initial player response', video_id, fatal=False)
|
|
|
|
|
|
|
|
|
|
|
@ -3746,11 +3754,22 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|
|
|
player_url = self._download_player_url(video_id)
|
|
|
|
player_url = self._download_player_url(video_id)
|
|
|
|
tried_iframe_fallback = True
|
|
|
|
tried_iframe_fallback = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pr = initial_pr if client == 'web' and initial_pr else None
|
|
|
|
|
|
|
|
for retry in self.RetryManager(fatal=False):
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
pr = initial_pr if client == 'web' and initial_pr else self._extract_player_response(
|
|
|
|
pr = pr or self._extract_player_response(
|
|
|
|
client, video_id, player_ytcfg or master_ytcfg, player_ytcfg, player_url if require_js_player else None, initial_pr, smuggled_data)
|
|
|
|
client, video_id, player_ytcfg or master_ytcfg, player_ytcfg,
|
|
|
|
|
|
|
|
player_url if require_js_player else None, initial_pr, smuggled_data)
|
|
|
|
except ExtractorError as e:
|
|
|
|
except ExtractorError as e:
|
|
|
|
self.report_warning(e)
|
|
|
|
self.report_warning(e)
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
experiments = traverse_obj(pr, (
|
|
|
|
|
|
|
|
'responseContext', 'serviceTrackingParams', lambda _, v: v['service'] == 'GFEEDBACK',
|
|
|
|
|
|
|
|
'params', lambda _, v: v['key'] == 'e', 'value', {lambda x: x.split(',')}, ..., {str}))
|
|
|
|
|
|
|
|
if all(x in experiments for x in self._POTOKEN_EXPERIMENTS):
|
|
|
|
|
|
|
|
pr = None
|
|
|
|
|
|
|
|
retry.error = ExtractorError('API returned broken formats (poToken experiment detected)', expected=True)
|
|
|
|
|
|
|
|
if not pr:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
if pr_id := self._invalid_player_response(pr, video_id):
|
|
|
|
if pr_id := self._invalid_player_response(pr, video_id):
|
|
|
|