]>
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', | |
50e93e03 | 25 | 'duration': 1369.6, |
26 | 'view_count': int, | |
27 | } | |
28 | }, { | |
29 | 'url': 'https://www.stream.cz/kdo-to-mluvi/kdo-to-mluvi-velke-odhaleni-prinasi-novy-porad-uz-od-25-srpna-64087937', | |
30 | 'md5': '41fd358000086a1ccdb068c77809b158', | |
31 | 'info_dict': { | |
32 | 'id': '64087937', | |
33 | 'ext': 'mp4', | |
34 | 'title': 'Kdo to mluví? Velké odhalení přináší nový pořad už od 25. srpna', | |
35 | 'display_id': 'kdo-to-mluvi-velke-odhaleni-prinasi-novy-porad-uz-od-25-srpna', | |
36 | 'description': 'md5:97a811000a6460266029d6c1c2ebcd59', | |
37 | 'duration': 50.2, | |
38 | 'view_count': int, | |
7d449fff | 39 | } |
865dbd4a | 40 | }, { |
7d449fff PV |
41 | 'url': 'https://www.stream.cz/tajemno/znicehonic-jim-skrz-strechu-prolitnul-zahadny-predmet-badatele-vse-objasnili-64147267', |
42 | 'md5': '3ee4d0be040e8f4a543e67e509d55e3f', | |
865dbd4a | 43 | 'info_dict': { |
7d449fff | 44 | 'id': '64147267', |
865dbd4a | 45 | 'ext': 'mp4', |
7d449fff PV |
46 | 'title': 'Zničehonic jim skrz střechu prolítnul záhadný předmět. Badatelé vše objasnili', |
47 | 'display_id': 'znicehonic-jim-skrz-strechu-prolitnul-zahadny-predmet-badatele-vse-objasnili', | |
50e93e03 | 48 | 'description': 'md5:4b8ada6718d34bb011c4e04ca4bc19bf', |
49 | 'duration': 442.84, | |
50 | 'view_count': int, | |
7d449fff | 51 | } |
865dbd4a | 52 | }] |
0793a7b3 | 53 | |
7d449fff PV |
54 | def _extract_formats(self, spl_url, video): |
55 | for ext, pref, streams in ( | |
56 | ('ts', -1, traverse_obj(video, ('http_stream', 'qualities'))), | |
57 | ('mp4', 1, video.get('mp4'))): | |
58 | for format_id, stream in streams.items(): | |
59 | if not stream.get('url'): | |
60 | continue | |
61 | yield { | |
62 | 'format_id': f'{format_id}-{ext}', | |
63 | 'ext': ext, | |
64 | 'source_preference': pref, | |
65 | 'url': urljoin(spl_url, stream['url']), | |
66 | 'tbr': float_or_none(stream.get('bandwidth'), scale=1000), | |
67 | 'duration': float_or_none(stream.get('duration'), scale=1000), | |
68 | 'width': traverse_obj(stream, ('resolution', 0)), | |
69 | 'height': traverse_obj(stream, ('resolution', 1)) or int_or_none(format_id.replace('p', '')), | |
70 | **parse_codecs(stream.get('codec')), | |
71 | } | |
0793a7b3 | 72 | |
7d449fff PV |
73 | def _real_extract(self, url): |
74 | display_id, video_id = self._match_valid_url(url).groups() | |
0793a7b3 | 75 | |
7d449fff PV |
76 | data = self._download_json( |
77 | 'https://www.televizeseznam.cz/api/graphql', video_id, 'Downloading GraphQL result', | |
78 | data=json.dumps({ | |
79 | 'variables': {'urlName': video_id}, | |
80 | 'query': ''' | |
81 | query LoadEpisode($urlName : String){ episode(urlName: $urlName){ ...VideoDetailFragmentOnEpisode } } | |
82 | fragment VideoDetailFragmentOnEpisode on Episode { | |
83 | id | |
84 | spl | |
85 | urlName | |
86 | name | |
87 | perex | |
88 | duration | |
89 | views | |
90 | }''' | |
91 | }).encode('utf-8'), | |
92 | headers={'Content-Type': 'application/json;charset=UTF-8'} | |
93 | )['data']['episode'] | |
20e35880 | 94 | |
7d449fff PV |
95 | spl_url = data['spl'] + 'spl2,3' |
96 | metadata = self._download_json(spl_url, video_id, 'Downloading playlist') | |
97 | if 'Location' in metadata and 'data' not in metadata: | |
98 | spl_url = metadata['Location'] | |
99 | metadata = self._download_json(spl_url, video_id, 'Downloading redirected playlist') | |
100 | video = metadata['data'] | |
20e35880 | 101 | |
afdb387c | 102 | subtitles = {} |
7d449fff PV |
103 | for subs in video.get('subtitles', {}).values(): |
104 | if not subs.get('language'): | |
105 | continue | |
106 | for ext, sub_url in subs.get('urls').items(): | |
107 | subtitles.setdefault(subs['language'], []).append({ | |
108 | 'ext': ext, | |
109 | 'url': urljoin(spl_url, sub_url) | |
110 | }) | |
111 | ||
112 | formats = list(self._extract_formats(spl_url, video)) | |
113 | self._sort_formats(formats) | |
afdb387c | 114 | |
0793a7b3 | 115 | return { |
20e35880 | 116 | 'id': video_id, |
7d449fff PV |
117 | 'display_id': display_id, |
118 | 'title': data.get('name'), | |
119 | 'description': data.get('perex'), | |
120 | 'duration': float_or_none(data.get('duration')), | |
20e35880 | 121 | 'view_count': int_or_none(data.get('views')), |
7d449fff | 122 | 'formats': formats, |
afdb387c | 123 | 'subtitles': subtitles, |
0793a7b3 | 124 | } |