]>
Commit | Line | Data |
---|---|---|
185744f9 RA |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | from .common import InfoExtractor | |
5 | from ..compat import compat_str | |
6 | from ..utils import ( | |
7 | unescapeHTML, | |
8 | int_or_none, | |
9 | ) | |
10 | ||
11 | ||
12 | class LEGOIE(InfoExtractor): | |
13 | _VALID_URL = r'https?://(?:www\.)?lego\.com/(?:[^/]+/)*videos/(?:[^/]+/)*[^/?#]+-(?P<id>[0-9a-f]+)' | |
14 | _TEST = { | |
15 | 'url': 'http://www.lego.com/en-us/videos/themes/club/blocumentary-kawaguchi-55492d823b1b4d5e985787fa8c2973b1', | |
16 | 'md5': 'f34468f176cfd76488767fc162c405fa', | |
17 | 'info_dict': { | |
18 | 'id': '55492d823b1b4d5e985787fa8c2973b1', | |
19 | 'ext': 'mp4', | |
20 | 'title': 'Blocumentary Great Creations: Akiyuki Kawaguchi', | |
21 | } | |
22 | } | |
23 | _BITRATES = [256, 512, 1024, 1536, 2560] | |
24 | ||
25 | def _real_extract(self, url): | |
26 | video_id = self._match_id(url) | |
27 | webpage = self._download_webpage( | |
28 | 'http://www.lego.com/en-US/mediaplayer/video/' + video_id, video_id) | |
29 | title = self._search_regex(r'<title>(.+?)</title>', webpage, 'title') | |
30 | video_data = self._parse_json(unescapeHTML(self._search_regex( | |
31 | r"video='([^']+)'", webpage, 'video data')), video_id) | |
32 | progressive_base = self._search_regex( | |
33 | r'data-video-progressive-url="([^"]+)"', | |
34 | webpage, 'progressive base', default='https://lc-mediaplayerns-live-s.legocdn.com/') | |
35 | streaming_base = self._search_regex( | |
36 | r'data-video-streaming-url="([^"]+)"', | |
37 | webpage, 'streaming base', default='http://legoprod-f.akamaihd.net/') | |
38 | item_id = video_data['ItemId'] | |
39 | ||
40 | net_storage_path = video_data.get('NetStoragePath') or '/'.join([item_id[:2], item_id[2:4]]) | |
41 | base_path = '_'.join([item_id, video_data['VideoId'], video_data['Locale'], compat_str(video_data['VideoVersion'])]) | |
42 | path = '/'.join([net_storage_path, base_path]) | |
43 | streaming_path = ','.join(map(lambda bitrate: compat_str(bitrate), self._BITRATES)) | |
44 | ||
45 | formats = self._extract_akamai_formats( | |
46 | '%si/s/public/%s_,%s,.mp4.csmil/master.m3u8' % (streaming_base, path, streaming_path), video_id) | |
47 | m3u8_formats = list(filter( | |
48 | lambda f: f.get('protocol') == 'm3u8_native' and f.get('vcodec') != 'none' and f.get('resolution') != 'multiple', | |
49 | formats)) | |
50 | if len(m3u8_formats) == len(self._BITRATES): | |
51 | self._sort_formats(m3u8_formats) | |
52 | for bitrate, m3u8_format in zip(self._BITRATES, m3u8_formats): | |
53 | progressive_base_url = '%spublic/%s_%d.' % (progressive_base, path, bitrate) | |
54 | mp4_f = m3u8_format.copy() | |
55 | mp4_f.update({ | |
56 | 'url': progressive_base_url + 'mp4', | |
57 | 'format_id': m3u8_format['format_id'].replace('hls', 'mp4'), | |
58 | 'protocol': 'http', | |
59 | }) | |
60 | web_f = { | |
61 | 'url': progressive_base_url + 'webm', | |
62 | 'format_id': m3u8_format['format_id'].replace('hls', 'webm'), | |
63 | 'width': m3u8_format['width'], | |
64 | 'height': m3u8_format['height'], | |
65 | 'tbr': m3u8_format.get('tbr'), | |
66 | 'ext': 'webm', | |
67 | } | |
68 | formats.extend([web_f, mp4_f]) | |
69 | else: | |
70 | for bitrate in self._BITRATES: | |
71 | for ext in ('web', 'mp4'): | |
72 | formats.append({ | |
73 | 'format_id': '%s-%s' % (ext, bitrate), | |
74 | 'url': '%spublic/%s_%d.%s' % (progressive_base, path, bitrate, ext), | |
75 | 'tbr': bitrate, | |
76 | 'ext': ext, | |
77 | }) | |
78 | self._sort_formats(formats) | |
79 | ||
80 | return { | |
81 | 'id': video_id, | |
82 | 'title': title, | |
83 | 'thumbnail': video_data.get('CoverImageUrl'), | |
84 | 'duration': int_or_none(video_data.get('Length')), | |
85 | 'formats': formats, | |
86 | } |