]> jfr.im git - yt-dlp.git/commitdiff
[youtube] Use android client as default and add age-gate bypass for it (#492)
authorcoletdjnz <redacted>
Tue, 13 Jul 2021 22:28:51 +0000 (10:28 +1200)
committerGitHub <redacted>
Tue, 13 Jul 2021 22:28:51 +0000 (03:58 +0530)
Authored by: colethedj

yt_dlp/extractor/youtube.py

index cb1d571f9b28e2486b9ed868058300c4d2451b0e..1b4f3960b275f459d3abb831bf5a383f8c4968e5 100644 (file)
@@ -2249,14 +2249,24 @@ def _generate_player_context(sts=None):
         }
 
     @staticmethod
-    def _get_video_info_params(video_id):
-        return {
+    def _get_video_info_params(video_id, client='TVHTML5'):
+        GVI_CLIENTS = {
+            'ANDROID': {
+                'c': 'ANDROID',
+                'cver': '16.20',
+            },
+            'TVHTML5': {
+                'c': 'TVHTML5',
+                'cver': '6.20180913',
+            }
+        }
+        query = {
             'video_id': video_id,
             'eurl': 'https://youtube.googleapis.com/v/' + video_id,
-            'html5': '1',
-            'c': 'TVHTML5',
-            'cver': '6.20180913',
+            'html5': '1'
         }
+        query.update(GVI_CLIENTS.get(client))
+        return query
 
     def _real_extract(self, url):
         url, smuggled_data = unsmuggle_url(url, {})
@@ -2278,8 +2288,8 @@ def _real_extract(self, url):
 
         player_client = self._configuration_arg('player_client', [''])[0]
         if player_client not in ('web', 'android', ''):
-            self.report_warning(f'Invalid player_client {player_client} given. Falling back to WEB')
-        force_mobile_client = player_client == 'android'
+            self.report_warning(f'Invalid player_client {player_client} given. Falling back to android client.')
+        force_mobile_client = player_client != 'web'
         player_skip = self._configuration_arg('player_skip')
 
         def get_text(x):
@@ -2308,7 +2318,7 @@ def get_text(x):
                 # Android client already has signature descrambled
                 # See: https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
                 if not sts:
-                    self.report_warning('Falling back to mobile remix client for player API.')
+                    self.report_warning('Falling back to android remix client for player API.')
                 ytm_client = 'ANDROID_MUSIC'
                 ytm_cfg = {}
 
@@ -2322,7 +2332,7 @@ def get_text(x):
                 item_id=video_id, ep='player', query=ytm_query,
                 ytcfg=ytm_cfg, headers=ytm_headers, fatal=False,
                 default_client=ytm_client,
-                note='Downloading %sremix player API JSON' % ('mobile ' if force_mobile_client else ''))
+                note='Downloading %sremix player API JSON' % ('android ' if force_mobile_client else ''))
             ytm_streaming_data = try_get(ytm_player_response, lambda x: x['streamingData'], dict) or {}
 
         player_response = None
@@ -2340,7 +2350,7 @@ def get_text(x):
                 # Android client already has signature descrambled
                 # See: https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
                 if not sts:
-                    self.report_warning('Falling back to mobile client for player API.')
+                    self.report_warning('Falling back to android client for player API.')
                 yt_client = 'ANDROID'
                 ytpcfg = {}
                 ytp_headers = self._generate_api_headers(ytpcfg, identity_token, syncid, yt_client)
@@ -2351,19 +2361,24 @@ def get_text(x):
                 item_id=video_id, ep='player', query=yt_query,
                 ytcfg=ytpcfg, headers=ytp_headers, fatal=False,
                 default_client=yt_client,
-                note='Downloading %splayer API JSON' % ('mobile ' if force_mobile_client else '')
-            )
+                note='Downloading %splayer API JSON' % ('android ' if force_mobile_client else '')
+            ) or player_response
 
         # Age-gate workarounds
         playability_status = player_response.get('playabilityStatus') or {}
         if playability_status.get('reason') in self._AGE_GATE_REASONS:
-            pr = self._parse_json(try_get(compat_parse_qs(
-                self._download_webpage(
-                    base_url + 'get_video_info', video_id,
-                    'Refetching age-gated info webpage', 'unable to download video info webpage',
-                    query=self._get_video_info_params(video_id), fatal=False)),
-                lambda x: x['player_response'][0],
-                compat_str) or '{}', video_id)
+            gvi_clients = ('ANDROID', 'TVHTML5') if force_mobile_client else ('TVHTML5', 'ANDROID')
+            for gvi_client in gvi_clients:
+                pr = self._parse_json(try_get(compat_parse_qs(
+                    self._download_webpage(
+                        base_url + 'get_video_info', video_id,
+                        'Refetching age-gated %s info webpage' % gvi_client.lower(),
+                        'unable to download video info webpage', fatal=False,
+                        query=self._get_video_info_params(video_id, client=gvi_client))),
+                    lambda x: x['player_response'][0],
+                    compat_str) or '{}', video_id)
+                if pr:
+                    break
             if not pr:
                 self.report_warning('Falling back to embedded-only age-gate workaround.')
                 embed_webpage = None
@@ -2386,7 +2401,7 @@ def get_text(x):
                         # See: https://github.com/TeamNewPipe/NewPipeExtractor/issues/562
                         if not sts:
                             self.report_warning(
-                                'Falling back to mobile embedded client for player API (note: some formats may be missing).')
+                                'Falling back to android embedded client for player API (note: some formats may be missing).')
                         yt_client = 'ANDROID_EMBEDDED_PLAYER'
                         ytcfg_age = {}
 
@@ -2398,7 +2413,7 @@ def get_text(x):
                         item_id=video_id, ep='player', query=yt_age_query,
                         ytcfg=ytcfg_age, headers=ytage_headers, fatal=False,
                         default_client=yt_client,
-                        note='Downloading %sage-gated player API JSON' % ('mobile ' if force_mobile_client else '')
+                        note='Downloading %sage-gated player API JSON' % ('android ' if force_mobile_client else '')
                     ) or {}
 
             if pr: