]>
Commit | Line | Data |
---|---|---|
c4da5ff9 | 1 | from ..utils import HEADRequest |
29f7c58a | 2 | from .common import InfoExtractor |
3 | ||
4 | ||
5 | class FujiTVFODPlus7IE(InfoExtractor): | |
c4da5ff9 Y |
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/' | |
b1cb0525 Y |
8 | _BITRATE_MAP = { |
9 | 300: (320, 180), | |
10 | 800: (640, 360), | |
11 | 1200: (1280, 720), | |
12 | 2000: (1280, 720), | |
13 | 4000: (1920, 1080), | |
14 | } | |
29f7c58a | 15 | |
61882afd | 16 | _TESTS = [{ |
c4da5ff9 | 17 | 'url': 'https://fod.fujitv.co.jp/title/5d40/5d40110076', |
61882afd | 18 | 'info_dict': { |
c4da5ff9 | 19 | 'id': '5d40110076', |
1d485a1a | 20 | 'ext': 'ts', |
c4da5ff9 Y |
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', | |
61882afd | 26 | }, |
b1cb0525 Y |
27 | }, { |
28 | 'url': 'https://fod.fujitv.co.jp/title/5d40/5d40810083', | |
29 | 'info_dict': { | |
30 | 'id': '5d40810083', | |
1d485a1a | 31 | 'ext': 'ts', |
b1cb0525 Y |
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' | |
61882afd Y |
38 | }] |
39 | ||
29f7c58a | 40 | def _real_extract(self, url): |
c4da5ff9 Y |
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: | |
8dcce6a8 | 48 | self.report_warning(f'The token cookie is needed to extract video metadata. {self._login_hint("cookies")}') |
c4da5ff9 Y |
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 | |
1d485a1a | 54 | fmt, subs = self._extract_m3u8_formats_and_subtitles(src['url'], video_id, 'ts') |
b1cb0525 Y |
55 | for f in fmt: |
56 | f.update(dict(zip(('height', 'width'), | |
57 | self._BITRATE_MAP.get(f.get('tbr'), ())))) | |
c4da5ff9 Y |
58 | formats.extend(fmt) |
59 | subtitles = self._merge_subtitles(subtitles, subs) | |
60 | self._sort_formats(formats, ['tbr']) | |
29f7c58a | 61 | |
62 | return { | |
63 | 'id': video_id, | |
c4da5ff9 Y |
64 | 'title': json_info.get('ep_title'), |
65 | 'series': json_info.get('lu_title'), | |
66 | 'series_id': series_id, | |
67 | 'description': json_info.get('ep_description'), | |
29f7c58a | 68 | 'formats': formats, |
c4da5ff9 Y |
69 | 'subtitles': subtitles, |
70 | 'thumbnail': f'{self._BASE_URL}img/program/{series_id}/episode/{video_id}_a.jpg', | |
29f7c58a | 71 | } |