]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/opencast.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
17 class OpencastBaseIE(InfoExtractor
):
18 _INSTANCES_RE
= r
'''(?:
19 opencast\.informatik\.kit\.edu|
20 electures\.uni-muenster\.de|
21 oc-presentation\.ltcc\.tuwien\.ac\.at|
22 medien\.ph-noe\.ac\.at|
23 oc-video\.ruhr-uni-bochum\.de|
24 oc-video1\.ruhr-uni-bochum\.de|
25 opencast\.informatik\.uni-goettingen\.de|
26 heicast\.uni-heidelberg\.de|
27 opencast\.hawk\.de:8080|
28 opencast\.hs-osnabrueck\.de|
29 video[0-9]+\.virtuos\.uni-osnabrueck\.de|
30 opencast\.uni-koeln\.de|
31 media\.opencast\.hochschule-rhein-waal\.de|
32 matterhorn\.dce\.harvard\.edu|
33 hs-harz\.opencast\.uni-halle\.de|
34 videocampus\.urz\.uni-leipzig\.de|
36 vid\.igb\.illinois\.edu|
37 cursosabertos\.c3sl\.ufpr\.br|
38 mcmedia\.missioncollege\.org|
41 _UUID_RE
= r
'[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}'
43 def _call_api(self
, host
, video_id
, **kwargs
):
44 return self
._download
_json
(self
._API
_BASE
% (host
, video_id
), video_id
, **kwargs
)
46 def _parse_mediapackage(self
, video
):
47 video_id
= video
.get('id')
49 raise ExtractorError('Video id was not found')
52 for track
in variadic(traverse_obj(video
, ('media', 'track')) or []):
53 href
= track
.get('url')
56 ext
= determine_ext(href
, None)
58 transport
= track
.get('transport')
60 if transport
== 'DASH' or ext
== 'mpd':
61 formats
.extend(self
._extract
_mpd
_formats
_and
_subtitles
(href
, video_id
, mpd_id
='dash', fatal
=False))
62 elif transport
== 'HLS' or ext
== 'm3u8':
63 formats
.extend(self
._extract
_m
3u8_formats
_and
_subtitles
(
64 href
, video_id
, m3u8_id
='hls', entry_protocol
='m3u8_native', fatal
=False))
65 elif transport
== 'HDS' or ext
== 'f4m':
66 formats
.extend(self
._extract
_f
4m
_formats
(href
, video_id
, f4m_id
='hds', fatal
=False))
67 elif transport
== 'SMOOTH':
68 formats
.extend(self
._extract
_ism
_formats
(href
, video_id
, ism_id
='smooth', fatal
=False))
70 formats
.extend(self
._extract
_smil
_formats
(href
, video_id
, fatal
=False))
75 'format_note': track
.get('transport'),
76 'resolution': traverse_obj(track
, ('video', 'resolution')),
77 'fps': int_or_none(traverse_obj(track
, ('video', 'framerate'))),
78 'vbr': int_or_none(traverse_obj(track
, ('video', 'bitrate')), scale
=1000),
79 'vcodec': traverse_obj(track
, ('video', 'encoder', 'type')) if track
.get('video') else 'none',
80 'abr': int_or_none(traverse_obj(track
, ('audio', 'bitrate')), scale
=1000),
81 'asr': int_or_none(traverse_obj(track
, ('audio', 'samplingrate'))),
82 'acodec': traverse_obj(track
, ('audio', 'encoder', 'type')) if track
.get('audio') else 'none',
85 if transport
== 'RTMP':
86 m_obj
= re
.search(r
'(?:rtmp://[^/]+/(?P<app>[^/]+))/(?P<ext>.+):(?P<playpath>.+)', href
)
90 'app': m_obj
.group('app'),
91 'ext': m_obj
.group('ext'),
92 'play_path': m_obj
.group('ext') + ':' + m_obj
.group('playpath'),
96 formats
.append(track_obj
)
98 self
._sort
_formats
(formats
)
103 'title': video
.get('title'),
104 'series': video
.get('seriestitle'),
105 'season_id': video
.get('series'),
106 'creator': traverse_obj(video
, ('creators', 'creator')),
107 'timestamp': parse_iso8601(video
.get('start')),
108 'thumbnail': traverse_obj(video
, ('attachments', 'attachment', ..., 'url'), get_all
=False),
112 class OpencastIE(OpencastBaseIE
):
113 _VALID_URL
= r
'''(?x)
114 https?://(?P<host>%s)/paella/ui/watch.html\?.*?
116 ''' % (OpencastBaseIE
._INSTANCES
_RE
, OpencastBaseIE
._UUID
_RE
)
118 _API_BASE
= 'https://%s/search/episode.json?id=%s'
122 'url': 'https://oc-video1.ruhr-uni-bochum.de/paella/ui/watch.html?id=ed063cd5-72c8-46b5-a60a-569243edcea8',
123 'md5': '554c8e99a90f7be7e874619fcf2a3bc9',
125 'id': 'ed063cd5-72c8-46b5-a60a-569243edcea8',
127 'title': '11 - Kryptographie - 24.11.2015',
128 'thumbnail': r
're:^https?://.*\.jpg$',
129 'timestamp': 1606208400,
130 'upload_date': '20201124',
135 def _real_extract(self
, url
):
136 host
, video_id
= self
._match
_valid
_url
(url
).group('host', 'id')
137 return self
._parse
_mediapackage
(
138 self
._call
_api
(host
, video_id
)['search-results']['result']['mediapackage'])
141 class OpencastPlaylistIE(OpencastBaseIE
):
142 _VALID_URL
= r
'''(?x)
143 https?://(?P<host>%s)/engage/ui/index.html\?.*?
145 ''' % (OpencastBaseIE
._INSTANCES
_RE
, OpencastBaseIE
._UUID
_RE
)
147 _API_BASE
= 'https://%s/search/episode.json?sid=%s'
151 'url': 'https://oc-video1.ruhr-uni-bochum.de/engage/ui/index.html?epFrom=cf68a4a1-36b1-4a53-a6ba-61af5705a0d0',
153 'id': 'cf68a4a1-36b1-4a53-a6ba-61af5705a0d0',
154 'title': 'Kryptographie - WiSe 15/16',
156 'playlist_mincount': 28,
159 'url': 'https://oc-video.ruhr-uni-bochum.de/engage/ui/index.html?e=1&p=1&epFrom=b1a54262-3684-403f-9731-8e77c3766f9a',
161 'id': 'b1a54262-3684-403f-9731-8e77c3766f9a',
162 'title': 'inSTUDIES-Social movements and prefigurative politics in a global perspective',
164 'playlist_mincount': 6,
168 def _real_extract(self
, url
):
169 host
, video_id
= self
._match
_valid
_url
(url
).group('host', 'id')
172 self
._parse
_mediapackage
(episode
['mediapackage'])
173 for episode
in variadic(self
._call
_api
(host
, video_id
)['search-results']['result'])
174 if episode
.get('mediapackage')
177 return self
.playlist_result(entries
, video_id
, traverse_obj(entries
, (0, 'series')))