]>
Commit | Line | Data |
---|---|---|
1 | # coding: utf-8 | |
2 | from __future__ import unicode_literals | |
3 | ||
4 | import re | |
5 | ||
6 | from .common import InfoExtractor | |
7 | from ..utils import ( | |
8 | ExtractorError, | |
9 | float_or_none, | |
10 | int_or_none, | |
11 | parse_age_limit, | |
12 | try_get, | |
13 | url_or_none, | |
14 | ) | |
15 | ||
16 | ||
17 | class TvigleIE(InfoExtractor): | |
18 | IE_NAME = 'tvigle' | |
19 | IE_DESC = 'Интернет-телевидение Tvigle.ru' | |
20 | _VALID_URL = r'https?://(?:www\.)?(?:tvigle\.ru/(?:[^/]+/)+(?P<display_id>[^/]+)/$|cloud\.tvigle\.ru/video/(?P<id>\d+))' | |
21 | ||
22 | _GEO_BYPASS = False | |
23 | _GEO_COUNTRIES = ['RU'] | |
24 | ||
25 | _TESTS = [ | |
26 | { | |
27 | 'url': 'http://www.tvigle.ru/video/sokrat/', | |
28 | 'info_dict': { | |
29 | 'id': '1848932', | |
30 | 'display_id': 'sokrat', | |
31 | 'ext': 'mp4', | |
32 | 'title': 'Сократ', | |
33 | 'description': 'md5:d6b92ffb7217b4b8ebad2e7665253c17', | |
34 | 'duration': 6586, | |
35 | 'age_limit': 12, | |
36 | }, | |
37 | 'skip': 'georestricted', | |
38 | }, | |
39 | { | |
40 | 'url': 'http://www.tvigle.ru/video/vladimir-vysotskii/vedushchii-teleprogrammy-60-minut-ssha-o-vladimire-vysotskom/', | |
41 | 'info_dict': { | |
42 | 'id': '5142516', | |
43 | 'ext': 'flv', | |
44 | 'title': 'Ведущий телепрограммы «60 минут» (США) о Владимире Высоцком', | |
45 | 'description': 'md5:027f7dc872948f14c96d19b4178428a4', | |
46 | 'duration': 186.080, | |
47 | 'age_limit': 0, | |
48 | }, | |
49 | 'skip': 'georestricted', | |
50 | }, { | |
51 | 'url': 'https://cloud.tvigle.ru/video/5267604/', | |
52 | 'only_matching': True, | |
53 | } | |
54 | ] | |
55 | ||
56 | def _real_extract(self, url): | |
57 | mobj = re.match(self._VALID_URL, url) | |
58 | video_id = mobj.group('id') | |
59 | display_id = mobj.group('display_id') | |
60 | ||
61 | if not video_id: | |
62 | webpage = self._download_webpage(url, display_id) | |
63 | video_id = self._html_search_regex( | |
64 | (r'<div[^>]+class=["\']player["\'][^>]+id=["\'](\d+)', | |
65 | r'cloudId\s*=\s*["\'](\d+)', | |
66 | r'class="video-preview current_playing" id="(\d+)"'), | |
67 | webpage, 'video id') | |
68 | ||
69 | video_data = self._download_json( | |
70 | 'http://cloud.tvigle.ru/api/play/video/%s/' % video_id, display_id) | |
71 | ||
72 | item = video_data['playlist']['items'][0] | |
73 | ||
74 | videos = item.get('videos') | |
75 | ||
76 | error_message = item.get('errorMessage') | |
77 | if not videos and error_message: | |
78 | if item.get('isGeoBlocked') is True: | |
79 | self.raise_geo_restricted( | |
80 | msg=error_message, countries=self._GEO_COUNTRIES) | |
81 | else: | |
82 | raise ExtractorError( | |
83 | '%s returned error: %s' % (self.IE_NAME, error_message), | |
84 | expected=True) | |
85 | ||
86 | title = item['title'] | |
87 | description = item.get('description') | |
88 | thumbnail = item.get('thumbnail') | |
89 | duration = float_or_none(item.get('durationMilliseconds'), 1000) | |
90 | age_limit = parse_age_limit(item.get('ageRestrictions')) | |
91 | ||
92 | formats = [] | |
93 | for vcodec, url_or_fmts in item['videos'].items(): | |
94 | if vcodec == 'hls': | |
95 | m3u8_url = url_or_none(url_or_fmts) | |
96 | if not m3u8_url: | |
97 | continue | |
98 | formats.extend(self._extract_m3u8_formats( | |
99 | m3u8_url, video_id, ext='mp4', entry_protocol='m3u8_native', | |
100 | m3u8_id='hls', fatal=False)) | |
101 | elif vcodec == 'dash': | |
102 | mpd_url = url_or_none(url_or_fmts) | |
103 | if not mpd_url: | |
104 | continue | |
105 | formats.extend(self._extract_mpd_formats( | |
106 | mpd_url, video_id, mpd_id='dash', fatal=False)) | |
107 | else: | |
108 | if not isinstance(url_or_fmts, dict): | |
109 | continue | |
110 | for format_id, video_url in url_or_fmts.items(): | |
111 | if format_id == 'm3u8': | |
112 | continue | |
113 | video_url = url_or_none(video_url) | |
114 | if not video_url: | |
115 | continue | |
116 | height = self._search_regex( | |
117 | r'^(\d+)[pP]$', format_id, 'height', default=None) | |
118 | filesize = int_or_none(try_get( | |
119 | item, lambda x: x['video_files_size'][vcodec][format_id])) | |
120 | formats.append({ | |
121 | 'url': video_url, | |
122 | 'format_id': '%s-%s' % (vcodec, format_id), | |
123 | 'vcodec': vcodec, | |
124 | 'height': int_or_none(height), | |
125 | 'filesize': filesize, | |
126 | }) | |
127 | self._sort_formats(formats) | |
128 | ||
129 | return { | |
130 | 'id': video_id, | |
131 | 'display_id': display_id, | |
132 | 'title': title, | |
133 | 'description': description, | |
134 | 'thumbnail': thumbnail, | |
135 | 'duration': duration, | |
136 | 'age_limit': age_limit, | |
137 | 'formats': formats, | |
138 | } |