]>
Commit | Line | Data |
---|---|---|
dcdb292f | 1 | # coding: utf-8 |
7d449fff | 2 | import json |
a294bce8 | 3 | |
0793a7b3 | 4 | from .common import InfoExtractor |
418424e5 | 5 | from ..utils import ( |
7d449fff | 6 | float_or_none, |
418424e5 | 7 | int_or_none, |
7d449fff PV |
8 | parse_codecs, |
9 | traverse_obj, | |
10 | urljoin, | |
418424e5 | 11 | ) |
0793a7b3 | 12 | |
13 | ||
14 | class StreamCZIE(InfoExtractor): | |
7d449fff | 15 | _VALID_URL = r'https?://(?:www\.)?(?:stream|televizeseznam)\.cz/[^?#]+/(?P<display_id>[^?#]+)-(?P<id>[0-9]+)' |
865dbd4a | 16 | _TESTS = [{ |
7d449fff PV |
17 | 'url': 'https://www.televizeseznam.cz/video/lajna/buh-57953890', |
18 | 'md5': '40c41ade1464a390a0b447e333df4239', | |
0793a7b3 | 19 | 'info_dict': { |
7d449fff | 20 | 'id': '57953890', |
0793a7b3 | 21 | 'ext': 'mp4', |
7d449fff PV |
22 | 'title': 'Bůh', |
23 | 'display_id': 'buh', | |
24 | 'description': 'md5:8f5f09b9b7bc67df910486cdd88f7165', | |
25 | } | |
865dbd4a | 26 | }, { |
7d449fff PV |
27 | 'url': 'https://www.stream.cz/tajemno/znicehonic-jim-skrz-strechu-prolitnul-zahadny-predmet-badatele-vse-objasnili-64147267', |
28 | 'md5': '3ee4d0be040e8f4a543e67e509d55e3f', | |
865dbd4a | 29 | 'info_dict': { |
7d449fff | 30 | 'id': '64147267', |
865dbd4a | 31 | 'ext': 'mp4', |
7d449fff PV |
32 | 'title': 'Zničehonic jim skrz střechu prolítnul záhadný předmět. Badatelé vše objasnili', |
33 | 'display_id': 'znicehonic-jim-skrz-strechu-prolitnul-zahadny-predmet-badatele-vse-objasnili', | |
34 | 'description': 'md5:1dcb5e010eb697dedc5942f76c5b3744', | |
35 | } | |
865dbd4a | 36 | }] |
0793a7b3 | 37 | |
7d449fff PV |
38 | def _extract_formats(self, spl_url, video): |
39 | for ext, pref, streams in ( | |
40 | ('ts', -1, traverse_obj(video, ('http_stream', 'qualities'))), | |
41 | ('mp4', 1, video.get('mp4'))): | |
42 | for format_id, stream in streams.items(): | |
43 | if not stream.get('url'): | |
44 | continue | |
45 | yield { | |
46 | 'format_id': f'{format_id}-{ext}', | |
47 | 'ext': ext, | |
48 | 'source_preference': pref, | |
49 | 'url': urljoin(spl_url, stream['url']), | |
50 | 'tbr': float_or_none(stream.get('bandwidth'), scale=1000), | |
51 | 'duration': float_or_none(stream.get('duration'), scale=1000), | |
52 | 'width': traverse_obj(stream, ('resolution', 0)), | |
53 | 'height': traverse_obj(stream, ('resolution', 1)) or int_or_none(format_id.replace('p', '')), | |
54 | **parse_codecs(stream.get('codec')), | |
55 | } | |
0793a7b3 | 56 | |
7d449fff PV |
57 | def _real_extract(self, url): |
58 | display_id, video_id = self._match_valid_url(url).groups() | |
0793a7b3 | 59 | |
7d449fff PV |
60 | data = self._download_json( |
61 | 'https://www.televizeseznam.cz/api/graphql', video_id, 'Downloading GraphQL result', | |
62 | data=json.dumps({ | |
63 | 'variables': {'urlName': video_id}, | |
64 | 'query': ''' | |
65 | query LoadEpisode($urlName : String){ episode(urlName: $urlName){ ...VideoDetailFragmentOnEpisode } } | |
66 | fragment VideoDetailFragmentOnEpisode on Episode { | |
67 | id | |
68 | spl | |
69 | urlName | |
70 | name | |
71 | perex | |
72 | duration | |
73 | views | |
74 | }''' | |
75 | }).encode('utf-8'), | |
76 | headers={'Content-Type': 'application/json;charset=UTF-8'} | |
77 | )['data']['episode'] | |
20e35880 | 78 | |
7d449fff PV |
79 | spl_url = data['spl'] + 'spl2,3' |
80 | metadata = self._download_json(spl_url, video_id, 'Downloading playlist') | |
81 | if 'Location' in metadata and 'data' not in metadata: | |
82 | spl_url = metadata['Location'] | |
83 | metadata = self._download_json(spl_url, video_id, 'Downloading redirected playlist') | |
84 | video = metadata['data'] | |
20e35880 | 85 | |
afdb387c | 86 | subtitles = {} |
7d449fff PV |
87 | for subs in video.get('subtitles', {}).values(): |
88 | if not subs.get('language'): | |
89 | continue | |
90 | for ext, sub_url in subs.get('urls').items(): | |
91 | subtitles.setdefault(subs['language'], []).append({ | |
92 | 'ext': ext, | |
93 | 'url': urljoin(spl_url, sub_url) | |
94 | }) | |
95 | ||
96 | formats = list(self._extract_formats(spl_url, video)) | |
97 | self._sort_formats(formats) | |
afdb387c | 98 | |
0793a7b3 | 99 | return { |
20e35880 | 100 | 'id': video_id, |
7d449fff PV |
101 | 'display_id': display_id, |
102 | 'title': data.get('name'), | |
103 | 'description': data.get('perex'), | |
104 | 'duration': float_or_none(data.get('duration')), | |
20e35880 | 105 | 'view_count': int_or_none(data.get('views')), |
7d449fff | 106 | 'formats': formats, |
afdb387c | 107 | 'subtitles': subtitles, |
0793a7b3 | 108 | } |