]>
Commit | Line | Data |
---|---|---|
80f772c2 | 1 | # coding: utf-8 |
b54a2da4 YCH |
2 | from __future__ import unicode_literals, division |
3 | ||
80f772c2 | 4 | from .common import InfoExtractor |
5 | from ..utils import int_or_none | |
6 | ||
7 | ||
8 | class CrackleIE(InfoExtractor): | |
abd29a2c | 9 | _GEO_COUNTRIES = ['US'] |
23b35a63 | 10 | _VALID_URL = r'(?:crackle:|https?://(?:(?:www|m)\.)?crackle\.com/(?:playlist/\d+/|(?:[^/]+/)+))(?P<id>\d+)' |
80f772c2 | 11 | _TEST = { |
b54a2da4 | 12 | 'url': 'http://www.crackle.com/comedians-in-cars-getting-coffee/2498934', |
80f772c2 | 13 | 'info_dict': { |
b54a2da4 | 14 | 'id': '2498934', |
80f772c2 | 15 | 'ext': 'mp4', |
b54a2da4 YCH |
16 | 'title': 'Everybody Respects A Bloody Nose', |
17 | 'description': 'Jerry is kaffeeklatsching in L.A. with funnyman J.B. Smoove (Saturday Night Live, Real Husbands of Hollywood). They’re headed for brew at 10 Speed Coffee in a 1964 Studebaker Avanti.', | |
ec85ded8 | 18 | 'thumbnail': r're:^https?://.*\.jpg', |
b54a2da4 YCH |
19 | 'duration': 906, |
20 | 'series': 'Comedians In Cars Getting Coffee', | |
21 | 'season_number': 8, | |
22 | 'episode_number': 4, | |
23 | 'subtitles': { | |
1f9fefe7 TF |
24 | 'en-US': [ |
25 | {'ext': 'vtt'}, | |
26 | {'ext': 'tt'}, | |
27 | ] | |
b54a2da4 | 28 | }, |
80f772c2 | 29 | }, |
30 | 'params': { | |
31 | # m3u8 download | |
32 | 'skip_download': True, | |
33 | } | |
34 | } | |
35 | ||
23b35a63 RA |
36 | _THUMBNAIL_RES = [ |
37 | (120, 90), | |
38 | (208, 156), | |
39 | (220, 124), | |
40 | (220, 220), | |
41 | (240, 180), | |
42 | (250, 141), | |
43 | (315, 236), | |
44 | (320, 180), | |
45 | (360, 203), | |
46 | (400, 300), | |
47 | (421, 316), | |
48 | (460, 330), | |
49 | (460, 460), | |
50 | (462, 260), | |
51 | (480, 270), | |
52 | (587, 330), | |
53 | (640, 480), | |
54 | (700, 330), | |
55 | (700, 394), | |
56 | (854, 480), | |
57 | (1024, 1024), | |
58 | (1920, 1080), | |
59 | ] | |
60 | ||
80f772c2 | 61 | # extracted from http://legacyweb-us.crackle.com/flash/ReferrerRedirect.ashx |
62 | _MEDIA_FILE_SLOTS = { | |
63 | 'c544.flv': { | |
64 | 'width': 544, | |
65 | 'height': 306, | |
66 | }, | |
67 | '360p.mp4': { | |
68 | 'width': 640, | |
69 | 'height': 360, | |
70 | }, | |
71 | '480p.mp4': { | |
72 | 'width': 852, | |
73 | 'height': 478, | |
74 | }, | |
75 | '480p_1mbps.mp4': { | |
76 | 'width': 852, | |
77 | 'height': 478, | |
78 | }, | |
79 | } | |
80 | ||
81 | def _real_extract(self, url): | |
82 | video_id = self._match_id(url) | |
b54a2da4 YCH |
83 | |
84 | config_doc = self._download_xml( | |
85 | 'http://legacyweb-us.crackle.com/flash/QueryReferrer.ashx?site=16', | |
86 | video_id, 'Downloading config') | |
87 | ||
80f772c2 | 88 | item = self._download_xml( |
47d205a6 | 89 | 'http://legacyweb-us.crackle.com/app/revamp/vidwallcache.aspx?flags=-1&fm=%s' % video_id, |
23b35a63 | 90 | video_id, headers=self.geo_verification_headers()).find('i') |
80f772c2 | 91 | title = item.attrib['t'] |
92 | ||
80f772c2 | 93 | subtitles = {} |
47d205a6 | 94 | formats = self._extract_m3u8_formats( |
b54a2da4 | 95 | 'http://content.uplynk.com/ext/%s/%s.m3u8' % (config_doc.attrib['strUplynkOwnerId'], video_id), |
a1188d0e | 96 | video_id, 'mp4', m3u8_id='hls', fatal=None) |
23b35a63 | 97 | thumbnails = [] |
80f772c2 | 98 | path = item.attrib.get('p') |
99 | if path: | |
23b35a63 RA |
100 | for width, height in self._THUMBNAIL_RES: |
101 | res = '%dx%d' % (width, height) | |
102 | thumbnails.append({ | |
103 | 'id': res, | |
104 | 'url': 'http://images-us-am.crackle.com/%stnl_%s.jpg' % (path, res), | |
105 | 'width': width, | |
106 | 'height': height, | |
107 | 'resolution': res, | |
108 | }) | |
80f772c2 | 109 | http_base_url = 'http://ahttp.crackle.com/' + path |
110 | for mfs_path, mfs_info in self._MEDIA_FILE_SLOTS.items(): | |
111 | formats.append({ | |
112 | 'url': http_base_url + mfs_path, | |
a1188d0e | 113 | 'format_id': 'http-' + mfs_path.split('.')[0], |
80f772c2 | 114 | 'width': mfs_info['width'], |
115 | 'height': mfs_info['height'], | |
116 | }) | |
117 | for cc in item.findall('cc'): | |
118 | locale = cc.attrib.get('l') | |
119 | v = cc.attrib.get('v') | |
120 | if locale and v: | |
121 | if locale not in subtitles: | |
122 | subtitles[locale] = [] | |
23b35a63 RA |
123 | for url_ext, ext in (('vtt', 'vtt'), ('xml', 'tt')): |
124 | subtitles.setdefault(locale, []).append({ | |
125 | 'url': '%s/%s%s_%s.%s' % (config_doc.attrib['strSubtitleServer'], path, locale, v, url_ext), | |
126 | 'ext': ext, | |
127 | }) | |
47d205a6 | 128 | self._sort_formats(formats, ('width', 'height', 'tbr', 'format_id')) |
80f772c2 | 129 | |
130 | return { | |
131 | 'id': video_id, | |
132 | 'title': title, | |
133 | 'description': item.attrib.get('d'), | |
b54a2da4 | 134 | 'duration': int(item.attrib.get('r'), 16) / 1000 if item.attrib.get('r') else None, |
80f772c2 | 135 | 'series': item.attrib.get('sn'), |
136 | 'season_number': int_or_none(item.attrib.get('se')), | |
137 | 'episode_number': int_or_none(item.attrib.get('ep')), | |
23b35a63 | 138 | 'thumbnails': thumbnails, |
80f772c2 | 139 | 'subtitles': subtitles, |
140 | 'formats': formats, | |
141 | } |