From 1ba1fb1327f4375307190fa516b07f4f65905fce Mon Sep 17 00:00:00 2001 From: HobbyistDev Date: Tue, 13 Feb 2024 20:37:26 +0800 Subject: [PATCH] [viu:ott] Fix indonesian (and probably malaysian) viu extraction --- yt_dlp/extractor/viu.py | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/yt_dlp/extractor/viu.py b/yt_dlp/extractor/viu.py index 279d79721..eea44d3c2 100644 --- a/yt_dlp/extractor/viu.py +++ b/yt_dlp/extractor/viu.py @@ -8,7 +8,9 @@ from ..compat import compat_str from ..utils import ( ExtractorError, + float_or_none, int_or_none, + merge_dicts, remove_end, strip_or_none, traverse_obj, @@ -196,6 +198,21 @@ class ViuOTTIE(InfoExtractor): 'noplaylist': False, }, 'skip': 'Geo-restricted to Hong Kong', + }, { + 'url': 'https://www.viu.com/ott/id/id/vod/1130404/Dr-Stone-Stone-Wars', + 'info_dict': { + 'id': '1130404', + 'ext': 'mp4', + 'duration': 1440.0, + 'title': 'Dr. Stone: Stone Wars - Dr. Stone: Stone Wars - Episode 11', + 'episode_number': 11, + 'episode': 'Dr. Stone: Stone Wars - Dr. Stone: Stone Wars - Episode 11', + 'description': 'md5:65aa14cb80e0d18acf829513b6d64297', + 'series': 'Dr. Stone: Stone Wars', + 'series_id': '35837', + 'thumbnail': 'https://prod-images.viu.com/clip_asset_v6/1165917542/1165917580/e31e9fb2dc0d38db7f6c9b4de1f62d55d5fdfb80', + + } }] _AREA_ID = { @@ -271,6 +288,68 @@ def _real_extract(self, url): url, idata = unsmuggle_url(url, {}) country_code, lang_code, video_id = self._match_valid_url(url).groups() + if country_code in ('id'): + webpage = self._download_webpage(url, video_id) + json_ld = self._search_json_ld(webpage, video_id) + next_js_data = self._search_nextjs_data(webpage, video_id)['props'] + runtime_info = next_js_data['initialState']['app']['runtimeInfo'] + + product_detail_json = traverse_obj(next_js_data, ('pageProps', 'fallback', lambda k, v: v if re.match(r'@"PRODUCT_DETAIL"[^:]+', k) else None), get_all=False) + current_product_info = traverse_obj(product_detail_json, ('data', 'current_product')) + current_product_subtitle_info = current_product_info.get('subtitle') + + formats, subtitles = [], {} + + for subtitle_info in current_product_subtitle_info: + subtitles.setdefault(subtitle_info.get('code'), []).append({ + 'url': subtitle_info.get('url'), + 'name': subtitle_info.get('name') + }) + + stream_info_json = self._download_json('https://api-gateway-global.viu.com/api/playback/distribute', video_id, query={ + 'platform_flag_label': 'web', + 'area_id': runtime_info.get('areaId') or 1000, + 'language_flag_id': int_or_none(runtime_info.get('languageFlagId'), default=3), + 'countryCode': country_code.upper(), + 'ccs_product_id': current_product_info.get('ccs_product_id') + }, headers={ + 'Authorization': f'Bearer {self._get_token(country_code, video_id)}' + }) + + stream_urls = traverse_obj(stream_info_json, ('data', 'stream', ('url', 'airplayurl'), lambda _, v: v)) + + for stream_url in stream_urls: + fmts, subs = self._extract_m3u8_formats_and_subtitles(stream_url, video_id, fatal=False) + formats.extend(fmts) + self._merge_subtitles(subs, target=subtitles) + + return merge_dicts({ + 'id': video_id, + 'formats': formats, + 'subtitles': subtitles, + 'thumbnails': json_ld.get('thumbnails'), + }, + traverse_obj(json_ld, { + 'thumbnails': 'thumbnails', + 'title': 'title', + 'episode': 'episode', + 'episode_number': 'episode_number' + }), + traverse_obj(current_product_info, { + 'description': 'description', + 'thumbnail': ('cover_image_url', {url_or_none}), + 'duration': ('time_duration', {float_or_none}), + 'episode_number': ('number', {float_or_none}), + + }), + traverse_obj(product_detail_json, ('data', 'series', { + 'series_id': 'series_id', + 'series': 'name' + })), + { + 'title': self._html_search_meta(['og:title'], webpage), + 'thumbnail': self._html_search_meta(['og:image'], webpage)} + ) query = { 'r': 'vod/ajax-detail', 'platform_flag_label': 'web',