mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[extractor/rumble] Add HLS formats and extract more metadata (#5280)
Closes #5177, #5277 Authored by: flashdagger
This commit is contained in:
		| @@ -2399,40 +2399,6 @@ class GenericIE(InfoExtractor): | |||||||
|                 'upload_date': '20210111', |                 'upload_date': '20210111', | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         { |  | ||||||
|             'note': 'Rumble embed', |  | ||||||
|             'url': 'https://rumble.com/vdmum1-moose-the-dog-helps-girls-dig-a-snow-fort.html', |  | ||||||
|             'md5': '53af34098a7f92c4e51cf0bd1c33f009', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': 'vb0ofn', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'timestamp': 1612662578, |  | ||||||
|                 'uploader': 'LovingMontana', |  | ||||||
|                 'channel': 'LovingMontana', |  | ||||||
|                 'upload_date': '20210207', |  | ||||||
|                 'title': 'Winter-loving dog helps girls dig a snow fort ', |  | ||||||
|                 'channel_url': 'https://rumble.com/c/c-546523', |  | ||||||
|                 'thumbnail': 'https://sp.rmbl.ws/s8/1/5/f/x/x/5fxxb.OvCc.1-small-Moose-The-Dog-Helps-Girls-D.jpg', |  | ||||||
|                 'duration': 103, |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             'note': 'Rumble JS embed', |  | ||||||
|             'url': 'https://therightscoop.com/what-does-9-plus-1-plus-1-equal-listen-to-this-audio-of-attempted-kavanaugh-assassins-call-and-youll-get-it', |  | ||||||
|             'md5': '4701209ac99095592e73dbba21889690', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': 'v15eqxl', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'channel': 'Mr Producer Media', |  | ||||||
|                 'duration': 92, |  | ||||||
|                 'title': '911 Audio From The Man Who Wanted To Kill Supreme Court Justice Kavanaugh', |  | ||||||
|                 'channel_url': 'https://rumble.com/c/RichSementa', |  | ||||||
|                 'thumbnail': 'https://sp.rmbl.ws/s8/1/P/j/f/A/PjfAe.OvCc-small-911-Audio-From-The-Man-Who-.jpg', |  | ||||||
|                 'timestamp': 1654892716, |  | ||||||
|                 'uploader': 'Mr Producer Media', |  | ||||||
|                 'upload_date': '20220610', |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         { |         { | ||||||
|             'note': 'JSON LD with multiple @type', |             'note': 'JSON LD with multiple @type', | ||||||
|             'url': 'https://www.nu.nl/280161/video/hoe-een-bladvlo-dit-verwoestende-japanse-onkruid-moet-vernietigen.html', |             'url': 'https://www.nu.nl/280161/video/hoe-een-bladvlo-dit-verwoestende-japanse-onkruid-moet-vernietigen.html', | ||||||
|   | |||||||
| @@ -2,12 +2,11 @@ import itertools | |||||||
| import re | import re | ||||||
| 
 | 
 | ||||||
| from .common import InfoExtractor | from .common import InfoExtractor | ||||||
| from ..compat import compat_str, compat_HTTPError | from ..compat import compat_HTTPError | ||||||
| from ..utils import ( | from ..utils import ( | ||||||
|     determine_ext, |  | ||||||
|     int_or_none, |     int_or_none, | ||||||
|     parse_iso8601, |     parse_iso8601, | ||||||
|     try_get, |     traverse_obj, | ||||||
|     unescapeHTML, |     unescapeHTML, | ||||||
|     ExtractorError, |     ExtractorError, | ||||||
| ) | ) | ||||||
| @@ -30,6 +29,7 @@ class RumbleEmbedIE(InfoExtractor): | |||||||
|             'thumbnail': 'https://sp.rmbl.ws/s8/1/5/M/z/1/5Mz1a.OvCc-small-WMAR-2-News-Latest-Headline.jpg', |             'thumbnail': 'https://sp.rmbl.ws/s8/1/5/M/z/1/5Mz1a.OvCc-small-WMAR-2-News-Latest-Headline.jpg', | ||||||
|             'duration': 234, |             'duration': 234, | ||||||
|             'uploader': 'WMAR', |             'uploader': 'WMAR', | ||||||
|  |             'live_status': 'not_live', | ||||||
|         } |         } | ||||||
|     }, { |     }, { | ||||||
|         'url': 'https://rumble.com/embed/vslb7v', |         'url': 'https://rumble.com/embed/vslb7v', | ||||||
| @@ -45,12 +45,110 @@ class RumbleEmbedIE(InfoExtractor): | |||||||
|             'thumbnail': 'https://sp.rmbl.ws/s8/6/7/i/9/h/7i9hd.OvCc.jpg', |             'thumbnail': 'https://sp.rmbl.ws/s8/6/7/i/9/h/7i9hd.OvCc.jpg', | ||||||
|             'duration': 901, |             'duration': 901, | ||||||
|             'uploader': 'CTNews', |             'uploader': 'CTNews', | ||||||
|  |             'live_status': 'not_live', | ||||||
|         } |         } | ||||||
|  |     }, { | ||||||
|  |         'url': 'https://rumble.com/embed/vunh1h', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': 'vunh1h', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': '‘Gideon, op zoek naar de waarheid’ including ENG SUBS', | ||||||
|  |             'timestamp': 1647197663, | ||||||
|  |             'upload_date': '20220313', | ||||||
|  |             'channel_url': 'https://rumble.com/user/BLCKBX', | ||||||
|  |             'channel': 'BLCKBX', | ||||||
|  |             'thumbnail': r're:https://.+\.jpg', | ||||||
|  |             'duration': 5069, | ||||||
|  |             'uploader': 'BLCKBX', | ||||||
|  |             'live_status': 'not_live', | ||||||
|  |             'subtitles': { | ||||||
|  |                 'en': [ | ||||||
|  |                     { | ||||||
|  |                         'url': r're:https://.+\.vtt', | ||||||
|  |                         'name': 'English', | ||||||
|  |                         'ext': 'vtt' | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |         }, | ||||||
|  |         'params': {'skip_download': True} | ||||||
|  |     }, { | ||||||
|  |         'url': 'https://rumble.com/embed/v1essrt', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': 'v1essrt', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'startswith:lofi hip hop radio - beats to relax/study', | ||||||
|  |             'timestamp': 1661519399, | ||||||
|  |             'upload_date': '20220826', | ||||||
|  |             'channel_url': 'https://rumble.com/c/LofiGirl', | ||||||
|  |             'channel': 'Lofi Girl', | ||||||
|  |             'thumbnail': r're:https://.+\.jpg', | ||||||
|  |             'duration': None, | ||||||
|  |             'uploader': 'Lofi Girl', | ||||||
|  |             'live_status': 'is_live', | ||||||
|  |         }, | ||||||
|  |         'params': {'skip_download': True} | ||||||
|  |     }, { | ||||||
|  |         'url': 'https://rumble.com/embed/v1amumr', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': 'v1amumr', | ||||||
|  |             'ext': 'webm', | ||||||
|  |             'fps': 60, | ||||||
|  |             'title': 'Turning Point USA 2022 Student Action Summit DAY 1  - Rumble Exclusive Live', | ||||||
|  |             'timestamp': 1658518457, | ||||||
|  |             'upload_date': '20220722', | ||||||
|  |             'channel_url': 'https://rumble.com/c/RumbleEvents', | ||||||
|  |             'channel': 'Rumble Events', | ||||||
|  |             'thumbnail': r're:https://.+\.jpg', | ||||||
|  |             'duration': 16427, | ||||||
|  |             'uploader': 'Rumble Events', | ||||||
|  |             'live_status': 'was_live', | ||||||
|  |         }, | ||||||
|  |         'params': {'skip_download': True} | ||||||
|     }, { |     }, { | ||||||
|         'url': 'https://rumble.com/embed/ufe9n.v5pv5f', |         'url': 'https://rumble.com/embed/ufe9n.v5pv5f', | ||||||
|         'only_matching': True, |         'only_matching': True, | ||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
|  |     _WEBPAGE_TESTS = [ | ||||||
|  |         { | ||||||
|  |             'note': 'Rumble embed', | ||||||
|  |             'url': 'https://rumble.com/vdmum1-moose-the-dog-helps-girls-dig-a-snow-fort.html', | ||||||
|  |             'md5': '53af34098a7f92c4e51cf0bd1c33f009', | ||||||
|  |             'info_dict': { | ||||||
|  |                 'id': 'vb0ofn', | ||||||
|  |                 'ext': 'mp4', | ||||||
|  |                 'timestamp': 1612662578, | ||||||
|  |                 'uploader': 'LovingMontana', | ||||||
|  |                 'channel': 'LovingMontana', | ||||||
|  |                 'upload_date': '20210207', | ||||||
|  |                 'title': 'Winter-loving dog helps girls dig a snow fort ', | ||||||
|  |                 'channel_url': 'https://rumble.com/c/c-546523', | ||||||
|  |                 'thumbnail': 'https://sp.rmbl.ws/s8/1/5/f/x/x/5fxxb.OvCc.1-small-Moose-The-Dog-Helps-Girls-D.jpg', | ||||||
|  |                 'duration': 103, | ||||||
|  |                 'live_status': 'not_live', | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             'note': 'Rumble JS embed', | ||||||
|  |             'url': 'https://therightscoop.com/what-does-9-plus-1-plus-1-equal-listen-to-this-audio-of-attempted-kavanaugh-assassins-call-and-youll-get-it', | ||||||
|  |             'md5': '4701209ac99095592e73dbba21889690', | ||||||
|  |             'info_dict': { | ||||||
|  |                 'id': 'v15eqxl', | ||||||
|  |                 'ext': 'mp4', | ||||||
|  |                 'channel': 'Mr Producer Media', | ||||||
|  |                 'duration': 92, | ||||||
|  |                 'title': '911 Audio From The Man Who Wanted To Kill Supreme Court Justice Kavanaugh', | ||||||
|  |                 'channel_url': 'https://rumble.com/c/RichSementa', | ||||||
|  |                 'thumbnail': 'https://sp.rmbl.ws/s8/1/P/j/f/A/PjfAe.OvCc-small-911-Audio-From-The-Man-Who-.jpg', | ||||||
|  |                 'timestamp': 1654892716, | ||||||
|  |                 'uploader': 'Mr Producer Media', | ||||||
|  |                 'upload_date': '20220610', | ||||||
|  |                 'live_status': 'not_live', | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def _extract_embed_urls(cls, url, webpage): |     def _extract_embed_urls(cls, url, webpage): | ||||||
|         embeds = tuple(super()._extract_embed_urls(url, webpage)) |         embeds = tuple(super()._extract_embed_urls(url, webpage)) | ||||||
| @@ -62,26 +160,48 @@ class RumbleEmbedIE(InfoExtractor): | |||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         video_id = self._match_id(url) |         video_id = self._match_id(url) | ||||||
|         video = self._download_json( |         video = self._download_json( | ||||||
|             'https://rumble.com/embedJS/', video_id, |             'https://rumble.com/embedJS/u3/', video_id, | ||||||
|             query={'request': 'video', 'v': video_id}) |             query={'request': 'video', 'ver': 2, 'v': video_id}) | ||||||
|         title = unescapeHTML(video['title']) | 
 | ||||||
|  |         sys_msg = traverse_obj(video, ('sys', 'msg')) | ||||||
|  |         if sys_msg: | ||||||
|  |             self.report_warning(sys_msg, video_id=video_id) | ||||||
|  | 
 | ||||||
|  |         if video.get('live') == 0: | ||||||
|  |             live_status = 'not_live' if video.get('livestream_has_dvr') is None else 'was_live' | ||||||
|  |         elif video.get('live') == 1: | ||||||
|  |             live_status = 'is_upcoming' if video.get('livestream_has_dvr') else 'was_live' | ||||||
|  |         elif video.get('live') == 2: | ||||||
|  |             live_status = 'is_live' | ||||||
|  |         else: | ||||||
|  |             live_status = None | ||||||
| 
 | 
 | ||||||
|         formats = [] |         formats = [] | ||||||
|         for height, ua in (video.get('ua') or {}).items(): |         for ext, ext_info in (video.get('ua') or {}).items(): | ||||||
|             for i in range(2): |             for height, video_info in (ext_info or {}).items(): | ||||||
|                 f_url = try_get(ua, lambda x: x[i], compat_str) |                 meta = video_info.get('meta') or {} | ||||||
|                 if f_url: |                 if not video_info.get('url'): | ||||||
|                     ext = determine_ext(f_url) |                     continue | ||||||
|                     f = { |                 if ext == 'hls': | ||||||
|  |                     if meta.get('live') is True and video.get('live') == 1: | ||||||
|  |                         live_status = 'post_live' | ||||||
|  |                     formats.extend(self._extract_m3u8_formats( | ||||||
|  |                         video_info['url'], video_id, | ||||||
|  |                         ext='mp4', m3u8_id='hls', fatal=False, live=live_status == 'is_live')) | ||||||
|  |                     continue | ||||||
|  |                 formats.append({ | ||||||
|                     'ext': ext, |                     'ext': ext, | ||||||
|  |                     'url': video_info['url'], | ||||||
|                     'format_id': '%s-%sp' % (ext, height), |                     'format_id': '%s-%sp' % (ext, height), | ||||||
|                     'height': int_or_none(height), |                     'height': int_or_none(height), | ||||||
|                         'url': f_url, |                     'fps': video.get('fps'), | ||||||
|                     } |                     **traverse_obj(meta, { | ||||||
|                     bitrate = try_get(ua, lambda x: x[i + 2]['bitrate']) |                         'tbr': 'bitrate', | ||||||
|                     if bitrate: |                         'filesize': 'size', | ||||||
|                         f['tbr'] = int_or_none(bitrate) |                         'width': 'w', | ||||||
|                     formats.append(f) |                         'height': 'h', | ||||||
|  |                     }, default={}) | ||||||
|  |                 }) | ||||||
|         self._sort_formats(formats) |         self._sort_formats(formats) | ||||||
| 
 | 
 | ||||||
|         subtitles = { |         subtitles = { | ||||||
| @@ -92,18 +212,27 @@ class RumbleEmbedIE(InfoExtractor): | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         author = video.get('author') or {} |         author = video.get('author') or {} | ||||||
|  |         thumbnails = traverse_obj(video, ('t', ..., {'url': 'i', 'width': 'w', 'height': 'h'})) | ||||||
|  |         if not thumbnails and video.get('i'): | ||||||
|  |             thumbnails = [{'url': video['i']}] | ||||||
|  | 
 | ||||||
|  |         if live_status in {'is_live', 'post_live'}: | ||||||
|  |             duration = None | ||||||
|  |         else: | ||||||
|  |             duration = int_or_none(video.get('duration')) | ||||||
| 
 | 
 | ||||||
|         return { |         return { | ||||||
|             'id': video_id, |             'id': video_id, | ||||||
|             'title': title, |             'title': unescapeHTML(video.get('title')), | ||||||
|             'formats': formats, |             'formats': formats, | ||||||
|             'subtitles': subtitles, |             'subtitles': subtitles, | ||||||
|             'thumbnail': video.get('i'), |             'thumbnails': thumbnails, | ||||||
|             'timestamp': parse_iso8601(video.get('pubDate')), |             'timestamp': parse_iso8601(video.get('pubDate')), | ||||||
|             'channel': author.get('name'), |             'channel': author.get('name'), | ||||||
|             'channel_url': author.get('url'), |             'channel_url': author.get('url'), | ||||||
|             'duration': int_or_none(video.get('duration')), |             'duration': duration, | ||||||
|             'uploader': author.get('name'), |             'uploader': author.get('name'), | ||||||
|  |             'live_status': live_status, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @@ -118,7 +247,7 @@ class RumbleChannelIE(InfoExtractor): | |||||||
|         }, |         }, | ||||||
|     }, { |     }, { | ||||||
|         'url': 'https://rumble.com/user/goldenpoodleharleyeuna', |         'url': 'https://rumble.com/user/goldenpoodleharleyeuna', | ||||||
|         'playlist_count': 4, |         'playlist_mincount': 4, | ||||||
|         'info_dict': { |         'info_dict': { | ||||||
|             'id': 'goldenpoodleharleyeuna', |             'id': 'goldenpoodleharleyeuna', | ||||||
|         }, |         }, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 MMM
					MMM