]> jfr.im git - yt-dlp.git/commitdiff
[extractor/twitch] Extract chapters for single chapter VODs (#4453)
authormpeter50 <redacted>
Sat, 30 Jul 2022 16:11:27 +0000 (16:11 +0000)
committerGitHub <redacted>
Sat, 30 Jul 2022 16:11:27 +0000 (21:41 +0530)
Closes #4421
Authored by: mpeter50

yt_dlp/extractor/twitch.py

index 32cfd8a08d5324e7ab37f31f616cfd795163cdbe..028e7a1e892359e5a3501bfa956d5b0ba33406db 100644 (file)
@@ -205,7 +205,13 @@ class TwitchVodIE(TwitchBaseIE):
             'uploader_id': 'riotgames',
             'view_count': int,
             'start_time': 310,
-            'chapters': [],
+            'chapters': [
+                {
+                    'start_time': 0,
+                    'end_time': 17208,
+                    'title': 'League of Legends'
+                }
+            ],
             'live_status': 'was_live',
         },
         'params': {
@@ -322,6 +328,33 @@ class TwitchVodIE(TwitchBaseIE):
             'format': 'mhtml',
             'skip_download': True
         }
+    }, {
+        'note': 'VOD with single chapter',
+        'url': 'https://www.twitch.tv/videos/1536751224',
+        'info_dict': {
+            'id': 'v1536751224',
+            'ext': 'mp4',
+            'title': 'Porter Robinson Star Guardian Stream Tour with LilyPichu',
+            'duration': 8353,
+            'uploader': 'Riot Games',
+            'uploader_id': 'riotgames',
+            'timestamp': 1658267731,
+            'upload_date': '20220719',
+            'chapters': [
+                {
+                    'start_time': 0,
+                    'end_time': 8353,
+                    'title': 'League of Legends'
+                }
+            ],
+            'live_status': 'was_live',
+            'thumbnail': r're:^https?://.*\.jpg$',
+            'view_count': int,
+        },
+        'params': {
+            'skip_download': True
+        },
+        'expected_warnings': ['Unable to download JSON metadata: HTTP Error 403: Forbidden']
     }]
 
     def _download_info(self, item_id):
@@ -393,8 +426,14 @@ def _extract_info(self, info):
             'was_live': True,
         }
 
-    def _extract_moments(self, info, item_id):
-        for moment in info.get('moments') or []:
+    def _extract_chapters(self, info, item_id):
+        if not info.get('moments'):
+            game = traverse_obj(info, ('game', 'displayName'))
+            if game:
+                yield {'title': game}
+            return
+
+        for moment in info['moments']:
             start_time = int_or_none(moment.get('positionMilliseconds'), 1000)
             duration = int_or_none(moment.get('durationMilliseconds'), 1000)
             name = str_or_none(moment.get('description'))
@@ -433,7 +472,7 @@ def _extract_info_gql(self, info, item_id):
             'uploader_id': try_get(info, lambda x: x['owner']['login'], compat_str),
             'timestamp': unified_timestamp(info.get('publishedAt')),
             'view_count': int_or_none(info.get('viewCount')),
-            'chapters': list(self._extract_moments(info, item_id)),
+            'chapters': list(self._extract_chapters(info, item_id)),
             'is_live': is_live,
             'was_live': True,
         }