]> jfr.im git - yt-dlp.git/blame - yt_dlp/extractor/arkena.py
[ie/orf:on] Improve extraction (#9677)
[yt-dlp.git] / yt_dlp / extractor / arkena.py
CommitLineData
bbe1f363
S
1from .common import InfoExtractor
2from ..utils import (
1f766b6e 3 ExtractorError,
bbe1f363
S
4 float_or_none,
5 int_or_none,
bbe1f363 6 parse_iso8601,
4dfbf869 7 parse_qs,
29f7c58a 8 try_get,
bbe1f363
S
9)
10
11
12class ArkenaIE(InfoExtractor):
1f766b6e
S
13 _VALID_URL = r'''(?x)
14 https?://
15 (?:
29f7c58a 16 video\.(?:arkena|qbrick)\.com/play2/embed/player\?|
1f766b6e
S
17 play\.arkena\.com/(?:config|embed)/avp/v\d/player/media/(?P<id>[^/]+)/[^/]+/(?P<account_id>\d+)
18 )
19 '''
bfd973ec 20 # See https://support.arkena.com/display/PLAY/Ways+to+embed+your+video
21 _EMBED_REGEX = [r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//play\.arkena\.com/embed/avp/.+?)\1']
bbe1f363 22 _TESTS = [{
29f7c58a 23 'url': 'https://video.qbrick.com/play2/embed/player?accountId=1034090&mediaId=d8ab4607-00090107-aab86310',
24 'md5': '97f117754e5f3c020f5f26da4a44ebaf',
bbe1f363 25 'info_dict': {
29f7c58a 26 'id': 'd8ab4607-00090107-aab86310',
bbe1f363 27 'ext': 'mp4',
29f7c58a 28 'title': 'EM_HT20_117_roslund_v2.mp4',
29 'timestamp': 1608285912,
30 'upload_date': '20201218',
31 'duration': 1429.162667,
32 'subtitles': {
33 'sv': 'count:3',
34 },
bbe1f363 35 },
29f7c58a 36 }, {
37 'url': 'https://play.arkena.com/embed/avp/v2/player/media/b41dda37-d8e7-4d3f-b1b5-9a9db578bdfe/1/129411',
38 'only_matching': True,
bbe1f363
S
39 }, {
40 'url': 'https://play.arkena.com/config/avp/v2/player/media/b41dda37-d8e7-4d3f-b1b5-9a9db578bdfe/1/129411/?callbackMethod=jQuery1111023664739129262213_1469227693893',
41 'only_matching': True,
42 }, {
43 'url': 'http://play.arkena.com/config/avp/v1/player/media/327336/darkmatter/131064/?callbackMethod=jQuery1111002221189684892677_1469227595972',
44 'only_matching': True,
45 }, {
46 'url': 'http://play.arkena.com/embed/avp/v1/player/media/327336/darkmatter/131064/',
47 'only_matching': True,
1f766b6e
S
48 }, {
49 'url': 'http://video.arkena.com/play2/embed/player?accountId=472718&mediaId=35763b3b-00090078-bf604299&pageStyling=styled',
50 'only_matching': True,
bbe1f363
S
51 }]
52
bbe1f363 53 def _real_extract(self, url):
5ad28e7f 54 mobj = self._match_valid_url(url)
bbe1f363
S
55 video_id = mobj.group('id')
56 account_id = mobj.group('account_id')
57
1f766b6e
S
58 # Handle http://video.arkena.com/play2/embed/player URL
59 if not video_id:
4dfbf869 60 qs = parse_qs(url)
1f766b6e
S
61 video_id = qs.get('mediaId', [None])[0]
62 account_id = qs.get('accountId', [None])[0]
63 if not video_id or not account_id:
64 raise ExtractorError('Invalid URL', expected=True)
65
29f7c58a 66 media = self._download_json(
67 'https://video.qbrick.com/api/v1/public/accounts/%s/medias/%s' % (account_id, video_id),
68 video_id, query={
69 # https://video.qbrick.com/docs/api/examples/library-api.html
70 'fields': 'asset/resources/*/renditions/*(height,id,language,links/*(href,mimeType),type,size,videos/*(audios/*(codec,sampleRate),bitrate,codec,duration,height,width),width),created,metadata/*(title,description),tags',
71 })
72 metadata = media.get('metadata') or {}
73 title = metadata['title']
bbe1f363 74
29f7c58a 75 duration = None
bbe1f363 76 formats = []
29f7c58a 77 thumbnails = []
78 subtitles = {}
79 for resource in media['asset']['resources']:
80 for rendition in (resource.get('renditions') or []):
81 rendition_type = rendition.get('type')
82 for i, link in enumerate(rendition.get('links') or []):
83 href = link.get('href')
84 if not href:
85 continue
86 if rendition_type == 'image':
87 thumbnails.append({
88 'filesize': int_or_none(rendition.get('size')),
89 'height': int_or_none(rendition.get('height')),
90 'id': rendition.get('id'),
91 'url': href,
92 'width': int_or_none(rendition.get('width')),
93 })
94 elif rendition_type == 'subtitle':
95 subtitles.setdefault(rendition.get('language') or 'en', []).append({
96 'url': href,
97 })
98 elif rendition_type == 'video':
99 f = {
100 'filesize': int_or_none(rendition.get('size')),
101 'format_id': rendition.get('id'),
102 'url': href,
103 }
104 video = try_get(rendition, lambda x: x['videos'][i], dict)
105 if video:
106 if not duration:
107 duration = float_or_none(video.get('duration'))
108 f.update({
109 'height': int_or_none(video.get('height')),
110 'tbr': int_or_none(video.get('bitrate'), 1000),
111 'vcodec': video.get('codec'),
112 'width': int_or_none(video.get('width')),
113 })
114 audio = try_get(video, lambda x: x['audios'][0], dict)
115 if audio:
116 f.update({
117 'acodec': audio.get('codec'),
118 'asr': int_or_none(audio.get('sampleRate')),
119 })
120 formats.append(f)
121 elif rendition_type == 'index':
122 mime_type = link.get('mimeType')
123 if mime_type == 'application/smil+xml':
124 formats.extend(self._extract_smil_formats(
125 href, video_id, fatal=False))
126 elif mime_type == 'application/x-mpegURL':
127 formats.extend(self._extract_m3u8_formats(
128 href, video_id, 'mp4', 'm3u8_native',
129 m3u8_id='hls', fatal=False))
130 elif mime_type == 'application/hds+xml':
131 formats.extend(self._extract_f4m_formats(
132 href, video_id, f4m_id='hds', fatal=False))
133 elif mime_type == 'application/dash+xml':
134 formats.extend(self._extract_f4m_formats(
135 href, video_id, f4m_id='hds', fatal=False))
136 elif mime_type == 'application/vnd.ms-sstr+xml':
137 formats.extend(self._extract_ism_formats(
138 href, video_id, ism_id='mss', fatal=False))
bbe1f363 139
bbe1f363
S
140 return {
141 'id': video_id,
142 'title': title,
29f7c58a 143 'description': metadata.get('description'),
144 'timestamp': parse_iso8601(media.get('created')),
bbe1f363 145 'thumbnails': thumbnails,
29f7c58a 146 'subtitles': subtitles,
147 'duration': duration,
148 'tags': media.get('tags'),
bbe1f363
S
149 'formats': formats,
150 }