Skip to content

Commit b92bb0e

Browse files
committed
[viki] improve extraction(closes ytdl-org#26522)(closes ytdl-org#28203)
- extract uploader_url and episode_number - report login required error - extract 480p formats - fix API v4 calls
1 parent 40edffa commit b92bb0e

File tree

1 file changed

+44
-25
lines changed

1 file changed

+44
-25
lines changed

youtube_dl/extractor/viki.py

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
parse_iso8601,
2222
sanitized_Request,
2323
std_headers,
24+
try_get,
2425
)
2526

2627

@@ -30,7 +31,7 @@ class VikiBaseIE(InfoExtractor):
3031
_API_URL_TEMPLATE = 'https://api.viki.io%s&sig=%s'
3132

3233
_APP = '100005a'
33-
_APP_VERSION = '2.2.5.1428709186'
34+
_APP_VERSION = '6.0.0'
3435
_APP_SECRET = 'MM_d*yP@`&1@]@!AVrXf_o-HVEnoTnm$O-ti4[G~$JDI/Dc-&piU&z&5.;:}95=Iad'
3536

3637
_GEO_BYPASS = False
@@ -41,7 +42,7 @@ class VikiBaseIE(InfoExtractor):
4142
_ERRORS = {
4243
'geo': 'Sorry, this content is not available in your region.',
4344
'upcoming': 'Sorry, this content is not yet available.',
44-
# 'paywall': 'paywall',
45+
'paywall': 'Sorry, this content is only available to Viki Pass Plus subscribers',
4546
}
4647

4748
def _prepare_call(self, path, timestamp=None, post_data=None):
@@ -62,7 +63,8 @@ def _prepare_call(self, path, timestamp=None, post_data=None):
6263

6364
def _call_api(self, path, video_id, note, timestamp=None, post_data=None):
6465
resp = self._download_json(
65-
self._prepare_call(path, timestamp, post_data), video_id, note)
66+
self._prepare_call(path, timestamp, post_data), video_id, note,
67+
headers={'x-viki-app-ver': self._APP_VERSION})
6668

6769
error = resp.get('error')
6870
if error:
@@ -82,11 +84,13 @@ def _raise_error(self, error):
8284
expected=True)
8385

8486
def _check_errors(self, data):
85-
for reason, status in data.get('blocking', {}).items():
87+
for reason, status in (data.get('blocking') or {}).items():
8688
if status and reason in self._ERRORS:
8789
message = self._ERRORS[reason]
8890
if reason == 'geo':
8991
self.raise_geo_restricted(msg=message)
92+
elif reason == 'paywall':
93+
self.raise_login_required(message)
9094
raise ExtractorError('%s said: %s' % (
9195
self.IE_NAME, message), expected=True)
9296

@@ -131,13 +135,19 @@ class VikiIE(VikiBaseIE):
131135
'info_dict': {
132136
'id': '1023585v',
133137
'ext': 'mp4',
134-
'title': 'Heirs Episode 14',
135-
'uploader': 'SBS',
136-
'description': 'md5:c4b17b9626dd4b143dcc4d855ba3474e',
138+
'title': 'Heirs - Episode 14',
139+
'uploader': 'SBS Contents Hub',
140+
'timestamp': 1385047627,
137141
'upload_date': '20131121',
138142
'age_limit': 13,
143+
'duration': 3570,
144+
'episode_number': 14,
145+
},
146+
'params': {
147+
'format': 'bestvideo',
139148
},
140149
'skip': 'Blocked in the US',
150+
'expected_warnings': ['Unknown MIME type image/jpeg in DASH manifest'],
141151
}, {
142152
# clip
143153
'url': 'http://www.viki.com/videos/1067139v-the-avengers-age-of-ultron-press-conference',
@@ -153,7 +163,8 @@ class VikiIE(VikiBaseIE):
153163
'uploader': 'Arirang TV',
154164
'like_count': int,
155165
'age_limit': 0,
156-
}
166+
},
167+
'skip': 'Sorry. There was an error loading this video',
157168
}, {
158169
'url': 'http://www.viki.com/videos/1048879v-ankhon-dekhi',
159170
'info_dict': {
@@ -171,7 +182,7 @@ class VikiIE(VikiBaseIE):
171182
}, {
172183
# episode
173184
'url': 'http://www.viki.com/videos/44699v-boys-over-flowers-episode-1',
174-
'md5': '94e0e34fd58f169f40c184f232356cfe',
185+
'md5': '0a53dc252e6e690feccd756861495a8c',
175186
'info_dict': {
176187
'id': '44699v',
177188
'ext': 'mp4',
@@ -183,6 +194,10 @@ class VikiIE(VikiBaseIE):
183194
'uploader': 'group8',
184195
'like_count': int,
185196
'age_limit': 13,
197+
'episode_number': 1,
198+
},
199+
'params': {
200+
'format': 'bestvideo',
186201
},
187202
'expected_warnings': ['Unknown MIME type image/jpeg in DASH manifest'],
188203
}, {
@@ -209,7 +224,7 @@ class VikiIE(VikiBaseIE):
209224
}, {
210225
# non-English description
211226
'url': 'http://www.viki.com/videos/158036v-love-in-magic',
212-
'md5': 'adf9e321a0ae5d0aace349efaaff7691',
227+
'md5': '41faaba0de90483fb4848952af7c7d0d',
213228
'info_dict': {
214229
'id': '158036v',
215230
'ext': 'mp4',
@@ -220,6 +235,10 @@ class VikiIE(VikiBaseIE):
220235
'title': 'Love In Magic',
221236
'age_limit': 13,
222237
},
238+
'params': {
239+
'format': 'bestvideo',
240+
},
241+
'expected_warnings': ['Unknown MIME type image/jpeg in DASH manifest'],
223242
}]
224243

225244
def _real_extract(self, url):
@@ -229,36 +248,33 @@ def _real_extract(self, url):
229248
'https://www.viki.com/api/videos/' + video_id,
230249
video_id, 'Downloading video JSON', headers={
231250
'x-client-user-agent': std_headers['User-Agent'],
232-
'x-viki-app-ver': '4.0.57',
251+
'x-viki-app-ver': '3.0.0',
233252
})
234253
video = resp['video']
235254

236255
self._check_errors(video)
237256

238257
title = self.dict_selection(video.get('titles', {}), 'en', allow_fallback=False)
258+
episode_number = int_or_none(video.get('number'))
239259
if not title:
240-
title = 'Episode %d' % video.get('number') if video.get('type') == 'episode' else video.get('id') or video_id
241-
container_titles = video.get('container', {}).get('titles', {})
260+
title = 'Episode %d' % episode_number if video.get('type') == 'episode' else video.get('id') or video_id
261+
container_titles = try_get(video, lambda x: x['container']['titles'], dict) or {}
242262
container_title = self.dict_selection(container_titles, 'en')
243263
title = '%s - %s' % (container_title, title)
244264

245265
description = self.dict_selection(video.get('descriptions', {}), 'en')
246266

247-
duration = int_or_none(video.get('duration'))
248-
timestamp = parse_iso8601(video.get('created_at'))
249-
uploader = video.get('author')
250-
like_count = int_or_none(video.get('likes', {}).get('count'))
251-
age_limit = parse_age_limit(video.get('rating'))
267+
like_count = int_or_none(try_get(video, lambda x: x['likes']['count']))
252268

253269
thumbnails = []
254-
for thumbnail_id, thumbnail in video.get('images', {}).items():
270+
for thumbnail_id, thumbnail in (video.get('images') or {}).items():
255271
thumbnails.append({
256272
'id': thumbnail_id,
257273
'url': thumbnail.get('url'),
258274
})
259275

260276
subtitles = {}
261-
for subtitle_lang, _ in video.get('subtitle_completions', {}).items():
277+
for subtitle_lang, _ in (video.get('subtitle_completions') or {}).items():
262278
subtitles[subtitle_lang] = [{
263279
'ext': subtitles_format,
264280
'url': self._prepare_call(
@@ -269,13 +285,15 @@ def _real_extract(self, url):
269285
'id': video_id,
270286
'title': title,
271287
'description': description,
272-
'duration': duration,
273-
'timestamp': timestamp,
274-
'uploader': uploader,
288+
'duration': int_or_none(video.get('duration')),
289+
'timestamp': parse_iso8601(video.get('created_at')),
290+
'uploader': video.get('author'),
291+
'uploader_url': video.get('author_url'),
275292
'like_count': like_count,
276-
'age_limit': age_limit,
293+
'age_limit': parse_age_limit(video.get('rating')),
277294
'thumbnails': thumbnails,
278295
'subtitles': subtitles,
296+
'episode_number': episode_number,
279297
}
280298

281299
formats = []
@@ -360,7 +378,7 @@ class VikiChannelIE(VikiBaseIE):
360378
'info_dict': {
361379
'id': '50c',
362380
'title': 'Boys Over Flowers',
363-
'description': 'md5:ecd3cff47967fe193cff37c0bec52790',
381+
'description': 'md5:804ce6e7837e1fd527ad2f25420f4d59',
364382
},
365383
'playlist_mincount': 71,
366384
}, {
@@ -371,6 +389,7 @@ class VikiChannelIE(VikiBaseIE):
371389
'description': 'md5:05bf5471385aa8b21c18ad450e350525',
372390
},
373391
'playlist_count': 127,
392+
'skip': 'Page not found',
374393
}, {
375394
'url': 'http://www.viki.com/news/24569c-showbiz-korea',
376395
'only_matching': True,

0 commit comments

Comments
 (0)