diff --git a/youtube_dl/extractor/opencast.py b/youtube_dl/extractor/opencast.py index c12f2a834..4390b1741 100644 --- a/youtube_dl/extractor/opencast.py +++ b/youtube_dl/extractor/opencast.py @@ -5,6 +5,7 @@ import re from .common import InfoExtractor from ..utils import ( + determine_ext, parse_iso8601, parse_resolution, int_or_none, @@ -42,42 +43,75 @@ class OpencastBaseIE(InfoExtractor): def _parse_mediapackage(self, video): tracks = video.get('media', {}).get('track', []) + + video_id = video.get('id') + formats = [] - for track in tracks: - track_obj = {'url': track['url']} + href = track['url'] + ext = determine_ext(href, None) + track_obj = {'url': href} - audio_info = track.get('audio') - if audio_info is not None: - if 'bitrate' in audio_info: - track_obj.update({'abr': int_or_none(audio_info.get('bitrate'), 1000)}) - if 'samplingrate' in audio_info: - track_obj.update({'asr': int_or_none(audio_info.get('samplingrate'))}) - audio_encoder = audio_info.get('encoder', {}) - if 'type' in audio_encoder: - track_obj.update({'acodec': audio_encoder.get('type')}) + transport = track.get('transport') - video_info = track.get('video') - if video_info is not None: - if 'resolution' in video_info: - track_obj.update({'resolution': video_info.get('resolution')}) - resolution = parse_resolution(video_info.get('resolution')) - track_obj.update(resolution) - if 'framerate' in video_info: - track_obj.update({'fps': int_or_none(video_info.get('framerate'))}) - if 'bitrate' in video_info: - track_obj.update({'vbr': int_or_none(video_info.get('bitrate'), 1000)}) - video_encoder = video_info.get('encoder', {}) - if 'type' in video_encoder: - track_obj.update({'vcodec': video_encoder.get('type')}) + if transport == 'DASH' or ext == 'mpd': + formats.extend(self._extract_mpd_formats(href, video_id, mpd_id='dash', fatal=False)) + elif transport == 'HLS' or ext == 'm3u8': + formats.extend( + self._extract_m3u8_formats( + href, video_id, ext='mp4', m3u8_id='hls', entry_protocol='m3u8_native', fatal=False + ) + ) + elif transport == 'HDS' or ext == 'f4m': + formats.extend(self._extract_f4m_formats(href, video_id, f4m_id='hds', fatal=False)) + elif transport == 'SMOOTH': + formats.extend(self._extract_ism_formats(href, video_id, ism_id='smooth', fatal=False)) + elif ext == 'smil': + formats.extend(self._extract_smil_formats(href, video_id, fatal=False)) + else: + if transport is not None: + track_obj.update({'format_note': track.get('transport')}) + if transport == 'RTMP': + m_obj = re.search(r'^(?:rtmp://[^/]+/(?P[^/]+))/(?P.+)$', href) + if not m_obj: + continue + track_obj.update( + { + 'app': m_obj.group('app'), + 'play_path': m_obj.group('playpath'), + } + ) - formats.append(track_obj) + audio_info = track.get('audio') + if audio_info is not None: + if 'bitrate' in audio_info: + track_obj.update({'abr': int_or_none(audio_info.get('bitrate'), 1000)}) + if 'samplingrate' in audio_info: + track_obj.update({'asr': int_or_none(audio_info.get('samplingrate'))}) + audio_encoder = audio_info.get('encoder', {}) + if 'type' in audio_encoder: + track_obj.update({'acodec': audio_encoder.get('type')}) + + video_info = track.get('video') + if video_info is not None: + if 'resolution' in video_info: + track_obj.update({'resolution': video_info.get('resolution')}) + resolution = parse_resolution(video_info.get('resolution')) + track_obj.update(resolution) + if 'framerate' in video_info: + track_obj.update({'fps': int_or_none(video_info.get('framerate'))}) + if 'bitrate' in video_info: + track_obj.update({'vbr': int_or_none(video_info.get('bitrate'), 1000)}) + video_encoder = video_info.get('encoder', {}) + if 'type' in video_encoder: + track_obj.update({'vcodec': video_encoder.get('type')}) + + formats.append(track_obj) self._sort_formats(formats) result_obj = {'formats': formats} - video_id = video.get('id') if video_id is not None: result_obj.update({'id': video_id}) @@ -165,15 +199,24 @@ class OpencastPlaylistIE(OpencastBaseIE): _API_BASE = 'https://%s/search/episode.json?sid=%s' - _TEST = { - 'url': 'https://oc-video1.ruhr-uni-bochum.de/engage/ui/index.html?epFrom=cf68a4a1-36b1-4a53-a6ba-61af5705a0d0', - 'md5': '554c8e99a90f7be7e874619fcf2a3bc9', - 'info_dict': { - 'id': 'cf68a4a1-36b1-4a53-a6ba-61af5705a0d0', - 'title': 'Kryptographie - WiSe 15/16', + _TESTS = [ + { + 'url': 'https://oc-video1.ruhr-uni-bochum.de/engage/ui/index.html?epFrom=cf68a4a1-36b1-4a53-a6ba-61af5705a0d0', + 'info_dict': { + 'id': 'cf68a4a1-36b1-4a53-a6ba-61af5705a0d0', + 'title': 'Kryptographie - WiSe 15/16', + }, + 'playlist_mincount': 28, }, - 'playlist_mincount': 28, - } + { + 'url': 'https://oc-video.ruhr-uni-bochum.de/engage/ui/index.html?e=1&p=1&epFrom=b1a54262-3684-403f-9731-8e77c3766f9a', + 'info_dict': { + 'id': 'b1a54262-3684-403f-9731-8e77c3766f9a', + 'title': 'inSTUDIES-Social movements and prefigurative politics in a global perspective', + }, + 'playlist_mincount': 8, + }, + ] def _real_extract(self, url): mobj = re.match(self._VALID_URL, url)