]>
Commit | Line | Data |
---|---|---|
4cd70099 | 1 | import re |
2 | ||
3 | from .common import InfoExtractor | |
4 | from ..utils import ( | |
4cd70099 | 5 | int_or_none, |
6aaf96a3 | 6 | join_nonempty, |
4cd70099 | 7 | parse_duration, |
a7978f8e | 8 | urljoin, |
e897bd82 SS |
9 | xpath_element, |
10 | xpath_text, | |
4cd70099 | 11 | ) |
12 | ||
13 | ||
4e4db743 | 14 | class HBOBaseIE(InfoExtractor): |
4cd70099 | 15 | _FORMATS_INFO = { |
ca5ed022 RA |
16 | 'pro7': { |
17 | 'width': 1280, | |
18 | 'height': 720, | |
19 | }, | |
4cd70099 | 20 | '1920': { |
21 | 'width': 1280, | |
22 | 'height': 720, | |
23 | }, | |
ca5ed022 RA |
24 | 'pro6': { |
25 | 'width': 768, | |
26 | 'height': 432, | |
27 | }, | |
4cd70099 | 28 | '640': { |
29 | 'width': 768, | |
30 | 'height': 432, | |
31 | }, | |
ca5ed022 RA |
32 | 'pro5': { |
33 | 'width': 640, | |
34 | 'height': 360, | |
35 | }, | |
4cd70099 | 36 | 'highwifi': { |
37 | 'width': 640, | |
38 | 'height': 360, | |
39 | }, | |
40 | 'high3g': { | |
41 | 'width': 640, | |
42 | 'height': 360, | |
43 | }, | |
44 | 'medwifi': { | |
45 | 'width': 400, | |
46 | 'height': 224, | |
47 | }, | |
48 | 'med3g': { | |
49 | 'width': 400, | |
50 | 'height': 224, | |
51 | }, | |
52 | } | |
53 | ||
4e4db743 RA |
54 | def _extract_info(self, url, display_id): |
55 | video_data = self._download_xml(url, display_id) | |
a7978f8e RA |
56 | video_id = xpath_text(video_data, 'id', fatal=True) |
57 | episode_title = title = xpath_text(video_data, 'title', fatal=True) | |
58 | series = xpath_text(video_data, 'program') | |
59 | if series: | |
add96eb9 | 60 | title = f'{series} - {title}' |
4cd70099 | 61 | |
62 | formats = [] | |
63 | for source in xpath_element(video_data, 'videos', 'sources', True): | |
64 | if source.tag == 'size': | |
65 | path = xpath_text(source, './/path') | |
66 | if not path: | |
67 | continue | |
68 | width = source.attrib.get('width') | |
69 | format_info = self._FORMATS_INFO.get(width, {}) | |
70 | height = format_info.get('height') | |
71 | fmt = { | |
72 | 'url': path, | |
6aaf96a3 | 73 | 'format_id': join_nonempty('http'. height and f'{height}p'), |
4cd70099 | 74 | 'width': format_info.get('width'), |
75 | 'height': height, | |
76 | } | |
77 | rtmp = re.search(r'^(?P<url>rtmpe?://[^/]+/(?P<app>.+))/(?P<playpath>mp4:.+)$', path) | |
78 | if rtmp: | |
79 | fmt.update({ | |
80 | 'url': rtmp.group('url'), | |
81 | 'play_path': rtmp.group('playpath'), | |
82 | 'app': rtmp.group('app'), | |
83 | 'ext': 'flv', | |
84 | 'format_id': fmt['format_id'].replace('http', 'rtmp'), | |
85 | }) | |
86 | formats.append(fmt) | |
87 | else: | |
88 | video_url = source.text | |
89 | if not video_url: | |
90 | continue | |
91 | if source.tag == 'tarball': | |
92 | formats.extend(self._extract_m3u8_formats( | |
93 | video_url.replace('.tar', '/base_index_w8.m3u8'), | |
94 | video_id, 'mp4', 'm3u8_native', m3u8_id='hls', fatal=False)) | |
ca5ed022 | 95 | elif source.tag == 'hls': |
3f7409f7 RA |
96 | m3u8_formats = self._extract_m3u8_formats( |
97 | video_url.replace('.tar', '/base_index.m3u8'), | |
98 | video_id, 'mp4', 'm3u8_native', m3u8_id='hls', fatal=False) | |
99 | for f in m3u8_formats: | |
100 | if f.get('vcodec') == 'none' and not f.get('tbr'): | |
101 | f['tbr'] = int_or_none(self._search_regex( | |
102 | r'-(\d+)k/', f['url'], 'tbr', default=None)) | |
103 | formats.extend(m3u8_formats) | |
ca5ed022 RA |
104 | elif source.tag == 'dash': |
105 | formats.extend(self._extract_mpd_formats( | |
106 | video_url.replace('.tar', '/manifest.mpd'), | |
107 | video_id, mpd_id='dash', fatal=False)) | |
4cd70099 | 108 | else: |
109 | format_info = self._FORMATS_INFO.get(source.tag, {}) | |
110 | formats.append({ | |
add96eb9 | 111 | 'format_id': f'http-{source.tag}', |
4cd70099 | 112 | 'url': video_url, |
113 | 'width': format_info.get('width'), | |
114 | 'height': format_info.get('height'), | |
115 | }) | |
4cd70099 | 116 | |
117 | thumbnails = [] | |
118 | card_sizes = xpath_element(video_data, 'titleCardSizes') | |
119 | if card_sizes is not None: | |
120 | for size in card_sizes: | |
121 | path = xpath_text(size, 'path') | |
122 | if not path: | |
123 | continue | |
124 | width = int_or_none(size.get('width')) | |
125 | thumbnails.append({ | |
126 | 'id': width, | |
127 | 'url': path, | |
128 | 'width': width, | |
129 | }) | |
130 | ||
a7978f8e RA |
131 | subtitles = None |
132 | caption_url = xpath_text(video_data, 'captionUrl') | |
133 | if caption_url: | |
134 | subtitles = { | |
135 | 'en': [{ | |
136 | 'url': caption_url, | |
add96eb9 | 137 | 'ext': 'ttml', |
a7978f8e RA |
138 | }], |
139 | } | |
140 | ||
4cd70099 | 141 | return { |
142 | 'id': video_id, | |
143 | 'title': title, | |
71cdcb23 | 144 | 'duration': parse_duration(xpath_text(video_data, 'duration/tv14')), |
a7978f8e RA |
145 | 'series': series, |
146 | 'episode': episode_title, | |
4cd70099 | 147 | 'formats': formats, |
148 | 'thumbnails': thumbnails, | |
a7978f8e | 149 | 'subtitles': subtitles, |
4cd70099 | 150 | } |
4e4db743 RA |
151 | |
152 | ||
153 | class HBOIE(HBOBaseIE): | |
154 | IE_NAME = 'hbo' | |
155 | _VALID_URL = r'https?://(?:www\.)?hbo\.com/(?:video|embed)(?:/[^/]+)*/(?P<id>[^/?#]+)' | |
156 | _TEST = { | |
157 | 'url': 'https://www.hbo.com/video/game-of-thrones/seasons/season-8/videos/trailer', | |
158 | 'md5': '8126210656f433c452a21367f9ad85b3', | |
159 | 'info_dict': { | |
160 | 'id': '22113301', | |
161 | 'ext': 'mp4', | |
162 | 'title': 'Game of Thrones - Trailer', | |
163 | }, | |
164 | 'expected_warnings': ['Unknown MIME type application/mp4 in DASH manifest'], | |
165 | } | |
166 | ||
167 | def _real_extract(self, url): | |
168 | display_id = self._match_id(url) | |
169 | webpage = self._download_webpage(url, display_id) | |
170 | location_path = self._parse_json(self._html_search_regex( | |
171 | r'data-state="({.+?})"', webpage, 'state'), display_id)['video']['locationUrl'] | |
172 | return self._extract_info(urljoin(url, location_path), display_id) |