mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[extractor/brightcove] Add BrightcoveNewBaseIE and fix embed extraction (#5558)
				
					
				
			* Move Brightcove embed extraction and tests into the IEs
* Split `BrightcoveNewBaseIE` from `BrightcoveNewIE`
* Fix bug in ade1fa70cb with the "wrong" spelling of `referrer` being smuggled
Closes #5539
			
			
This commit is contained in:
		| @@ -1,8 +1,8 @@ | |||||||
| from .brightcove import BrightcoveNewIE | from .brightcove import BrightcoveNewBaseIE | ||||||
| from ..utils import extract_attributes | from ..utils import extract_attributes | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BandaiChannelIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE | class BandaiChannelIE(BrightcoveNewBaseIE): | ||||||
|     IE_NAME = 'bandaichannel' |     IE_NAME = 'bandaichannel' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?b-ch\.com/titles/(?P<id>\d+/\d+)' |     _VALID_URL = r'https?://(?:www\.)?b-ch\.com/titles/(?P<id>\d+/\d+)' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
| @@ -145,6 +145,159 @@ class BrightcoveLegacyIE(InfoExtractor): | |||||||
|         } |         } | ||||||
|     ] |     ] | ||||||
| 
 | 
 | ||||||
|  |     _WEBPAGE_TESTS = [{ | ||||||
|  |         # embedded brightcove video | ||||||
|  |         # it also tests brightcove videos that need to set the 'Referer' | ||||||
|  |         # in the http requests | ||||||
|  |         'url': 'http://www.bfmtv.com/video/bfmbusiness/cours-bourse/cours-bourse-l-analyse-technique-154522/', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '2765128793001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Le cours de bourse : l’analyse technique', | ||||||
|  |             'description': 'md5:7e9ad046e968cb2d1114004aba466fd9', | ||||||
|  |             'uploader': 'BFM BUSINESS', | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             'skip_download': True, | ||||||
|  |         }, | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # embedded with itemprop embedURL and video id spelled as `idVideo` | ||||||
|  |         'url': 'http://bfmbusiness.bfmtv.com/mediaplayer/chroniques/olivier-delamarche/', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '5255628253001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'md5:37c519b1128915607601e75a87995fc0', | ||||||
|  |             'description': 'md5:37f7f888b434bb8f8cc8dbd4f7a4cf26', | ||||||
|  |             'uploader': 'BFM BUSINESS', | ||||||
|  |             'uploader_id': '876450612001', | ||||||
|  |             'timestamp': 1482255315, | ||||||
|  |             'upload_date': '20161220', | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             'skip_download': True, | ||||||
|  |         }, | ||||||
|  |         'skip': 'Redirects, page gone', | ||||||
|  |     }, { | ||||||
|  |         # https://github.com/ytdl-org/youtube-dl/issues/2253 | ||||||
|  |         'url': 'http://bcove.me/i6nfkrc3', | ||||||
|  |         'md5': '0ba9446db037002366bab3b3eb30c88c', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '3101154703001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Still no power', | ||||||
|  |             'uploader': 'thestar.com', | ||||||
|  |             'description': 'Mississauga resident David Farmer is still out of power as a result of the ice storm a month ago. To keep the house warm, Farmer cuts wood from his property for a wood burning stove downstairs.', | ||||||
|  |         }, | ||||||
|  |         'skip': 'video gone', | ||||||
|  |     }, { | ||||||
|  |         # https://github.com/ytdl-org/youtube-dl/issues/3541 | ||||||
|  |         'url': 'http://www.kijk.nl/sbs6/leermijvrouwenkennen/videos/jqMiXKAYan2S/aflevering-1', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '3866516442001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Leer mij vrouwen kennen: Aflevering 1', | ||||||
|  |             'description': 'Leer mij vrouwen kennen: Aflevering 1', | ||||||
|  |             'uploader': 'SBS Broadcasting', | ||||||
|  |         }, | ||||||
|  |         'skip': 'Restricted to Netherlands, 404 Not Found', | ||||||
|  |         'params': { | ||||||
|  |             'skip_download': True,  # m3u8 download | ||||||
|  |         }, | ||||||
|  |     }, { | ||||||
|  |         # Brightcove video in <iframe> | ||||||
|  |         'url': 'http://www.un.org/chinese/News/story.asp?NewsID=27724', | ||||||
|  |         'md5': '36d74ef5e37c8b4a2ce92880d208b968', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '5360463607001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': '叙利亚失明儿童在废墟上演唱《心跳》  呼吁获得正常童年生活', | ||||||
|  |             'description': '联合国儿童基金会中东和北非区域大使、作曲家扎德·迪拉尼(Zade Dirani)在3月15日叙利亚冲突爆发7周年纪念日之际发布了为叙利亚谱写的歌曲《心跳》(HEARTBEAT),为受到六年冲突影响的叙利亚儿童发出强烈呐喊,呼吁世界做出共同努力,使叙利亚儿童重新获得享有正常童年生活的权利。', | ||||||
|  |             'uploader': 'United Nations', | ||||||
|  |             'uploader_id': '1362235914001', | ||||||
|  |             'timestamp': 1489593889, | ||||||
|  |             'upload_date': '20170315', | ||||||
|  |         }, | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # Brightcove with UUID in videoPlayer | ||||||
|  |         'url': 'http://www8.hp.com/cn/zh/home.html', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '5255815316001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Sprocket Video - China', | ||||||
|  |             'description': 'Sprocket Video - China', | ||||||
|  |             'uploader': 'HP-Video Gallery', | ||||||
|  |             'timestamp': 1482263210, | ||||||
|  |             'upload_date': '20161220', | ||||||
|  |             'uploader_id': '1107601872001', | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             'skip_download': True,  # m3u8 download | ||||||
|  |         }, | ||||||
|  |         'skip': 'video rotates...weekly?', | ||||||
|  |     }, { | ||||||
|  |         # Multiple brightcove videos | ||||||
|  |         # https://github.com/ytdl-org/youtube-dl/issues/2283 | ||||||
|  |         'url': 'http://www.newyorker.com/online/blogs/newsdesk/2014/01/always-never-nuclear-command-and-control.html', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': 'always-never', | ||||||
|  |             'title': 'Always / Never - The New Yorker', | ||||||
|  |         }, | ||||||
|  |         'playlist_count': 3, | ||||||
|  |         'params': { | ||||||
|  |             'extract_flat': False, | ||||||
|  |             'skip_download': True, | ||||||
|  |         }, | ||||||
|  |         'skip': 'Redirects, page gone', | ||||||
|  |     }, { | ||||||
|  |         # BrightcoveInPageEmbed embed | ||||||
|  |         'url': 'http://www.geekandsundry.com/tabletop-bonus-wils-final-thoughts-on-dread/', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '4238694884001', | ||||||
|  |             'ext': 'flv', | ||||||
|  |             'title': 'Tabletop: Dread, Last Thoughts', | ||||||
|  |             'description': 'Tabletop: Dread, Last Thoughts', | ||||||
|  |             'duration': 51690, | ||||||
|  |         }, | ||||||
|  |         'skip': 'Redirects, page gone', | ||||||
|  |     }, { | ||||||
|  |         # Brightcove embed, with no valid 'renditions' but valid 'IOSRenditions' | ||||||
|  |         # This video can't be played in browsers if Flash disabled and UA set to iPhone, which is actually a false alarm | ||||||
|  |         'url': 'https://dl.dropboxusercontent.com/u/29092637/interview.html', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '4785848093001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'The Cardinal Pell Interview', | ||||||
|  |             'description': 'Sky News Contributor Andrew Bolt interviews George Pell in Rome, following the Cardinal\'s evidence before the Royal Commission into Child Abuse. ', | ||||||
|  |             'uploader': 'GlobeCast Australia - GlobeStream', | ||||||
|  |             'uploader_id': '2733773828001', | ||||||
|  |             'upload_date': '20160304', | ||||||
|  |             'timestamp': 1457083087, | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             # m3u8 downloads | ||||||
|  |             'skip_download': True, | ||||||
|  |         }, | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # Brightcove embed with whitespace around attribute names | ||||||
|  |         'url': 'http://www.stack.com/video/3167554373001/learn-to-hit-open-three-pointers-with-damian-lillard-s-baseline-drift-drill', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '3167554373001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': "Learn to Hit Open Three-Pointers With Damian Lillard's Baseline Drift Drill", | ||||||
|  |             'description': 'md5:57bacb0e0f29349de4972bfda3191713', | ||||||
|  |             'uploader_id': '1079349493', | ||||||
|  |             'upload_date': '20140207', | ||||||
|  |             'timestamp': 1391810548, | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             'skip_download': True, | ||||||
|  |         }, | ||||||
|  |         'skip': '410 Gone', | ||||||
|  |     }] | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def _build_brightcove_url(cls, object_str): |     def _build_brightcove_url(cls, object_str): | ||||||
|         """ |         """ | ||||||
| @@ -281,6 +434,11 @@ class BrightcoveLegacyIE(InfoExtractor): | |||||||
|         return [src for _, src in re.findall( |         return [src for _, src in re.findall( | ||||||
|             r'<iframe[^>]+src=([\'"])((?:https?:)?//link\.brightcove\.com/services/player/(?!\1).+)\1', webpage)] |             r'<iframe[^>]+src=([\'"])((?:https?:)?//link\.brightcove\.com/services/player/(?!\1).+)\1', webpage)] | ||||||
| 
 | 
 | ||||||
|  |     def _extract_from_webpage(self, url, webpage): | ||||||
|  |         bc_urls = self._extract_brightcove_urls(webpage) | ||||||
|  |         for bc_url in bc_urls: | ||||||
|  |             yield self.url_result(smuggle_url(bc_url, {'Referer': url}), BrightcoveLegacyIE) | ||||||
|  | 
 | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         url, smuggled_data = unsmuggle_url(url, {}) |         url, smuggled_data = unsmuggle_url(url, {}) | ||||||
| 
 | 
 | ||||||
| @@ -336,136 +494,7 @@ class BrightcoveLegacyIE(InfoExtractor): | |||||||
|         raise UnsupportedError(url) |         raise UnsupportedError(url) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class BrightcoveNewIE(AdobePassIE): | class BrightcoveNewBaseIE(AdobePassIE): | ||||||
|     IE_NAME = 'brightcove:new' |  | ||||||
|     _VALID_URL = r'https?://players\.brightcove\.net/(?P<account_id>\d+)/(?P<player_id>[^/]+)_(?P<embed>[^/]+)/index\.html\?.*(?P<content_type>video|playlist)Id=(?P<video_id>\d+|ref:[^&]+)' |  | ||||||
|     _TESTS = [{ |  | ||||||
|         'url': 'http://players.brightcove.net/929656772001/e41d32dc-ec74-459e-a845-6c69f7b724ea_default/index.html?videoId=4463358922001', |  | ||||||
|         'md5': 'c8100925723840d4b0d243f7025703be', |  | ||||||
|         'info_dict': { |  | ||||||
|             'id': '4463358922001', |  | ||||||
|             'ext': 'mp4', |  | ||||||
|             'title': 'Meet the man behind Popcorn Time', |  | ||||||
|             'description': 'md5:eac376a4fe366edc70279bfb681aea16', |  | ||||||
|             'duration': 165.768, |  | ||||||
|             'timestamp': 1441391203, |  | ||||||
|             'upload_date': '20150904', |  | ||||||
|             'uploader_id': '929656772001', |  | ||||||
|             'formats': 'mincount:20', |  | ||||||
|         }, |  | ||||||
|     }, { |  | ||||||
|         # with rtmp streams |  | ||||||
|         'url': 'http://players.brightcove.net/4036320279001/5d112ed9-283f-485f-a7f9-33f42e8bc042_default/index.html?videoId=4279049078001', |  | ||||||
|         'info_dict': { |  | ||||||
|             'id': '4279049078001', |  | ||||||
|             'ext': 'mp4', |  | ||||||
|             'title': 'Titansgrave: Chapter 0', |  | ||||||
|             'description': 'Titansgrave: Chapter 0', |  | ||||||
|             'duration': 1242.058, |  | ||||||
|             'timestamp': 1433556729, |  | ||||||
|             'upload_date': '20150606', |  | ||||||
|             'uploader_id': '4036320279001', |  | ||||||
|             'formats': 'mincount:39', |  | ||||||
|         }, |  | ||||||
|         'params': { |  | ||||||
|             # m3u8 download |  | ||||||
|             'skip_download': True, |  | ||||||
|         } |  | ||||||
|     }, { |  | ||||||
|         # playlist stream |  | ||||||
|         'url': 'https://players.brightcove.net/1752604059001/S13cJdUBz_default/index.html?playlistId=5718313430001', |  | ||||||
|         'info_dict': { |  | ||||||
|             'id': '5718313430001', |  | ||||||
|             'title': 'No Audio Playlist', |  | ||||||
|         }, |  | ||||||
|         'playlist_count': 7, |  | ||||||
|         'params': { |  | ||||||
|             # m3u8 download |  | ||||||
|             'skip_download': True, |  | ||||||
|         } |  | ||||||
|     }, { |  | ||||||
|         'url': 'http://players.brightcove.net/5690807595001/HyZNerRl7_default/index.html?playlistId=5743160747001', |  | ||||||
|         'only_matching': True, |  | ||||||
|     }, { |  | ||||||
|         # ref: prefixed video id |  | ||||||
|         'url': 'http://players.brightcove.net/3910869709001/21519b5c-4b3b-4363-accb-bdc8f358f823_default/index.html?videoId=ref:7069442', |  | ||||||
|         'only_matching': True, |  | ||||||
|     }, { |  | ||||||
|         # non numeric ref: prefixed video id |  | ||||||
|         'url': 'http://players.brightcove.net/710858724001/default_default/index.html?videoId=ref:event-stream-356', |  | ||||||
|         'only_matching': True, |  | ||||||
|     }, { |  | ||||||
|         # unavailable video without message but with error_code |  | ||||||
|         'url': 'http://players.brightcove.net/1305187701/c832abfb-641b-44eb-9da0-2fe76786505f_default/index.html?videoId=4377407326001', |  | ||||||
|         'only_matching': True, |  | ||||||
|     }] |  | ||||||
| 
 |  | ||||||
|     @staticmethod |  | ||||||
|     def _extract_url(ie, webpage): |  | ||||||
|         urls = BrightcoveNewIE._extract_brightcove_urls(ie, webpage) |  | ||||||
|         return urls[0] if urls else None |  | ||||||
| 
 |  | ||||||
|     @staticmethod |  | ||||||
|     def _extract_brightcove_urls(ie, webpage): |  | ||||||
|         # Reference: |  | ||||||
|         # 1. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#setvideoiniframe |  | ||||||
|         # 2. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#tag |  | ||||||
|         # 3. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#setvideousingjavascript |  | ||||||
|         # 4. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/in-page-embed-player-implementation.html |  | ||||||
|         # 5. https://support.brightcove.com/en/video-cloud/docs/dynamically-assigning-videos-player |  | ||||||
| 
 |  | ||||||
|         entries = [] |  | ||||||
| 
 |  | ||||||
|         # Look for iframe embeds [1] |  | ||||||
|         for _, url in re.findall( |  | ||||||
|                 r'<iframe[^>]+src=(["\'])((?:https?:)?//players\.brightcove\.net/\d+/[^/]+/index\.html.+?)\1', webpage): |  | ||||||
|             entries.append(url if url.startswith('http') else 'http:' + url) |  | ||||||
| 
 |  | ||||||
|         # Look for <video> tags [2] and embed_in_page embeds [3] |  | ||||||
|         # [2] looks like: |  | ||||||
|         for video, script_tag, account_id, player_id, embed in re.findall( |  | ||||||
|                 r'''(?isx) |  | ||||||
|                     (<video(?:-js)?\s+[^>]*\bdata-video-id\s*=\s*['"]?[^>]+>) |  | ||||||
|                     (?:.*? |  | ||||||
|                         (<script[^>]+ |  | ||||||
|                             src=["\'](?:https?:)?//players\.brightcove\.net/ |  | ||||||
|                             (\d+)/([^/]+)_([^/]+)/index(?:\.min)?\.js |  | ||||||
|                         ) |  | ||||||
|                     )? |  | ||||||
|                 ''', webpage): |  | ||||||
|             attrs = extract_attributes(video) |  | ||||||
| 
 |  | ||||||
|             # According to examples from [4] it's unclear whether video id |  | ||||||
|             # may be optional and what to do when it is |  | ||||||
|             video_id = attrs.get('data-video-id') |  | ||||||
|             if not video_id: |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             account_id = account_id or attrs.get('data-account') |  | ||||||
|             if not account_id: |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             player_id = player_id or attrs.get('data-player') or 'default' |  | ||||||
|             embed = embed or attrs.get('data-embed') or 'default' |  | ||||||
| 
 |  | ||||||
|             bc_url = 'http://players.brightcove.net/%s/%s_%s/index.html?videoId=%s' % ( |  | ||||||
|                 account_id, player_id, embed, video_id) |  | ||||||
| 
 |  | ||||||
|             # Some brightcove videos may be embedded with video tag only and |  | ||||||
|             # without script tag or any mentioning of brightcove at all. Such |  | ||||||
|             # embeds are considered ambiguous since they are matched based only |  | ||||||
|             # on data-video-id and data-account attributes and in the wild may |  | ||||||
|             # not be brightcove embeds at all. Let's check reconstructed |  | ||||||
|             # brightcove URLs in case of such embeds and only process valid |  | ||||||
|             # ones. By this we ensure there is indeed a brightcove embed. |  | ||||||
|             if not script_tag and not ie._is_valid_url( |  | ||||||
|                     bc_url, video_id, 'possible brightcove video'): |  | ||||||
|                 continue |  | ||||||
| 
 |  | ||||||
|             entries.append(bc_url) |  | ||||||
| 
 |  | ||||||
|         return entries |  | ||||||
| 
 |  | ||||||
|     def _parse_brightcove_metadata(self, json_data, video_id, headers={}): |     def _parse_brightcove_metadata(self, json_data, video_id, headers={}): | ||||||
|         title = json_data['name'].strip() |         title = json_data['name'].strip() | ||||||
| 
 | 
 | ||||||
| @@ -588,6 +617,244 @@ class BrightcoveNewIE(AdobePassIE): | |||||||
|             'is_live': is_live, |             'is_live': is_live, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | class BrightcoveNewIE(BrightcoveNewBaseIE): | ||||||
|  |     IE_NAME = 'brightcove:new' | ||||||
|  |     _VALID_URL = r'https?://players\.brightcove\.net/(?P<account_id>\d+)/(?P<player_id>[^/]+)_(?P<embed>[^/]+)/index\.html\?.*(?P<content_type>video|playlist)Id=(?P<video_id>\d+|ref:[^&]+)' | ||||||
|  |     _TESTS = [{ | ||||||
|  |         'url': 'http://players.brightcove.net/929656772001/e41d32dc-ec74-459e-a845-6c69f7b724ea_default/index.html?videoId=4463358922001', | ||||||
|  |         'md5': 'c8100925723840d4b0d243f7025703be', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '4463358922001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Meet the man behind Popcorn Time', | ||||||
|  |             'description': 'md5:eac376a4fe366edc70279bfb681aea16', | ||||||
|  |             'duration': 165.768, | ||||||
|  |             'timestamp': 1441391203, | ||||||
|  |             'upload_date': '20150904', | ||||||
|  |             'uploader_id': '929656772001', | ||||||
|  |             'formats': 'mincount:20', | ||||||
|  |         }, | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # with rtmp streams | ||||||
|  |         'url': 'http://players.brightcove.net/4036320279001/5d112ed9-283f-485f-a7f9-33f42e8bc042_default/index.html?videoId=4279049078001', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '4279049078001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'Titansgrave: Chapter 0', | ||||||
|  |             'description': 'Titansgrave: Chapter 0', | ||||||
|  |             'duration': 1242.058, | ||||||
|  |             'timestamp': 1433556729, | ||||||
|  |             'upload_date': '20150606', | ||||||
|  |             'uploader_id': '4036320279001', | ||||||
|  |             'formats': 'mincount:39', | ||||||
|  |         }, | ||||||
|  |         'params': { | ||||||
|  |             # m3u8 download | ||||||
|  |             'skip_download': True, | ||||||
|  |         } | ||||||
|  |     }, { | ||||||
|  |         # playlist stream | ||||||
|  |         'url': 'https://players.brightcove.net/1752604059001/S13cJdUBz_default/index.html?playlistId=5718313430001', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '5718313430001', | ||||||
|  |             'title': 'No Audio Playlist', | ||||||
|  |         }, | ||||||
|  |         'playlist_count': 7, | ||||||
|  |         'params': { | ||||||
|  |             # m3u8 download | ||||||
|  |             'skip_download': True, | ||||||
|  |         } | ||||||
|  |     }, { | ||||||
|  |         'url': 'http://players.brightcove.net/5690807595001/HyZNerRl7_default/index.html?playlistId=5743160747001', | ||||||
|  |         'only_matching': True, | ||||||
|  |     }, { | ||||||
|  |         # ref: prefixed video id | ||||||
|  |         'url': 'http://players.brightcove.net/3910869709001/21519b5c-4b3b-4363-accb-bdc8f358f823_default/index.html?videoId=ref:7069442', | ||||||
|  |         'only_matching': True, | ||||||
|  |     }, { | ||||||
|  |         # non numeric ref: prefixed video id | ||||||
|  |         'url': 'http://players.brightcove.net/710858724001/default_default/index.html?videoId=ref:event-stream-356', | ||||||
|  |         'only_matching': True, | ||||||
|  |     }, { | ||||||
|  |         # unavailable video without message but with error_code | ||||||
|  |         'url': 'http://players.brightcove.net/1305187701/c832abfb-641b-44eb-9da0-2fe76786505f_default/index.html?videoId=4377407326001', | ||||||
|  |         'only_matching': True, | ||||||
|  |     }] | ||||||
|  | 
 | ||||||
|  |     _WEBPAGE_TESTS = [{ | ||||||
|  |         # brightcove player url embed | ||||||
|  |         'url': 'https://nbc-2.com/weather/forecast/2022/11/16/forecast-warmest-day-of-the-week/', | ||||||
|  |         'md5': '2934d5372b354d27083ccf8575dbfee2', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '6315650313112', | ||||||
|  |             'title': 'First Alert Forecast: November 15, 2022', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'tags': ['nbc2', 'forecast'], | ||||||
|  |             'uploader_id': '6146886170001', | ||||||
|  |             'thumbnail': r're:^https?://.*\.jpg$', | ||||||
|  |             'timestamp': 1668574571, | ||||||
|  |             'duration': 233.375, | ||||||
|  |             'upload_date': '20221116', | ||||||
|  |         }, | ||||||
|  |     }, { | ||||||
|  |         # embedded with video tag only | ||||||
|  |         'url': 'https://www.gooddishtv.com/tiktok-rapping-chef-mr-pyrex', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': 'tiktok-rapping-chef-mr-pyrex', | ||||||
|  |             'title': 'TikTok\'s Rapping Chef Makes Jambalaya for the Hosts', | ||||||
|  |             'thumbnail': r're:^https?://.*\.jpg$', | ||||||
|  |             'age_limit': 0, | ||||||
|  |             'description': 'Just in time for Mardi Gras', | ||||||
|  |         }, | ||||||
|  |         'playlist': [{ | ||||||
|  |             'info_dict': { | ||||||
|  |                 'id': '6299189544001', | ||||||
|  |                 'ext': 'mp4', | ||||||
|  |                 'title': 'TGD_01-032_5', | ||||||
|  |                 'thumbnail': r're:^https?://.*\.jpg$', | ||||||
|  |                 'tags': [], | ||||||
|  |                 'timestamp': 1646078943, | ||||||
|  |                 'uploader_id': '1569565978001', | ||||||
|  |                 'upload_date': '20220228', | ||||||
|  |                 'duration': 217.195, | ||||||
|  |             }, | ||||||
|  |         }, { | ||||||
|  |             'info_dict': { | ||||||
|  |                 'id': '6305565995112', | ||||||
|  |                 'ext': 'mp4', | ||||||
|  |                 'title': 'TGD 01-087 (Airs 05.25.22)_Segment 5', | ||||||
|  |                 'thumbnail': r're:^https?://.*\.jpg$', | ||||||
|  |                 'tags': [], | ||||||
|  |                 'timestamp': 1651604591, | ||||||
|  |                 'uploader_id': '1569565978001', | ||||||
|  |                 'upload_date': '20220503', | ||||||
|  |                 'duration': 310.421, | ||||||
|  |             }, | ||||||
|  |         }], | ||||||
|  |     }, { | ||||||
|  |         # Brightcove:new type [2]. | ||||||
|  |         'url': 'http://www.delawaresportszone.com/video-st-thomas-more-earns-first-trip-to-basketball-semis', | ||||||
|  |         'md5': '2b35148fcf48da41c9fb4591650784f3', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '5348741021001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'upload_date': '20170306', | ||||||
|  |             'uploader_id': '4191638492001', | ||||||
|  |             'timestamp': 1488769918, | ||||||
|  |             'title': 'VIDEO:  St. Thomas More earns first trip to basketball semis', | ||||||
|  |         }, | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # Alternative brightcove <video> attributes | ||||||
|  |         'url': 'http://www.programme-tv.net/videos/extraits/81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche/', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche', | ||||||
|  |             'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche, Extraits : toutes les vidéos avec Télé-Loisirs", | ||||||
|  |         }, | ||||||
|  |         'playlist': [{ | ||||||
|  |             'md5': '732d22ba3d33f2f3fc253c39f8f36523', | ||||||
|  |             'info_dict': { | ||||||
|  |                 'id': '5311302538001', | ||||||
|  |                 'ext': 'mp4', | ||||||
|  |                 'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche", | ||||||
|  |                 'description': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche (France 2, 5 février 2017)", | ||||||
|  |                 'timestamp': 1486321708, | ||||||
|  |                 'upload_date': '20170205', | ||||||
|  |                 'uploader_id': '800000640001', | ||||||
|  |             }, | ||||||
|  |             'only_matching': True, | ||||||
|  |         }], | ||||||
|  |         'skip': '404 Not Found', | ||||||
|  |     }, { | ||||||
|  |         # Brightcove URL in single quotes | ||||||
|  |         'url': 'http://www.sportsnet.ca/baseball/mlb/sn-presents-russell-martin-world-citizen/', | ||||||
|  |         'md5': '4ae374f1f8b91c889c4b9203c8c752af', | ||||||
|  |         'info_dict': { | ||||||
|  |             'id': '4255764656001', | ||||||
|  |             'ext': 'mp4', | ||||||
|  |             'title': 'SN Presents: Russell Martin, World Citizen', | ||||||
|  |             'description': 'To understand why he was the Toronto Blue Jays’ top off-season priority is to appreciate his background and upbringing in Montreal, where he first developed his baseball skills. Written and narrated by Stephen Brunt.', | ||||||
|  |             'uploader': 'Rogers Sportsnet', | ||||||
|  |             'uploader_id': '1704050871', | ||||||
|  |             'upload_date': '20150525', | ||||||
|  |             'timestamp': 1432570283, | ||||||
|  |         }, | ||||||
|  |         'skip': 'Page no longer has URL, now has javascript', | ||||||
|  |     }] | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def _extract_url(ie, webpage): | ||||||
|  |         urls = BrightcoveNewIE._extract_brightcove_urls(ie, webpage) | ||||||
|  |         return urls[0] if urls else None | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def _extract_brightcove_urls(ie, webpage): | ||||||
|  |         # Reference: | ||||||
|  |         # 1. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#setvideoiniframe | ||||||
|  |         # 2. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#tag | ||||||
|  |         # 3. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/publish-video.html#setvideousingjavascript | ||||||
|  |         # 4. http://docs.brightcove.com/en/video-cloud/brightcove-player/guides/in-page-embed-player-implementation.html | ||||||
|  |         # 5. https://support.brightcove.com/en/video-cloud/docs/dynamically-assigning-videos-player | ||||||
|  | 
 | ||||||
|  |         entries = [] | ||||||
|  | 
 | ||||||
|  |         # Look for iframe embeds [1] | ||||||
|  |         for _, url in re.findall( | ||||||
|  |                 r'<iframe[^>]+src=(["\'])((?:https?:)?//players\.brightcove\.net/\d+/[^/]+/index\.html.+?)\1', webpage): | ||||||
|  |             entries.append(url if url.startswith('http') else 'http:' + url) | ||||||
|  | 
 | ||||||
|  |         # Look for <video> tags [2] and embed_in_page embeds [3] | ||||||
|  |         # [2] looks like: | ||||||
|  |         for video, script_tag, account_id, player_id, embed in re.findall( | ||||||
|  |                 r'''(?isx) | ||||||
|  |                     (<video(?:-js)?\s+[^>]*\bdata-video-id\s*=\s*['"]?[^>]+>) | ||||||
|  |                     (?:.*? | ||||||
|  |                         (<script[^>]+ | ||||||
|  |                             src=["\'](?:https?:)?//players\.brightcove\.net/ | ||||||
|  |                             (\d+)/([^/]+)_([^/]+)/index(?:\.min)?\.js | ||||||
|  |                         ) | ||||||
|  |                     )? | ||||||
|  |                 ''', webpage): | ||||||
|  |             attrs = extract_attributes(video) | ||||||
|  | 
 | ||||||
|  |             # According to examples from [4] it's unclear whether video id | ||||||
|  |             # may be optional and what to do when it is | ||||||
|  |             video_id = attrs.get('data-video-id') | ||||||
|  |             if not video_id: | ||||||
|  |                 continue | ||||||
|  | 
 | ||||||
|  |             account_id = account_id or attrs.get('data-account') | ||||||
|  |             if not account_id: | ||||||
|  |                 continue | ||||||
|  | 
 | ||||||
|  |             player_id = player_id or attrs.get('data-player') or 'default' | ||||||
|  |             embed = embed or attrs.get('data-embed') or 'default' | ||||||
|  | 
 | ||||||
|  |             bc_url = 'http://players.brightcove.net/%s/%s_%s/index.html?videoId=%s' % ( | ||||||
|  |                 account_id, player_id, embed, video_id) | ||||||
|  | 
 | ||||||
|  |             # Some brightcove videos may be embedded with video tag only and | ||||||
|  |             # without script tag or any mentioning of brightcove at all. Such | ||||||
|  |             # embeds are considered ambiguous since they are matched based only | ||||||
|  |             # on data-video-id and data-account attributes and in the wild may | ||||||
|  |             # not be brightcove embeds at all. Let's check reconstructed | ||||||
|  |             # brightcove URLs in case of such embeds and only process valid | ||||||
|  |             # ones. By this we ensure there is indeed a brightcove embed. | ||||||
|  |             if not script_tag and not ie._is_valid_url( | ||||||
|  |                     bc_url, video_id, 'possible brightcove video'): | ||||||
|  |                 continue | ||||||
|  | 
 | ||||||
|  |             entries.append(bc_url) | ||||||
|  | 
 | ||||||
|  |         return entries | ||||||
|  | 
 | ||||||
|  |     def _extract_from_webpage(self, url, webpage): | ||||||
|  |         bc_urls = self._extract_brightcove_urls(self, webpage) | ||||||
|  |         for bc_url in bc_urls: | ||||||
|  |             yield self.url_result(smuggle_url(bc_url, {'referrer': url}), BrightcoveNewIE) | ||||||
|  | 
 | ||||||
|     def _real_extract(self, url): |     def _real_extract(self, url): | ||||||
|         url, smuggled_data = unsmuggle_url(url, {}) |         url, smuggled_data = unsmuggle_url(url, {}) | ||||||
|         self._initialize_geo_bypass({ |         self._initialize_geo_bypass({ | ||||||
| @@ -630,7 +897,7 @@ class BrightcoveNewIE(AdobePassIE): | |||||||
| 
 | 
 | ||||||
|         api_url = 'https://edge.api.brightcove.com/playback/v1/accounts/%s/%ss/%s' % (account_id, content_type, video_id) |         api_url = 'https://edge.api.brightcove.com/playback/v1/accounts/%s/%ss/%s' % (account_id, content_type, video_id) | ||||||
|         headers = {} |         headers = {} | ||||||
|         referrer = smuggled_data.get('referrer') |         referrer = smuggled_data.get('referrer')  # XXX: notice the spelling/case of the key | ||||||
|         if referrer: |         if referrer: | ||||||
|             headers.update({ |             headers.update({ | ||||||
|                 'Referer': referrer, |                 'Referer': referrer, | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ import urllib.parse | |||||||
| import xml.etree.ElementTree | import xml.etree.ElementTree | ||||||
| 
 | 
 | ||||||
| from .common import InfoExtractor  # isort: split | from .common import InfoExtractor  # isort: split | ||||||
| from .brightcove import BrightcoveLegacyIE, BrightcoveNewIE |  | ||||||
| from .commonprotocols import RtmpIE | from .commonprotocols import RtmpIE | ||||||
| from .youtube import YoutubeIE | from .youtube import YoutubeIE | ||||||
| from ..compat import compat_etree_fromstring | from ..compat import compat_etree_fromstring | ||||||
| @@ -361,188 +360,6 @@ class GenericIE(InfoExtractor): | |||||||
|             }, |             }, | ||||||
|             'skip': 'There is a limit of 200 free downloads / month for the test song', |             'skip': 'There is a limit of 200 free downloads / month for the test song', | ||||||
|         }, |         }, | ||||||
|         { |  | ||||||
|             # embedded brightcove video |  | ||||||
|             # it also tests brightcove videos that need to set the 'Referer' |  | ||||||
|             # in the http requests |  | ||||||
|             'add_ie': ['BrightcoveLegacy'], |  | ||||||
|             'url': 'http://www.bfmtv.com/video/bfmbusiness/cours-bourse/cours-bourse-l-analyse-technique-154522/', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '2765128793001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Le cours de bourse : l’analyse technique', |  | ||||||
|                 'description': 'md5:7e9ad046e968cb2d1114004aba466fd9', |  | ||||||
|                 'uploader': 'BFM BUSINESS', |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # embedded with itemprop embedURL and video id spelled as `idVideo` |  | ||||||
|             'add_id': ['BrightcoveLegacy'], |  | ||||||
|             'url': 'http://bfmbusiness.bfmtv.com/mediaplayer/chroniques/olivier-delamarche/', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '5255628253001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'md5:37c519b1128915607601e75a87995fc0', |  | ||||||
|                 'description': 'md5:37f7f888b434bb8f8cc8dbd4f7a4cf26', |  | ||||||
|                 'uploader': 'BFM BUSINESS', |  | ||||||
|                 'uploader_id': '876450612001', |  | ||||||
|                 'timestamp': 1482255315, |  | ||||||
|                 'upload_date': '20161220', |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # https://github.com/ytdl-org/youtube-dl/issues/2253 |  | ||||||
|             'url': 'http://bcove.me/i6nfkrc3', |  | ||||||
|             'md5': '0ba9446db037002366bab3b3eb30c88c', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '3101154703001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Still no power', |  | ||||||
|                 'uploader': 'thestar.com', |  | ||||||
|                 'description': 'Mississauga resident David Farmer is still out of power as a result of the ice storm a month ago. To keep the house warm, Farmer cuts wood from his property for a wood burning stove downstairs.', |  | ||||||
|             }, |  | ||||||
|             'add_ie': ['BrightcoveLegacy'], |  | ||||||
|             'skip': 'video gone', |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             'url': 'http://www.championat.com/video/football/v/87/87499.html', |  | ||||||
|             'md5': 'fb973ecf6e4a78a67453647444222983', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '3414141473001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Видео. Удаление Дзагоева (ЦСКА)', |  | ||||||
|                 'description': 'Онлайн-трансляция матча ЦСКА - "Волга"', |  | ||||||
|                 'uploader': 'Championat', |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # https://github.com/ytdl-org/youtube-dl/issues/3541 |  | ||||||
|             'add_ie': ['BrightcoveLegacy'], |  | ||||||
|             'url': 'http://www.kijk.nl/sbs6/leermijvrouwenkennen/videos/jqMiXKAYan2S/aflevering-1', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '3866516442001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Leer mij vrouwen kennen: Aflevering 1', |  | ||||||
|                 'description': 'Leer mij vrouwen kennen: Aflevering 1', |  | ||||||
|                 'uploader': 'SBS Broadcasting', |  | ||||||
|             }, |  | ||||||
|             'skip': 'Restricted to Netherlands', |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True,  # m3u8 download |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove video in <iframe> |  | ||||||
|             'url': 'http://www.un.org/chinese/News/story.asp?NewsID=27724', |  | ||||||
|             'md5': '36d74ef5e37c8b4a2ce92880d208b968', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '5360463607001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': '叙利亚失明儿童在废墟上演唱《心跳》  呼吁获得正常童年生活', |  | ||||||
|                 'description': '联合国儿童基金会中东和北非区域大使、作曲家扎德·迪拉尼(Zade Dirani)在3月15日叙利亚冲突爆发7周年纪念日之际发布了为叙利亚谱写的歌曲《心跳》(HEARTBEAT),为受到六年冲突影响的叙利亚儿童发出强烈呐喊,呼吁世界做出共同努力,使叙利亚儿童重新获得享有正常童年生活的权利。', |  | ||||||
|                 'uploader': 'United Nations', |  | ||||||
|                 'uploader_id': '1362235914001', |  | ||||||
|                 'timestamp': 1489593889, |  | ||||||
|                 'upload_date': '20170315', |  | ||||||
|             }, |  | ||||||
|             'add_ie': ['BrightcoveLegacy'], |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove with alternative playerID key |  | ||||||
|             'url': 'http://www.nature.com/nmeth/journal/v9/n7/fig_tab/nmeth.2062_SV1.html', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': 'nmeth.2062_SV1', |  | ||||||
|                 'title': 'Simultaneous multiview imaging of the Drosophila syncytial blastoderm : Quantitative high-speed imaging of entire developing embryos with simultaneous multiview light-sheet microscopy : Nature Methods : Nature Research', |  | ||||||
|             }, |  | ||||||
|             'playlist': [{ |  | ||||||
|                 'info_dict': { |  | ||||||
|                     'id': '2228375078001', |  | ||||||
|                     'ext': 'mp4', |  | ||||||
|                     'title': 'nmeth.2062-sv1', |  | ||||||
|                     'description': 'nmeth.2062-sv1', |  | ||||||
|                     'timestamp': 1363357591, |  | ||||||
|                     'upload_date': '20130315', |  | ||||||
|                     'uploader': 'Nature Publishing Group', |  | ||||||
|                     'uploader_id': '1964492299001', |  | ||||||
|                 }, |  | ||||||
|             }], |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove with UUID in videoPlayer |  | ||||||
|             'url': 'http://www8.hp.com/cn/zh/home.html', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '5255815316001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Sprocket Video - China', |  | ||||||
|                 'description': 'Sprocket Video - China', |  | ||||||
|                 'uploader': 'HP-Video Gallery', |  | ||||||
|                 'timestamp': 1482263210, |  | ||||||
|                 'upload_date': '20161220', |  | ||||||
|                 'uploader_id': '1107601872001', |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True,  # m3u8 download |  | ||||||
|             }, |  | ||||||
|             'skip': 'video rotates...weekly?', |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove:new type [2]. |  | ||||||
|             'url': 'http://www.delawaresportszone.com/video-st-thomas-more-earns-first-trip-to-basketball-semis', |  | ||||||
|             'md5': '2b35148fcf48da41c9fb4591650784f3', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '5348741021001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'upload_date': '20170306', |  | ||||||
|                 'uploader_id': '4191638492001', |  | ||||||
|                 'timestamp': 1488769918, |  | ||||||
|                 'title': 'VIDEO:  St. Thomas More earns first trip to basketball semis', |  | ||||||
| 
 |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Alternative brightcove <video> attributes |  | ||||||
|             'url': 'http://www.programme-tv.net/videos/extraits/81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche/', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '81095-guillaume-canet-evoque-les-rumeurs-d-infidelite-de-marion-cotillard-avec-brad-pitt-dans-vivement-dimanche', |  | ||||||
|                 'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche, Extraits : toutes les vidéos avec Télé-Loisirs", |  | ||||||
|             }, |  | ||||||
|             'playlist': [{ |  | ||||||
|                 'md5': '732d22ba3d33f2f3fc253c39f8f36523', |  | ||||||
|                 'info_dict': { |  | ||||||
|                     'id': '5311302538001', |  | ||||||
|                     'ext': 'mp4', |  | ||||||
|                     'title': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche", |  | ||||||
|                     'description': "Guillaume Canet évoque les rumeurs d'infidélité de Marion Cotillard avec Brad Pitt dans Vivement Dimanche (France 2, 5 février 2017)", |  | ||||||
|                     'timestamp': 1486321708, |  | ||||||
|                     'upload_date': '20170205', |  | ||||||
|                     'uploader_id': '800000640001', |  | ||||||
|                 }, |  | ||||||
|                 'only_matching': True, |  | ||||||
|             }], |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove with UUID in videoPlayer |  | ||||||
|             'url': 'http://www8.hp.com/cn/zh/home.html', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '5255815316001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'Sprocket Video - China', |  | ||||||
|                 'description': 'Sprocket Video - China', |  | ||||||
|                 'uploader': 'HP-Video Gallery', |  | ||||||
|                 'timestamp': 1482263210, |  | ||||||
|                 'upload_date': '20161220', |  | ||||||
|                 'uploader_id': '1107601872001', |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True,  # m3u8 download |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         # ooyala video |         # ooyala video | ||||||
|         { |         { | ||||||
|             'url': 'http://www.rollingstone.com/music/videos/norwegian-dj-cashmere-cat-goes-spartan-on-with-me-premiere-20131219', |             'url': 'http://www.rollingstone.com/music/videos/norwegian-dj-cashmere-cat-goes-spartan-on-with-me-premiere-20131219', | ||||||
| @@ -846,20 +663,6 @@ class GenericIE(InfoExtractor): | |||||||
|                 'title': 'Busty Blonde Siri Tit Fuck While Wank at HandjobHub.com', |                 'title': 'Busty Blonde Siri Tit Fuck While Wank at HandjobHub.com', | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         # Multiple brightcove videos |  | ||||||
|         # https://github.com/ytdl-org/youtube-dl/issues/2283 |  | ||||||
|         { |  | ||||||
|             'url': 'http://www.newyorker.com/online/blogs/newsdesk/2014/01/always-never-nuclear-command-and-control.html', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': 'always-never', |  | ||||||
|                 'title': 'Always / Never - The New Yorker', |  | ||||||
|             }, |  | ||||||
|             'playlist_count': 3, |  | ||||||
|             'params': { |  | ||||||
|                 'extract_flat': False, |  | ||||||
|                 'skip_download': True, |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         # MLB embed |         # MLB embed | ||||||
|         { |         { | ||||||
|             'url': 'http://umpire-empire.com/index.php/topic/58125-laz-decides-no-thats-low/', |             'url': 'http://umpire-empire.com/index.php/topic/58125-laz-decides-no-thats-low/', | ||||||
| @@ -1352,21 +1155,6 @@ class GenericIE(InfoExtractor): | |||||||
|             }, |             }, | ||||||
|             'expected_warnings': ['Failed to parse JSON Expecting value'], |             'expected_warnings': ['Failed to parse JSON Expecting value'], | ||||||
|         }, |         }, | ||||||
|         # Brightcove URL in single quotes |  | ||||||
|         { |  | ||||||
|             'url': 'http://www.sportsnet.ca/baseball/mlb/sn-presents-russell-martin-world-citizen/', |  | ||||||
|             'md5': '4ae374f1f8b91c889c4b9203c8c752af', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '4255764656001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'SN Presents: Russell Martin, World Citizen', |  | ||||||
|                 'description': 'To understand why he was the Toronto Blue Jays’ top off-season priority is to appreciate his background and upbringing in Montreal, where he first developed his baseball skills. Written and narrated by Stephen Brunt.', |  | ||||||
|                 'uploader': 'Rogers Sportsnet', |  | ||||||
|                 'uploader_id': '1704050871', |  | ||||||
|                 'upload_date': '20150525', |  | ||||||
|                 'timestamp': 1432570283, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         # Kinja embed |         # Kinja embed | ||||||
|         { |         { | ||||||
|             'url': 'http://www.clickhole.com/video/dont-understand-bitcoin-man-will-mumble-explanatio-2537', |             'url': 'http://www.clickhole.com/video/dont-understand-bitcoin-man-will-mumble-explanatio-2537', | ||||||
| @@ -1402,52 +1190,6 @@ class GenericIE(InfoExtractor): | |||||||
|                 'duration': 248.667, |                 'duration': 248.667, | ||||||
|             }, |             }, | ||||||
|         }, |         }, | ||||||
|         # BrightcoveInPageEmbed embed |  | ||||||
|         { |  | ||||||
|             'url': 'http://www.geekandsundry.com/tabletop-bonus-wils-final-thoughts-on-dread/', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '4238694884001', |  | ||||||
|                 'ext': 'flv', |  | ||||||
|                 'title': 'Tabletop: Dread, Last Thoughts', |  | ||||||
|                 'description': 'Tabletop: Dread, Last Thoughts', |  | ||||||
|                 'duration': 51690, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         # Brightcove embed, with no valid 'renditions' but valid 'IOSRenditions' |  | ||||||
|         # This video can't be played in browsers if Flash disabled and UA set to iPhone, which is actually a false alarm |  | ||||||
|         { |  | ||||||
|             'url': 'https://dl.dropboxusercontent.com/u/29092637/interview.html', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '4785848093001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': 'The Cardinal Pell Interview', |  | ||||||
|                 'description': 'Sky News Contributor Andrew Bolt interviews George Pell in Rome, following the Cardinal\'s evidence before the Royal Commission into Child Abuse. ', |  | ||||||
|                 'uploader': 'GlobeCast Australia - GlobeStream', |  | ||||||
|                 'uploader_id': '2733773828001', |  | ||||||
|                 'upload_date': '20160304', |  | ||||||
|                 'timestamp': 1457083087, |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 # m3u8 downloads |  | ||||||
|                 'skip_download': True, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             # Brightcove embed with whitespace around attribute names |  | ||||||
|             'url': 'http://www.stack.com/video/3167554373001/learn-to-hit-open-three-pointers-with-damian-lillard-s-baseline-drift-drill', |  | ||||||
|             'info_dict': { |  | ||||||
|                 'id': '3167554373001', |  | ||||||
|                 'ext': 'mp4', |  | ||||||
|                 'title': "Learn to Hit Open Three-Pointers With Damian Lillard's Baseline Drift Drill", |  | ||||||
|                 'description': 'md5:57bacb0e0f29349de4972bfda3191713', |  | ||||||
|                 'uploader_id': '1079349493', |  | ||||||
|                 'upload_date': '20140207', |  | ||||||
|                 'timestamp': 1391810548, |  | ||||||
|             }, |  | ||||||
|             'params': { |  | ||||||
|                 'skip_download': True, |  | ||||||
|             }, |  | ||||||
|         }, |  | ||||||
|         # Another form of arte.tv embed |         # Another form of arte.tv embed | ||||||
|         { |         { | ||||||
|             'url': 'http://www.tv-replay.fr/redirection/09-04-16/arte-reportage-arte-11508975.html', |             'url': 'http://www.tv-replay.fr/redirection/09-04-16/arte-reportage-arte-11508975.html', | ||||||
| @@ -1498,7 +1240,7 @@ class GenericIE(InfoExtractor): | |||||||
|                 'timestamp': 1464107587, |                 'timestamp': 1464107587, | ||||||
|                 'uploader': 'TheAtlantic', |                 'uploader': 'TheAtlantic', | ||||||
|             }, |             }, | ||||||
|             'add_ie': ['BrightcoveLegacy'], |             'skip': 'Private Youtube video', | ||||||
|         }, |         }, | ||||||
|         # Facebook <iframe> embed |         # Facebook <iframe> embed | ||||||
|         { |         { | ||||||
| @@ -2730,16 +2472,6 @@ class GenericIE(InfoExtractor): | |||||||
|         # There probably should be a second run of generic extractor on unescaped webpage. |         # There probably should be a second run of generic extractor on unescaped webpage. | ||||||
|         # webpage = urllib.parse.unquote(webpage) |         # webpage = urllib.parse.unquote(webpage) | ||||||
| 
 | 
 | ||||||
|         # TODO: Move to respective extractors |  | ||||||
|         bc_urls = BrightcoveLegacyIE._extract_brightcove_urls(webpage) |  | ||||||
|         if bc_urls: |  | ||||||
|             return [self.url_result(smuggle_url(bc_url, {'Referer': url}), BrightcoveLegacyIE) |  | ||||||
|                     for bc_url in bc_urls] |  | ||||||
|         bc_urls = BrightcoveNewIE._extract_brightcove_urls(self, webpage) |  | ||||||
|         if bc_urls: |  | ||||||
|             return [self.url_result(smuggle_url(bc_url, {'Referer': url}), BrightcoveNewIE) |  | ||||||
|                     for bc_url in bc_urls] |  | ||||||
| 
 |  | ||||||
|         embeds = [] |         embeds = [] | ||||||
|         for ie in self._downloader._ies.values(): |         for ie in self._downloader._ies.values(): | ||||||
|             if ie.ie_key() in smuggled_data.get('block_ies', []): |             if ie.ie_key() in smuggled_data.get('block_ies', []): | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import json | import json | ||||||
| import re | import re | ||||||
| 
 | 
 | ||||||
| from .brightcove import BrightcoveNewIE | from .brightcove import BrightcoveNewBaseIE | ||||||
| from ..compat import ( | from ..compat import ( | ||||||
|     compat_HTTPError, |     compat_HTTPError, | ||||||
|     compat_str, |     compat_str, | ||||||
| @@ -13,7 +13,7 @@ from ..utils import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SevenPlusIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE | class SevenPlusIE(BrightcoveNewBaseIE): | ||||||
|     IE_NAME = '7plus' |     IE_NAME = '7plus' | ||||||
|     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))' |     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))' | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 bashonly
					bashonly