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