]>
Commit | Line | Data |
---|---|---|
1 | from ..utils import HEADRequest | |
2 | from .common import InfoExtractor | |
3 | ||
4 | ||
5 | class FujiTVFODPlus7IE(InfoExtractor): | |
6 | _VALID_URL = r'https?://fod\.fujitv\.co\.jp/title/(?P<sid>[0-9a-z]{4})/(?P<id>[0-9a-z]+)' | |
7 | _BASE_URL = 'https://i.fod.fujitv.co.jp/' | |
8 | _BITRATE_MAP = { | |
9 | 300: (320, 180), | |
10 | 800: (640, 360), | |
11 | 1200: (1280, 720), | |
12 | 2000: (1280, 720), | |
13 | 4000: (1920, 1080), | |
14 | } | |
15 | ||
16 | _TESTS = [{ | |
17 | 'url': 'https://fod.fujitv.co.jp/title/5d40/5d40110076', | |
18 | 'info_dict': { | |
19 | 'id': '5d40110076', | |
20 | 'ext': 'ts', | |
21 | 'title': '#1318 『まる子、まぼろしの洋館を見る』の巻', | |
22 | 'series': 'ちびまる子ちゃん', | |
23 | 'series_id': '5d40', | |
24 | 'description': 'md5:b3f51dbfdda162ac4f789e0ff4d65750', | |
25 | 'thumbnail': 'https://i.fod.fujitv.co.jp/img/program/5d40/episode/5d40110076_a.jpg', | |
26 | }, | |
27 | }, { | |
28 | 'url': 'https://fod.fujitv.co.jp/title/5d40/5d40810083', | |
29 | 'info_dict': { | |
30 | 'id': '5d40810083', | |
31 | 'ext': 'ts', | |
32 | 'title': '#1324 『まる子とオニの子』の巻/『結成!2月をムダにしない会』の巻', | |
33 | 'description': 'md5:3972d900b896adc8ab1849e310507efa', | |
34 | 'series': 'ちびまる子ちゃん', | |
35 | 'series_id': '5d40', | |
36 | 'thumbnail': 'https://i.fod.fujitv.co.jp/img/program/5d40/episode/5d40810083_a.jpg'}, | |
37 | 'skip': 'Video available only in one week' | |
38 | }] | |
39 | ||
40 | def _real_extract(self, url): | |
41 | series_id, video_id = self._match_valid_url(url).groups() | |
42 | self._request_webpage(HEADRequest(url), video_id) | |
43 | json_info = {} | |
44 | token = self._get_cookies(url).get('CT') | |
45 | if token: | |
46 | json_info = self._download_json('https://fod-sp.fujitv.co.jp/apps/api/episode/detail/?ep_id=%s&is_premium=false' % video_id, video_id, headers={'x-authorization': f'Bearer {token.value}'}, fatal=False) | |
47 | else: | |
48 | self.report_warning(f'The token cookie is needed to extract video metadata. {self._login_hint("cookies")}') | |
49 | formats, subtitles = [], {} | |
50 | src_json = self._download_json(f'{self._BASE_URL}abrjson_v2/tv_android/{video_id}', video_id) | |
51 | for src in src_json['video_selector']: | |
52 | if not src.get('url'): | |
53 | continue | |
54 | fmt, subs = self._extract_m3u8_formats_and_subtitles(src['url'], video_id, 'ts') | |
55 | for f in fmt: | |
56 | f.update(dict(zip(('height', 'width'), | |
57 | self._BITRATE_MAP.get(f.get('tbr'), ())))) | |
58 | formats.extend(fmt) | |
59 | subtitles = self._merge_subtitles(subtitles, subs) | |
60 | ||
61 | return { | |
62 | 'id': video_id, | |
63 | 'title': json_info.get('ep_title'), | |
64 | 'series': json_info.get('lu_title'), | |
65 | 'series_id': series_id, | |
66 | 'description': json_info.get('ep_description'), | |
67 | 'formats': formats, | |
68 | 'subtitles': subtitles, | |
69 | 'thumbnail': f'{self._BASE_URL}img/program/{series_id}/episode/{video_id}_a.jpg', | |
70 | '_format_sort_fields': ('tbr', ) | |
71 | } |