From 1cdf69c57e8950b07f24a6ebc6dfb0c6b1e83274 Mon Sep 17 00:00:00 2001 From: mpeter50 <83356418+mpeter50@users.noreply.github.com> Date: Sat, 30 Jul 2022 16:11:27 +0000 Subject: [PATCH] [extractor/twitch] Extract chapters for single chapter VODs (#4453) Closes #4421 Authored by: mpeter50 --- yt_dlp/extractor/twitch.py | 47 ++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/yt_dlp/extractor/twitch.py b/yt_dlp/extractor/twitch.py index 32cfd8a08d..028e7a1e89 100644 --- a/yt_dlp/extractor/twitch.py +++ b/yt_dlp/extractor/twitch.py @@ -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, }