[rutv] Fix live stream test URL
[youtube-dl] / youtube_dl / extractor / rutv.py
1 # encoding: 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     int_or_none
10 )
11
12
13 class RUTVIE(InfoExtractor):
14     IE_DESC = 'RUTV.RU'
15     _VALID_URL = r'''(?x)
16         https?://player\.(?:rutv\.ru|vgtrk\.com)/
17             (?P<path>flash2v/container\.swf\?id=
18             |iframe/(?P<type>swf|video|live)/id/
19             |index/iframe/cast_id/)
20             (?P<id>\d+)'''
21
22     _TESTS = [
23         {
24             'url': 'http://player.rutv.ru/flash2v/container.swf?id=774471&sid=kultura&fbv=true&isPlay=true&ssl=false&i=560&acc_video_id=episode_id/972347/video_id/978186/brand_id/31724',
25             'info_dict': {
26                 'id': '774471',
27                 'ext': 'mp4',
28                 'title': 'Монологи на все времена',
29                 'description': 'md5:18d8b5e6a41fb1faa53819471852d5d5',
30                 'duration': 2906,
31             },
32             'params': {
33                 # m3u8 download
34                 'skip_download': True,
35             },
36         },
37         {
38             'url': 'https://player.vgtrk.com/flash2v/container.swf?id=774016&sid=russiatv&fbv=true&isPlay=true&ssl=false&i=560&acc_video_id=episode_id/972098/video_id/977760/brand_id/57638',
39             'info_dict': {
40                 'id': '774016',
41                 'ext': 'mp4',
42                 'title': 'Чужой в семье Сталина',
43                 'description': '',
44                 'duration': 2539,
45             },
46             'params': {
47                 # m3u8 download
48                 'skip_download': True,
49             },
50         },
51         {
52             'url': 'http://player.rutv.ru/iframe/swf/id/766888/sid/hitech/?acc_video_id=4000',
53             'info_dict': {
54                 'id': '766888',
55                 'ext': 'mp4',
56                 'title': 'Вести.net: интернет-гиганты начали перетягивание программных "одеял"',
57                 'description': 'md5:65ddd47f9830c4f42ed6475f8730c995',
58                 'duration': 279,
59             },
60             'params': {
61                 # m3u8 download
62                 'skip_download': True,
63             },
64         },
65         {
66             'url': 'http://player.rutv.ru/iframe/video/id/771852/start_zoom/true/showZoomBtn/false/sid/russiatv/?acc_video_id=episode_id/970443/video_id/975648/brand_id/5169',
67             'info_dict': {
68                 'id': '771852',
69                 'ext': 'mp4',
70                 'title': 'Прямой эфир. Жертвы загадочной болезни: смерть от старости в 17 лет',
71                 'description': 'md5:b81c8c55247a4bd996b43ce17395b2d8',
72                 'duration': 3096,
73             },
74             'params': {
75                 # m3u8 download
76                 'skip_download': True,
77             },
78         },
79         {
80             'url': 'http://player.rutv.ru/iframe/live/id/51499/showZoomBtn/false/isPlay/true/sid/sochi2014',
81             'info_dict': {
82                 'id': '51499',
83                 'ext': 'flv',
84                 'title': 'Сочи-2014. Биатлон. Индивидуальная гонка. Мужчины ',
85                 'description': 'md5:9e0ed5c9d2fa1efbfdfed90c9a6d179c',
86             },
87             'skip': 'Translation has finished',
88         },
89         {
90             'url': 'http://player.rutv.ru/iframe/live/id/21/showZoomBtn/false/isPlay/true/',
91             'info_dict': {
92                 'id': '21',
93                 'ext': 'mp4',
94                 'title': 're:^Россия 24. Прямой эфир [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
95                 'is_live': True,
96             },
97             'params': {
98                 # m3u8 download
99                 'skip_download': True,
100             },
101         },
102     ]
103
104     @classmethod
105     def _extract_url(cls, webpage):
106         mobj = re.search(
107             r'<iframe[^>]+?src=(["\'])(?P<url>https?://player\.rutv\.ru/(?:iframe/(?:swf|video|live)/id|index/iframe/cast_id)/.+?)\1', webpage)
108         if mobj:
109             return mobj.group('url')
110
111         mobj = re.search(
112             r'<meta[^>]+?property=(["\'])og:video\1[^>]+?content=(["\'])(?P<url>https?://player\.(?:rutv\.ru|vgtrk\.com)/flash2v/container\.swf\?id=.+?\2)',
113             webpage)
114         if mobj:
115             return mobj.group('url')
116
117     def _real_extract(self, url):
118         mobj = re.match(self._VALID_URL, url)
119         video_id = mobj.group('id')
120         video_path = mobj.group('path')
121
122         if video_path.startswith('flash2v'):
123             video_type = 'video'
124         elif video_path.startswith('iframe'):
125             video_type = mobj.group('type')
126             if video_type == 'swf':
127                 video_type = 'video'
128         elif video_path.startswith('index/iframe/cast_id'):
129             video_type = 'live'
130
131         json_data = self._download_json(
132             'http://player.rutv.ru/iframe/%splay/id/%s' % ('live-' if video_type == 'live' else '', video_id),
133             video_id, 'Downloading JSON')
134
135         if json_data['errors']:
136             raise ExtractorError('%s said: %s' % (self.IE_NAME, json_data['errors']), expected=True)
137
138         playlist = json_data['data']['playlist']
139         medialist = playlist['medialist']
140         media = medialist[0]
141
142         if media['errors']:
143             raise ExtractorError('%s said: %s' % (self.IE_NAME, media['errors']), expected=True)
144
145         view_count = playlist.get('count_views')
146         priority_transport = playlist['priority_transport']
147
148         thumbnail = media['picture']
149         width = int_or_none(media['width'])
150         height = int_or_none(media['height'])
151         description = media['anons']
152         title = media['title']
153         duration = int_or_none(media.get('duration'))
154
155         formats = []
156
157         for transport, links in media['sources'].items():
158             for quality, url in links.items():
159                 if transport == 'rtmp':
160                     mobj = re.search(r'^(?P<url>rtmp://[^/]+/(?P<app>.+))/(?P<playpath>.+)$', url)
161                     if not mobj:
162                         continue
163                     fmt = {
164                         'url': mobj.group('url'),
165                         'play_path': mobj.group('playpath'),
166                         'app': mobj.group('app'),
167                         'page_url': 'http://player.rutv.ru',
168                         'player_url': 'http://player.rutv.ru/flash2v/osmf.swf?i=22',
169                         'rtmp_live': True,
170                         'ext': 'flv',
171                         'vbr': int(quality),
172                     }
173                 elif transport == 'm3u8':
174                     formats.extend(self._extract_m3u8_formats(url, video_id, 'mp4'))
175                     continue
176                 else:
177                     fmt = {
178                         'url': url
179                     }
180                 fmt.update({
181                     'width': width,
182                     'height': height,
183                     'format_id': '%s-%s' % (transport, quality),
184                     'preference': -1 if priority_transport == transport else -2,
185                 })
186                 formats.append(fmt)
187
188         if not formats:
189             raise ExtractorError('No media links available for %s' % video_id)
190
191         self._sort_formats(formats)
192
193         is_live = video_type == 'live'
194
195         return {
196             'id': video_id,
197             'title': self._live_title(title) if is_live else title,
198             'description': description,
199             'thumbnail': thumbnail,
200             'view_count': view_count,
201             'duration': duration,
202             'formats': formats,
203             'is_live': is_live,
204         }