[extractor/cbc] Fix live extractor, playlist _VALID_URL (#6625)

Authored by: makew0rld
This commit is contained in:
makeworld 2023-04-27 22:42:25 -04:00 committed by GitHub
parent b5f61b69d4
commit 7a7b1376fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -8,14 +8,16 @@
compat_str, compat_str,
) )
from ..utils import ( from ..utils import (
ExtractorError,
int_or_none, int_or_none,
join_nonempty, join_nonempty,
js_to_json, js_to_json,
orderedSet, orderedSet,
parse_iso8601,
smuggle_url, smuggle_url,
strip_or_none, strip_or_none,
traverse_obj,
try_get, try_get,
ExtractorError,
) )
@ -404,7 +406,7 @@ def _real_extract(self, url):
class CBCGemPlaylistIE(InfoExtractor): class CBCGemPlaylistIE(InfoExtractor):
IE_NAME = 'gem.cbc.ca:playlist' IE_NAME = 'gem.cbc.ca:playlist'
_VALID_URL = r'https?://gem\.cbc\.ca/media/(?P<id>(?P<show>[0-9a-z-]+)/s(?P<season>[0-9]+))/?(?:[?#]|$)' _VALID_URL = r'https?://gem\.cbc\.ca/(?:media/)?(?P<id>(?P<show>[0-9a-z-]+)/s(?P<season>[0-9]+))/?(?:[?#]|$)'
_TESTS = [{ _TESTS = [{
# TV show playlist, all public videos # TV show playlist, all public videos
'url': 'https://gem.cbc.ca/media/schitts-creek/s06', 'url': 'https://gem.cbc.ca/media/schitts-creek/s06',
@ -414,6 +416,9 @@ class CBCGemPlaylistIE(InfoExtractor):
'title': 'Season 6', 'title': 'Season 6',
'description': 'md5:6a92104a56cbeb5818cc47884d4326a2', 'description': 'md5:6a92104a56cbeb5818cc47884d4326a2',
}, },
}, {
'url': 'https://gem.cbc.ca/schitts-creek/s06',
'only_matching': True,
}] }]
_API_BASE = 'https://services.radio-canada.ca/ott/cbc-api/v2/shows/' _API_BASE = 'https://services.radio-canada.ca/ott/cbc-api/v2/shows/'
@ -473,49 +478,90 @@ def _real_extract(self, url):
class CBCGemLiveIE(InfoExtractor): class CBCGemLiveIE(InfoExtractor):
IE_NAME = 'gem.cbc.ca:live' IE_NAME = 'gem.cbc.ca:live'
_VALID_URL = r'https?://gem\.cbc\.ca/live/(?P<id>\d+)' _VALID_URL = r'https?://gem\.cbc\.ca/live(?:-event)?/(?P<id>\d+)'
_TEST = { _TESTS = [
'url': 'https://gem.cbc.ca/live/920604739687', {
'info_dict': { 'url': 'https://gem.cbc.ca/live/920604739687',
'title': 'Ottawa', 'info_dict': {
'description': 'The live TV channel and local programming from Ottawa', 'title': 'Ottawa',
'thumbnail': 'https://thumbnails.cbc.ca/maven_legacy/thumbnails/CBC_OTT_VMS/Live_Channel_Static_Images/Ottawa_2880x1620.jpg', 'description': 'The live TV channel and local programming from Ottawa',
'is_live': True, 'thumbnail': 'https://thumbnails.cbc.ca/maven_legacy/thumbnails/CBC_OTT_VMS/Live_Channel_Static_Images/Ottawa_2880x1620.jpg',
'id': 'AyqZwxRqh8EH', 'is_live': True,
'ext': 'mp4', 'id': 'AyqZwxRqh8EH',
'timestamp': 1492106160, 'ext': 'mp4',
'upload_date': '20170413', 'timestamp': 1492106160,
'uploader': 'CBCC-NEW', 'upload_date': '20170413',
'uploader': 'CBCC-NEW',
},
'skip': 'Live might have ended',
}, },
'skip': 'Live might have ended', {
} 'url': 'https://gem.cbc.ca/live/44',
'info_dict': {
# It's unclear where the chars at the end come from, but they appear to be 'id': '44',
# constant. Might need updating in the future. 'ext': 'mp4',
# There are two URLs, some livestreams are in one, and some 'is_live': True,
# in the other. The JSON schema is the same for both. 'title': r're:^Ottawa [0-9\-: ]+',
_API_URLS = ['https://tpfeed.cbc.ca/f/ExhSPC/t_t3UKJR6MAT', 'https://tpfeed.cbc.ca/f/ExhSPC/FNiv9xQx_BnT'] 'description': 'The live TV channel and local programming from Ottawa',
'live_status': 'is_live',
'thumbnail': r're:https://images.gem.cbc.ca/v1/cbc-gem/live/.*'
},
'params': {'skip_download': True},
'skip': 'Live might have ended',
},
{
'url': 'https://gem.cbc.ca/live-event/10835',
'info_dict': {
'id': '10835',
'ext': 'mp4',
'is_live': True,
'title': r're:^The National \| Bidens trip wraps up, Paltrow testifies, Bird flu [0-9\-: ]+',
'description': 'March 24, 2023 | President Bidens Ottawa visit ends with big pledges from both countries. Plus, Gwyneth Paltrow testifies in her ski collision trial.',
'live_status': 'is_live',
'thumbnail': r're:https://images.gem.cbc.ca/v1/cbc-gem/live/.*',
'timestamp': 1679706000,
'upload_date': '20230325',
},
'params': {'skip_download': True},
'skip': 'Live might have ended',
}
]
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
video_info = self._search_nextjs_data(webpage, video_id)['props']['pageProps']['data']
for api_url in self._API_URLS: # Two types of metadata JSON
video_info = next(( if not video_info.get('formattedIdMedia'):
stream for stream in self._download_json(api_url, video_id)['entries'] video_info = traverse_obj(
if stream.get('guid') == video_id), None) video_info, (('freeTv', ('streams', ...)), 'items', lambda _, v: v['key'] == video_id, {dict}),
if video_info: get_all=False, default={})
break
else: video_stream_id = video_info.get('formattedIdMedia')
if not video_stream_id:
raise ExtractorError('Couldn\'t find video metadata, maybe this livestream is now offline', expected=True) raise ExtractorError('Couldn\'t find video metadata, maybe this livestream is now offline', expected=True)
stream_data = self._download_json(
'https://services.radio-canada.ca/media/validation/v2/', video_id, query={
'appCode': 'mpx',
'connectionType': 'hd',
'deviceType': 'ipad',
'idMedia': video_stream_id,
'multibitrate': 'true',
'output': 'json',
'tech': 'hls',
'manifestType': 'desktop',
})
return { return {
'_type': 'url_transparent',
'ie_key': 'ThePlatform',
'url': video_info['content'][0]['url'],
'id': video_id, 'id': video_id,
'title': video_info.get('title'), 'formats': self._extract_m3u8_formats(stream_data['url'], video_id, 'mp4', live=True),
'description': video_info.get('description'),
'tags': try_get(video_info, lambda x: x['keywords'].split(', ')),
'thumbnail': video_info.get('cbc$staticImage'),
'is_live': True, 'is_live': True,
**traverse_obj(video_info, {
'title': 'title',
'description': 'description',
'thumbnail': ('images', 'card', 'url'),
'timestamp': ('airDate', {parse_iso8601}),
})
} }