]>
Commit | Line | Data |
---|---|---|
02dbf93f | 1 | import operator |
d5822b96 PH |
2 | import re |
3 | ||
4 | from .common import InfoExtractor | |
5 | from ..utils import ( | |
02dbf93f PH |
6 | parse_xml_doc, |
7 | unified_strdate, | |
d5822b96 PH |
8 | ) |
9 | ||
0b7c2485 | 10 | |
d5822b96 | 11 | class ZDFIE(InfoExtractor): |
0b7c2485 | 12 | _VALID_URL = r'^http://www\.zdf\.de\/ZDFmediathek(?P<hash>#)?\/(.*beitrag\/video\/)(?P<video_id>[^/\?]+)(?:\?.*)?' |
d5822b96 PH |
13 | |
14 | def _real_extract(self, url): | |
15 | mobj = re.match(self._VALID_URL, url) | |
d5822b96 PH |
16 | video_id = mobj.group('video_id') |
17 | ||
02dbf93f PH |
18 | xml_url = u'http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?ak=web&id=%s' % video_id |
19 | info_xml = self._download_webpage( | |
20 | xml_url, video_id, note=u'Downloading video info') | |
21 | doc = parse_xml_doc(info_xml) | |
0b7c2485 | 22 | |
02dbf93f PH |
23 | title = doc.find('.//information/title').text |
24 | description = doc.find('.//information/detail').text | |
25 | uploader_node = doc.find('.//details/originChannelTitle') | |
26 | uploader = None if uploader_node is None else uploader_node.text | |
27 | duration_str = doc.find('.//details/length').text | |
28 | duration_m = re.match(r'''(?x)^ | |
29 | (?P<hours>[0-9]{2}) | |
30 | :(?P<minutes>[0-9]{2}) | |
31 | :(?P<seconds>[0-9]{2}) | |
32 | (?:\.(?P<ms>[0-9]+)?) | |
33 | ''', duration_str) | |
34 | duration = ( | |
35 | ( | |
36 | (int(duration_m.group('hours')) * 60 * 60) + | |
37 | (int(duration_m.group('minutes')) * 60) + | |
38 | int(duration_m.group('seconds')) | |
39 | ) | |
40 | if duration_m | |
41 | else None | |
42 | ) | |
43 | upload_date = unified_strdate(doc.find('.//details/airtime').text) | |
d5822b96 | 44 | |
02dbf93f PH |
45 | def xml_to_format(fnode): |
46 | video_url = fnode.find('url').text | |
47 | is_available = u'http://www.metafilegenerator' not in video_url | |
48 | ||
49 | format_id = fnode.attrib['basetype'] | |
50 | format_m = re.match(r'''(?x) | |
51 | (?P<vcodec>[^_]+)_(?P<acodec>[^_]+)_(?P<container>[^_]+)_ | |
52 | (?P<proto>[^_]+)_(?P<index>[^_]+)_(?P<indexproto>[^_]+) | |
53 | ''', format_id) | |
54 | ||
c059bdd4 PH |
55 | ext = format_m.group('container') |
56 | is_supported = ext != 'f4f' | |
57 | ||
02dbf93f | 58 | PROTO_ORDER = ['http', 'rtmp', 'rtsp'] |
0b7c2485 | 59 | try: |
02dbf93f | 60 | proto_pref = -PROTO_ORDER.index(format_m.group('proto')) |
0b7c2485 | 61 | except ValueError: |
02dbf93f | 62 | proto_pref = 999 |
0b7c2485 | 63 | |
02dbf93f PH |
64 | quality = fnode.find('./quality').text |
65 | QUALITY_ORDER = ['veryhigh', '300', 'high', 'med', 'low'] | |
0b7c2485 | 66 | try: |
02dbf93f | 67 | quality_pref = -QUALITY_ORDER.index(quality) |
0b7c2485 PH |
68 | except ValueError: |
69 | quality_pref = 999 | |
70 | ||
02dbf93f PH |
71 | abr = int(fnode.find('./audioBitrate').text) // 1000 |
72 | vbr = int(fnode.find('./videoBitrate').text) // 1000 | |
c059bdd4 PH |
73 | pref = (is_available, is_supported, |
74 | proto_pref, quality_pref, vbr, abr) | |
75 | ||
76 | format_note = u'' | |
77 | if not is_supported: | |
78 | format_note += u'(unsupported)' | |
79 | if not format_note: | |
80 | format_note = None | |
d5822b96 | 81 | |
02dbf93f | 82 | return { |
c059bdd4 | 83 | 'format_id': format_id + u'-' + quality, |
02dbf93f | 84 | 'url': video_url, |
c059bdd4 | 85 | 'ext': ext, |
02dbf93f PH |
86 | 'acodec': format_m.group('acodec'), |
87 | 'vcodec': format_m.group('vcodec'), | |
88 | 'abr': abr, | |
89 | 'vbr': vbr, | |
90 | 'width': int(fnode.find('./width').text), | |
91 | 'height': int(fnode.find('./height').text), | |
02dbf93f | 92 | 'filesize': int(fnode.find('./filesize').text), |
c059bdd4 | 93 | 'format_note': format_note, |
02dbf93f | 94 | '_pref': pref, |
c059bdd4 | 95 | '_available': is_available, |
02dbf93f | 96 | } |
d5822b96 | 97 | |
02dbf93f | 98 | format_nodes = doc.findall('.//formitaeten/formitaet') |
c059bdd4 PH |
99 | formats = sorted(filter(lambda f: f['_available'], |
100 | map(xml_to_format, format_nodes)), | |
02dbf93f | 101 | key=operator.itemgetter('_pref')) |
d5822b96 | 102 | |
0b7c2485 PH |
103 | return { |
104 | 'id': video_id, | |
0b7c2485 | 105 | 'title': title, |
02dbf93f PH |
106 | 'formats': formats, |
107 | 'description': description, | |
108 | 'uploader': uploader, | |
109 | 'duration': duration, | |
110 | 'upload_date': upload_date, | |
0b7c2485 | 111 | } |