3 from .common
import InfoExtractor
11 class BeaconTvIE(InfoExtractor
):
12 _VALID_URL
= r
'https?://(?:www\.)?beacon\.tv/content/(?P<id>[\w-]+)'
15 'url': 'https://beacon.tv/content/welcome-to-beacon',
16 'md5': 'b3f5932d437f288e662f10f3bfc5bd04',
18 'id': 'welcome-to-beacon',
20 'upload_date': '20240509',
21 'description': 'md5:ea2bd32e71acf3f9fca6937412cc3563',
22 'thumbnail': 'https://cdn.jwplayer.com/v2/media/I4CkkEvN/poster.jpg?width=720',
23 'title': 'Your home for Critical Role!',
24 'timestamp': 1715227200,
28 'url': 'https://beacon.tv/content/re-slayers-take-trailer',
29 'md5': 'd879b091485dbed2245094c8152afd89',
31 'id': 're-slayers-take-trailer',
33 'title': 'The Re-Slayer’s Take | Official Trailer',
34 'timestamp': 1715189040,
35 'upload_date': '20240508',
37 'thumbnail': 'https://cdn.jwplayer.com/v2/media/PW5ApIw3/poster.jpg?width=720',
41 def _real_extract(self
, url
):
42 video_id
= self
._match
_id
(url
)
43 webpage
= self
._download
_webpage
(url
, video_id
)
45 content_data
= traverse_obj(self
._search
_nextjs
_data
(webpage
, video_id
), (
46 'props', 'pageProps', '__APOLLO_STATE__',
47 lambda k
, v
: k
.startswith('Content:') and v
['slug'] == video_id
, any
))
49 raise ExtractorError('Failed to extract content data')
51 jwplayer_data
= traverse_obj(content_data
, (
52 (('contentVideo', 'video', 'videoData'),
53 ('contentPodcast', 'podcast', 'audioData')), {json
.loads
}, {dict}
, any
))
55 if content_data
.get('contentType') not in ('videoPodcast', 'video', 'podcast'):
56 raise ExtractorError('Content is not a video/podcast', expected
=True)
57 if traverse_obj(content_data
, ('contentTier', '__ref')) != 'MemberTier:65b258d178f89be87b4dc0a4':
58 self
.raise_login_required('This video/podcast is for members only')
59 raise ExtractorError('Failed to extract content')
62 **self
._parse
_jwplayer
_data
(jwplayer_data
, video_id
),
63 **traverse_obj(content_data
, {
64 'title': ('title', {str}
),
65 'description': ('description', {str}
),
66 'timestamp': ('publishedAt', {parse_iso8601}
),