diff --git a/yt_dlp/extractor/beacon.py b/yt_dlp/extractor/beacon.py index b9b41d4d2..ae47687cc 100644 --- a/yt_dlp/extractor/beacon.py +++ b/yt_dlp/extractor/beacon.py @@ -24,23 +24,42 @@ class BeaconTvIE(InfoExtractor): 'timestamp': 1715227200, 'duration': 105.494, }, + }, { + 'url': 'https://beacon.tv/content/re-slayers-take-trailer', + 'md5': 'd879b091485dbed2245094c8152afd89', + 'info_dict': { + 'id': 're-slayers-take-trailer', + 'ext': 'mp4', + 'title': 'The Re-Slayer’s Take | Official Trailer', + 'timestamp': 1715189040, + 'upload_date': '20240508', + 'duration': 53.249, + 'thumbnail': 'https://cdn.jwplayer.com/v2/media/PW5ApIw3/poster.jpg?width=720', + }, }] def _real_extract(self, url): video_id = self._match_id(url) webpage = self._download_webpage(url, video_id) - state = self._search_nextjs_data(webpage, video_id)['props']['pageProps']['__APOLLO_STATE__'] + content_data = traverse_obj(self._search_nextjs_data(webpage, video_id), ( + 'props', 'pageProps', '__APOLLO_STATE__', + lambda k, v: k.startswith('Content:') and v['slug'] == video_id, any)) + if not content_data: + raise ExtractorError('Failed to extract content data') - content_data = traverse_obj(state, (lambda k, v: k.startswith('Content:') and v['slug'] == video_id, any)) - - if not content_data or not content_data.get('contentVideo'): - raise ExtractorError( - 'Failed to extract video. Either the given content is not a video, or it requires authentication', expected=True) + jwplayer_data = traverse_obj(content_data, ( + (('contentVideo', 'video', 'videoData'), + ('contentPodcast', 'podcast', 'audioData')), {json.loads}, {dict}, any)) + if not jwplayer_data: + if content_data.get('contentType') not in ('videoPodcast', 'video', 'podcast'): + raise ExtractorError('Content is not a video/podcast', expected=True) + if traverse_obj(content_data, ('contentTier', '__ref')) != 'MemberTier:65b258d178f89be87b4dc0a4': + self.raise_login_required('This video/podcast is for members only') + raise ExtractorError('Failed to extract content') return { - **self._parse_jwplayer_data(traverse_obj( - content_data, ('contentVideo', 'video', 'videoData', {json.loads})), video_id), + **self._parse_jwplayer_data(jwplayer_data, video_id), **traverse_obj(content_data, { 'title': ('title', {str}), 'description': ('description', {str}),