]>
Commit | Line | Data |
---|---|---|
2e7c8cab ZJ |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | from .common import InfoExtractor | |
2e7c8cab ZJ |
5 | from ..utils import ( |
6 | ExtractorError, | |
d2e96a8e | 7 | qualities, |
2e7c8cab ZJ |
8 | ) |
9 | ||
d2e96a8e | 10 | |
2e7c8cab ZJ |
11 | class PandaTVIE(InfoExtractor): |
12 | IE_DESC = '熊猫TV' | |
13 | _VALID_URL = r'http://(?:www\.)?panda\.tv/(?P<id>[0-9]+)' | |
d2e96a8e | 14 | _TEST = { |
2e7c8cab ZJ |
15 | 'url': 'http://www.panda.tv/10091', |
16 | 'info_dict': { | |
17 | 'id': '10091', | |
18 | 'title': 're:.+', | |
19 | 'uploader': '囚徒', | |
20 | 'ext': 'flv', | |
21 | 'is_live': True, | |
22 | }, | |
23 | 'params': { | |
24 | 'skip_download': True, | |
25 | }, | |
d2e96a8e S |
26 | 'skip': 'Live stream is offline', |
27 | } | |
2e7c8cab ZJ |
28 | |
29 | def _real_extract(self, url): | |
30 | video_id = self._match_id(url) | |
31 | ||
32 | config = self._download_json( | |
d2e96a8e | 33 | 'http://www.panda.tv/api_room?roomid=%s' % video_id, video_id) |
2e7c8cab ZJ |
34 | |
35 | error_code = config.get('errno', 0) | |
36 | if error_code is not 0: | |
d2e96a8e S |
37 | raise ExtractorError( |
38 | '%s returned error %s: %s' | |
39 | % (self.IE_NAME, error_code, config['errmsg']), | |
40 | expected=True) | |
2e7c8cab | 41 | |
d2e96a8e | 42 | data = config['data'] |
2e7c8cab ZJ |
43 | video_info = data['videoinfo'] |
44 | ||
45 | # 2 = live, 3 = offline | |
46 | if video_info.get('status') != '2': | |
47 | raise ExtractorError( | |
48 | 'Live stream is offline', expected=True) | |
49 | ||
50 | title = data['roominfo']['name'] | |
51 | uploader = data.get('hostinfo', {}).get('name') | |
52 | room_key = video_info['room_key'] | |
d2e96a8e S |
53 | stream_addr = video_info.get( |
54 | 'stream_addr', {'OD': '1', 'HD': '1', 'SD': '1'}) | |
2e7c8cab | 55 | |
d2e96a8e S |
56 | # Reverse engineered from web player swf |
57 | # (http://s6.pdim.gs/static/07153e425f581151.swf at the moment of | |
58 | # writing). | |
2e7c8cab ZJ |
59 | plflag0, plflag1 = video_info['plflag'].split('_') |
60 | plflag0 = int(plflag0) - 1 | |
61 | if plflag1 == '21': | |
62 | plflag0 = 10 | |
63 | plflag1 = '4' | |
64 | live_panda = 'live_panda' if plflag0 < 1 else '' | |
65 | ||
66 | quality_key = qualities(['OD', 'HD', 'SD']) | |
67 | suffix = ['_small', '_mid', ''] | |
68 | formats = [] | |
69 | for k, v in stream_addr.items(): | |
d2e96a8e S |
70 | if v != '1': |
71 | continue | |
72 | quality = quality_key(k) | |
73 | if quality <= 0: | |
74 | continue | |
75 | for pref, (ext, pl) in enumerate((('m3u8', '-hls'), ('flv', ''))): | |
76 | formats.append({ | |
77 | 'url': 'http://pl%s%s.live.panda.tv/live_panda/%s%s%s.%s' | |
78 | % (pl, plflag1, room_key, live_panda, suffix[quality], ext), | |
79 | 'format_id': '%s-%s' % (k, ext), | |
80 | 'quality': quality, | |
81 | 'source_preference': pref, | |
82 | }) | |
2e7c8cab ZJ |
83 | self._sort_formats(formats) |
84 | ||
85 | return { | |
86 | 'id': video_id, | |
87 | 'title': self._live_title(title), | |
88 | 'uploader': uploader, | |
89 | 'formats': formats, | |
90 | 'is_live': True, | |
91 | } |