5 from .common
import InfoExtractor
6 from ..networking
.exceptions
import HTTPError
16 class DacastBaseIE(InfoExtractor
):
21 return fr
'https?://iframe\.dacast\.com/{cls._URL_TYPE}/(?P<user_id>[\w-]+)/(?P<id>[\w-]+)'
24 def _EMBED_REGEX(cls
):
25 return [rf
'<iframe[^>]+\bsrc=["\'](?P<url>{cls._VALID_URL})']
27 _API_INFO_URL
= 'https://playback.dacast.com/content/info'
30 def _get_url_from_id(cls
, content_id
):
31 user_id
, media_id
= content_id
.split(f
'-{cls._URL_TYPE}-')
32 return f
'https://iframe.dacast.com/{cls._URL_TYPE}/{user_id}/{media_id}'
35 def _extract_embed_urls(cls
, url
, webpage
):
36 yield from super()._extract
_embed
_urls
(url
, webpage
)
37 for content_id
in re
.findall(
38 rf
'<script[^>]+\bsrc=["\']https://player\.dacast\.com/js/player\.js\?contentId=([\w-]+-{cls._URL_TYPE}-[\w-]+)["\']', webpage
):
39 yield cls
._get
_url
_from
_id
(content_id
)
42 class DacastVODIE(DacastBaseIE
):
45 'url': 'https://iframe.dacast.com/vod/acae82153ef4d7a7344ae4eaa86af534/1c6143e3-5a06-371d-8695-19b96ea49090',
47 'id': '1c6143e3-5a06-371d-8695-19b96ea49090',
49 'uploader_id': 'acae82153ef4d7a7344ae4eaa86af534',
50 'title': '2_4||Adnexal mass characterisation: O-RADS US and MRI||N. Bharwani, London/UK',
51 'thumbnail': 'https://universe-files.dacast.com/26137208-5858-65c1-5e9a-9d6b6bd2b6c2',
53 'params': {'skip_download': 'm3u8'},
56 'url': 'https://www.dacast.com/support/knowledgebase/how-can-i-embed-a-video-on-my-website/',
58 'id': 'b6674869-f08a-23c5-1d7b-81f5309e1a90',
60 'title': '4-HowToEmbedVideo.mp4',
61 'uploader_id': '3b67c4a9-3886-4eb1-d0eb-39b23b14bef3',
62 'thumbnail': 'https://universe-files.dacast.com/d26ab48f-a52a-8783-c42e-a90290ba06b6.png',
64 'params': {'skip_download': 'm3u8'},
66 'url': 'https://gist.githubusercontent.com/bashonly/4ad249ef2910346fbdf3809b220f11ee/raw/87349778d4af1a80b1fcc3beb9c88108de5858f5/dacast_embeds.html',
68 'id': 'e7df418e-a83b-7a7f-7b5e-1a667981e8fa',
70 'title': 'Evening Service 2-5-23',
71 'uploader_id': '943bb1ab3c03695ba85330d92d6d226e',
72 'thumbnail': 'https://universe-files.dacast.com/337472b3-e92c-2ea4-7eb7-5700da477f67',
74 'params': {'skip_download': 'm3u8'},
77 def _real_extract(self
, url
):
78 user_id
, video_id
= self
._match
_valid
_url
(url
).group('user_id', 'id')
79 query
= {'contentId': f
'{user_id}-vod-{video_id}', 'provider': 'universe'}
80 info
= self
._download
_json
(self
._API
_INFO
_URL
, video_id
, query
=query
, fatal
=False)
81 access
= self
._download
_json
(
82 'https://playback.dacast.com/content/access', video_id
,
83 note
='Downloading access JSON', query
=query
, expected_status
=403)
85 error
= access
.get('error')
86 if error
in ('Broadcaster has been blocked', 'Content is offline'):
87 raise ExtractorError(error
, expected
=True)
89 raise ExtractorError(f
'Dacast API says "{error}"')
91 hls_url
= access
['hls']
94 if 'DRM_EXT' in hls_url
:
95 self
.report_drm(video_id
)
96 elif '/uspaes/' in hls_url
:
97 # From https://player.dacast.com/js/player.js
99 signature
= hashlib
.sha1(
100 f
'{10413792000 - ts}{ts}YfaKtquEEpDeusCKbvYszIEZnWmBcSvw').digest().hex()
101 hls_aes
['uri'] = f
'https://keys.dacast.com/uspaes/{video_id}.key?s={signature}&ts={ts}'
103 for retry
in self
.RetryManager():
105 formats
= self
._extract
_m
3u8_formats
(hls_url
, video_id
, 'mp4', m3u8_id
='hls')
106 except ExtractorError
as e
:
107 # CDN will randomly respond with 403
108 if isinstance(e
.cause
, HTTPError
) and e
.cause
.status
== 403:
115 'uploader_id': user_id
,
117 'hls_aes': hls_aes
or None,
118 **traverse_obj(info
, ('contentInfo', {
120 'duration': ('duration', {float_or_none}
),
121 'thumbnail': ('thumbnailUrl', {url_or_none}
),
126 class DacastPlaylistIE(DacastBaseIE
):
127 _URL_TYPE
= 'playlist'
129 'url': 'https://iframe.dacast.com/playlist/943bb1ab3c03695ba85330d92d6d226e/b632eb053cac17a9c9a02bcfc827f2d8',
130 'playlist_mincount': 28,
132 'id': 'b632eb053cac17a9c9a02bcfc827f2d8',
133 'title': 'Archive Sermons',
137 'url': 'https://gist.githubusercontent.com/bashonly/7efb606f49f3c6e07ea0327de5a661d1/raw/05a16eac830245ea301fb0a585023bec71e6093c/dacast_playlist_embed.html',
138 'playlist_mincount': 28,
140 'id': 'b632eb053cac17a9c9a02bcfc827f2d8',
141 'title': 'Archive Sermons',
145 def _real_extract(self
, url
):
146 user_id
, playlist_id
= self
._match
_valid
_url
(url
).group('user_id', 'id')
147 info
= self
._download
_json
(
148 self
._API
_INFO
_URL
, playlist_id
, note
='Downloading playlist JSON', query
={
149 'contentId': f
'{user_id}-playlist-{playlist_id}',
150 'provider': 'universe',
154 for video
in traverse_obj(info
, ('features', 'playlist', 'contents', lambda _
, v
: v
['id'])):
155 yield self
.url_result(
156 DacastVODIE
._get
_url
_from
_id
(video
['id']), DacastVODIE
, video
['id'], video
.get('title'))
158 return self
.playlist_result(entries(info
), playlist_id
, info
.get('title'))