]>
Commit | Line | Data |
---|---|---|
ed86f38a JMF |
1 | from __future__ import unicode_literals |
2 | ||
e9bf7479 JMF |
3 | import re |
4 | import json | |
5 | ||
6 | from .common import InfoExtractor | |
7 | from ..utils import ( | |
e35cb78c | 8 | compat_str, |
10e3d734 | 9 | determine_ext, |
f8b56e95 | 10 | ExtractorError, |
e9bf7479 | 11 | xpath_with_ns, |
e9bf7479 JMF |
12 | ) |
13 | ||
14 | _x = lambda p: xpath_with_ns(p, {'smil': 'http://www.w3.org/2005/SMIL21/Language'}) | |
15 | ||
16 | ||
17 | class ThePlatformIE(InfoExtractor): | |
a97bcd80 JMF |
18 | _VALID_URL = r'''(?x) |
19 | (?:https?://(?:link|player)\.theplatform\.com/[sp]/[^/]+/ | |
020cf5eb | 20 | (?P<config>(?:[^/\?]+/(?:swf|config)|onsite)/select/)? |
a97bcd80 | 21 | |theplatform:)(?P<id>[^/\?&]+)''' |
e9bf7479 JMF |
22 | |
23 | _TEST = { | |
24 | # from http://www.metacafe.com/watch/cb-e9I_cZgTgIPd/blackberrys_big_bold_z30/ | |
ed86f38a JMF |
25 | 'url': 'http://link.theplatform.com/s/dJ5BDC/e9I_cZgTgIPd/meta.smil?format=smil&Tracking=true&mbr=true', |
26 | 'info_dict': { | |
27 | 'id': 'e9I_cZgTgIPd', | |
28 | 'ext': 'flv', | |
29 | 'title': 'Blackberry\'s big, bold Z30', | |
30 | 'description': 'The Z30 is Blackberry\'s biggest, baddest mobile messaging device yet.', | |
31 | 'duration': 247, | |
e9bf7479 | 32 | }, |
ed86f38a | 33 | 'params': { |
e9bf7479 | 34 | # rtmp download |
ed86f38a | 35 | 'skip_download': True, |
e9bf7479 JMF |
36 | }, |
37 | } | |
5f6a1245 | 38 | |
10e3d734 PH |
39 | def _real_extract(self, url): |
40 | mobj = re.match(self._VALID_URL, url) | |
41 | video_id = mobj.group('id') | |
42 | if mobj.group('config'): | |
5f6a1245 | 43 | config_url = url + '&form=json' |
10e3d734 PH |
44 | config_url = config_url.replace('swf/', 'config/') |
45 | config_url = config_url.replace('onsite/', 'onsite/config/') | |
46 | config = self._download_json(config_url, video_id, 'Downloading config') | |
47 | smil_url = config['releaseUrl'] + '&format=SMIL&formats=MPEG4&manifest=f4m' | |
48 | else: | |
49 | smil_url = ('http://link.theplatform.com/s/dJ5BDC/{0}/meta.smil?' | |
9e1a5b84 | 50 | 'format=smil&mbr=true'.format(video_id)) |
e9bf7479 | 51 | |
10e3d734 | 52 | meta = self._download_xml(smil_url, video_id) |
f8b56e95 PH |
53 | try: |
54 | error_msg = next( | |
55 | n.attrib['abstract'] | |
56 | for n in meta.findall(_x('.//smil:ref')) | |
ed86f38a | 57 | if n.attrib.get('title') == 'Geographic Restriction') |
f8b56e95 PH |
58 | except StopIteration: |
59 | pass | |
60 | else: | |
61 | raise ExtractorError(error_msg, expected=True) | |
62 | ||
e9bf7479 JMF |
63 | info_url = 'http://link.theplatform.com/s/dJ5BDC/{0}?format=preview'.format(video_id) |
64 | info_json = self._download_webpage(info_url, video_id) | |
65 | info = json.loads(info_json) | |
66 | ||
67 | head = meta.find(_x('smil:head')) | |
68 | body = meta.find(_x('smil:body')) | |
360babf7 | 69 | |
22d99a80 | 70 | f4m_node = body.find(_x('smil:seq//smil:video')) |
e35cb78c | 71 | if f4m_node is not None and '.f4m' in f4m_node.attrib['src']: |
020cf5eb JMF |
72 | f4m_url = f4m_node.attrib['src'] |
73 | if 'manifest.f4m?' not in f4m_url: | |
74 | f4m_url += '?' | |
75 | # the parameters are from syfy.com, other sites may use others, | |
76 | # they also work for nbc.com | |
77 | f4m_url += '&g=UXWGVKRWHFSP&hdcore=3.0.3' | |
dd41e8c8 | 78 | formats = self._extract_f4m_formats(f4m_url, video_id) |
a97bcd80 | 79 | else: |
a97bcd80 | 80 | formats = [] |
e35cb78c JMF |
81 | switch = body.find(_x('smil:switch')) |
82 | if switch is not None: | |
83 | base_url = head.find(_x('smil:meta')).attrib['base'] | |
84 | for f in switch.findall(_x('smil:video')): | |
85 | attr = f.attrib | |
86 | width = int(attr['width']) | |
87 | height = int(attr['height']) | |
88 | vbr = int(attr['system-bitrate']) // 1000 | |
89 | format_id = '%dx%d_%dk' % (width, height, vbr) | |
90 | formats.append({ | |
91 | 'format_id': format_id, | |
92 | 'url': base_url, | |
93 | 'play_path': 'mp4:' + attr['src'], | |
94 | 'ext': 'flv', | |
95 | 'width': width, | |
96 | 'height': height, | |
97 | 'vbr': vbr, | |
98 | }) | |
99 | else: | |
100 | switch = body.find(_x('smil:seq//smil:switch')) | |
101 | for f in switch.findall(_x('smil:video')): | |
102 | attr = f.attrib | |
103 | vbr = int(attr['system-bitrate']) // 1000 | |
10e3d734 PH |
104 | ext = determine_ext(attr['src']) |
105 | if ext == 'once': | |
106 | ext = 'mp4' | |
e35cb78c JMF |
107 | formats.append({ |
108 | 'format_id': compat_str(vbr), | |
109 | 'url': attr['src'], | |
110 | 'vbr': vbr, | |
10e3d734 | 111 | 'ext': ext, |
e35cb78c | 112 | }) |
a97bcd80 | 113 | self._sort_formats(formats) |
e9bf7479 JMF |
114 | |
115 | return { | |
116 | 'id': video_id, | |
117 | 'title': info['title'], | |
118 | 'formats': formats, | |
119 | 'description': info['description'], | |
120 | 'thumbnail': info['defaultThumbnailUrl'], | |
2514d263 | 121 | 'duration': info['duration'] // 1000, |
e9bf7479 | 122 | } |