mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 06:35:12 +00:00 
			
		
		
		
	[twitch] fix clip extraction(closes #23375)
This commit is contained in:
		| @@ -17,12 +17,10 @@ from ..compat import ( | ||||
| from ..utils import ( | ||||
|     clean_html, | ||||
|     ExtractorError, | ||||
|     float_or_none, | ||||
|     int_or_none, | ||||
|     orderedSet, | ||||
|     parse_duration, | ||||
|     parse_iso8601, | ||||
|     qualities, | ||||
|     try_get, | ||||
|     unified_timestamp, | ||||
|     update_url_query, | ||||
| @@ -676,63 +674,81 @@ class TwitchClipsIE(TwitchBaseIE): | ||||
|     def _real_extract(self, url): | ||||
|         video_id = self._match_id(url) | ||||
|  | ||||
|         status = self._download_json( | ||||
|             'https://clips.twitch.tv/api/v2/clips/%s/status' % video_id, | ||||
|             video_id) | ||||
|         clip = self._download_json( | ||||
|             'https://gql.twitch.tv/gql', video_id, data=json.dumps({ | ||||
|                 'query': '''{ | ||||
|   clip(slug: "%s") { | ||||
|     broadcaster { | ||||
|       displayName | ||||
|     } | ||||
|     createdAt | ||||
|     curator { | ||||
|       displayName | ||||
|       id | ||||
|     } | ||||
|     durationSeconds | ||||
|     id | ||||
|     tiny: thumbnailURL(width: 86, height: 45) | ||||
|     small: thumbnailURL(width: 260, height: 147) | ||||
|     medium: thumbnailURL(width: 480, height: 272) | ||||
|     title | ||||
|     videoQualities { | ||||
|       frameRate | ||||
|       quality | ||||
|       sourceURL | ||||
|     } | ||||
|     viewCount | ||||
|   } | ||||
| }''' % video_id, | ||||
|             }).encode(), headers={ | ||||
|                 'Client-ID': self._CLIENT_ID, | ||||
|             })['data']['clip'] | ||||
|  | ||||
|         if not clip: | ||||
|             raise ExtractorError( | ||||
|                 'This clip is no longer available', expected=True) | ||||
|  | ||||
|         formats = [] | ||||
|  | ||||
|         for option in status['quality_options']: | ||||
|         for option in clip.get('videoQualities', []): | ||||
|             if not isinstance(option, dict): | ||||
|                 continue | ||||
|             source = url_or_none(option.get('source')) | ||||
|             source = url_or_none(option.get('sourceURL')) | ||||
|             if not source: | ||||
|                 continue | ||||
|             formats.append({ | ||||
|                 'url': source, | ||||
|                 'format_id': option.get('quality'), | ||||
|                 'height': int_or_none(option.get('quality')), | ||||
|                 'fps': int_or_none(option.get('frame_rate')), | ||||
|                 'fps': int_or_none(option.get('frameRate')), | ||||
|             }) | ||||
|  | ||||
|         self._sort_formats(formats) | ||||
|  | ||||
|         info = { | ||||
|         thumbnails = [] | ||||
|         for thumbnail_id in ('tiny', 'small', 'medium'): | ||||
|             thumbnail_url = clip.get(thumbnail_id) | ||||
|             if not thumbnail_url: | ||||
|                 continue | ||||
|             thumb = { | ||||
|                 'id': thumbnail_id, | ||||
|                 'url': thumbnail_url, | ||||
|             } | ||||
|             mobj = re.search(r'-(\d+)x(\d+)\.', thumbnail_url) | ||||
|             if mobj: | ||||
|                 thumb.update({ | ||||
|                     'height': int(mobj.group(2)), | ||||
|                     'width': int(mobj.group(1)), | ||||
|                 }) | ||||
|             thumbnails.append(thumb) | ||||
|  | ||||
|         return { | ||||
|             'id': clip.get('id') or video_id, | ||||
|             'title': clip.get('title') or video_id, | ||||
|             'formats': formats, | ||||
|             'duration': int_or_none(clip.get('durationSeconds')), | ||||
|             'views': int_or_none(clip.get('viewCount')), | ||||
|             'timestamp': unified_timestamp(clip.get('createdAt')), | ||||
|             'thumbnails': thumbnails, | ||||
|             'creator': try_get(clip, lambda x: x['broadcaster']['displayName'], compat_str), | ||||
|             'uploader': try_get(clip, lambda x: x['curator']['displayName'], compat_str), | ||||
|             'uploader_id': try_get(clip, lambda x: x['curator']['id'], compat_str), | ||||
|         } | ||||
|  | ||||
|         clip = self._call_api( | ||||
|             'kraken/clips/%s' % video_id, video_id, fatal=False, headers={ | ||||
|                 'Accept': 'application/vnd.twitchtv.v5+json', | ||||
|             }) | ||||
|  | ||||
|         if clip: | ||||
|             quality_key = qualities(('tiny', 'small', 'medium')) | ||||
|             thumbnails = [] | ||||
|             thumbnails_dict = clip.get('thumbnails') | ||||
|             if isinstance(thumbnails_dict, dict): | ||||
|                 for thumbnail_id, thumbnail_url in thumbnails_dict.items(): | ||||
|                     thumbnails.append({ | ||||
|                         'id': thumbnail_id, | ||||
|                         'url': thumbnail_url, | ||||
|                         'preference': quality_key(thumbnail_id), | ||||
|                     }) | ||||
|  | ||||
|             info.update({ | ||||
|                 'id': clip.get('tracking_id') or video_id, | ||||
|                 'title': clip.get('title') or video_id, | ||||
|                 'duration': float_or_none(clip.get('duration')), | ||||
|                 'views': int_or_none(clip.get('views')), | ||||
|                 'timestamp': unified_timestamp(clip.get('created_at')), | ||||
|                 'thumbnails': thumbnails, | ||||
|                 'creator': try_get(clip, lambda x: x['broadcaster']['display_name'], compat_str), | ||||
|                 'uploader': try_get(clip, lambda x: x['curator']['display_name'], compat_str), | ||||
|                 'uploader_id': try_get(clip, lambda x: x['curator']['id'], compat_str), | ||||
|             }) | ||||
|         else: | ||||
|             info.update({ | ||||
|                 'title': video_id, | ||||
|                 'id': video_id, | ||||
|             }) | ||||
|  | ||||
|         return info | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Remita Amine
					Remita Amine