|
|
@ -1637,12 +1637,12 @@ class InfoExtractor(object):
|
|
|
|
segment_template = element.find(_add_ns('SegmentTemplate'))
|
|
|
|
segment_template = element.find(_add_ns('SegmentTemplate'))
|
|
|
|
if segment_template is not None:
|
|
|
|
if segment_template is not None:
|
|
|
|
extract_common(segment_template)
|
|
|
|
extract_common(segment_template)
|
|
|
|
media_template = segment_template.get('media')
|
|
|
|
media = segment_template.get('media')
|
|
|
|
if media_template:
|
|
|
|
if media:
|
|
|
|
ms_info['media_template'] = media_template
|
|
|
|
ms_info['media'] = media
|
|
|
|
initialization = segment_template.get('initialization')
|
|
|
|
initialization = segment_template.get('initialization')
|
|
|
|
if initialization:
|
|
|
|
if initialization:
|
|
|
|
ms_info['initialization_url'] = initialization
|
|
|
|
ms_info['initialization'] = initialization
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
extract_Initialization(segment_template)
|
|
|
|
extract_Initialization(segment_template)
|
|
|
|
return ms_info
|
|
|
|
return ms_info
|
|
|
@ -1686,6 +1686,7 @@ class InfoExtractor(object):
|
|
|
|
lang = representation_attrib.get('lang')
|
|
|
|
lang = representation_attrib.get('lang')
|
|
|
|
url_el = representation.find(_add_ns('BaseURL'))
|
|
|
|
url_el = representation.find(_add_ns('BaseURL'))
|
|
|
|
filesize = int_or_none(url_el.attrib.get('{http://youtube.com/yt/2012/10/10}contentLength') if url_el is not None else None)
|
|
|
|
filesize = int_or_none(url_el.attrib.get('{http://youtube.com/yt/2012/10/10}contentLength') if url_el is not None else None)
|
|
|
|
|
|
|
|
bandwidth = int_or_none(representation_attrib.get('bandwidth'))
|
|
|
|
f = {
|
|
|
|
f = {
|
|
|
|
'format_id': '%s-%s' % (mpd_id, representation_id) if mpd_id else representation_id,
|
|
|
|
'format_id': '%s-%s' % (mpd_id, representation_id) if mpd_id else representation_id,
|
|
|
|
'url': base_url,
|
|
|
|
'url': base_url,
|
|
|
@ -1693,7 +1694,7 @@ class InfoExtractor(object):
|
|
|
|
'ext': mimetype2ext(mime_type),
|
|
|
|
'ext': mimetype2ext(mime_type),
|
|
|
|
'width': int_or_none(representation_attrib.get('width')),
|
|
|
|
'width': int_or_none(representation_attrib.get('width')),
|
|
|
|
'height': int_or_none(representation_attrib.get('height')),
|
|
|
|
'height': int_or_none(representation_attrib.get('height')),
|
|
|
|
'tbr': int_or_none(representation_attrib.get('bandwidth'), 1000),
|
|
|
|
'tbr': int_or_none(bandwidth, 1000),
|
|
|
|
'asr': int_or_none(representation_attrib.get('audioSamplingRate')),
|
|
|
|
'asr': int_or_none(representation_attrib.get('audioSamplingRate')),
|
|
|
|
'fps': int_or_none(representation_attrib.get('frameRate')),
|
|
|
|
'fps': int_or_none(representation_attrib.get('frameRate')),
|
|
|
|
'language': lang if lang not in ('mul', 'und', 'zxx', 'mis') else None,
|
|
|
|
'language': lang if lang not in ('mul', 'und', 'zxx', 'mis') else None,
|
|
|
@ -1702,13 +1703,32 @@ class InfoExtractor(object):
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.update(parse_codecs(representation_attrib.get('codecs')))
|
|
|
|
f.update(parse_codecs(representation_attrib.get('codecs')))
|
|
|
|
representation_ms_info = extract_multisegment_info(representation, adaption_set_ms_info)
|
|
|
|
representation_ms_info = extract_multisegment_info(representation, adaption_set_ms_info)
|
|
|
|
if 'segment_urls' not in representation_ms_info and 'media_template' in representation_ms_info:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
media_template = representation_ms_info['media_template']
|
|
|
|
def prepare_template(template_name, identifiers):
|
|
|
|
media_template = media_template.replace('$RepresentationID$', representation_id)
|
|
|
|
t = representation_ms_info[template_name]
|
|
|
|
media_template = re.sub(r'\$(Number|Bandwidth|Time)\$', r'%(\1)d', media_template)
|
|
|
|
t = t.replace('$RepresentationID$', representation_id)
|
|
|
|
media_template = re.sub(r'\$(Number|Bandwidth|Time)%([^$]+)\$', r'%(\1)\2', media_template)
|
|
|
|
t = re.sub(r'\$(%s)\$' % '|'.join(identifiers), r'%(\1)d', t)
|
|
|
|
media_template.replace('$$', '$')
|
|
|
|
t = re.sub(r'\$(%s)%%([^$]+)\$' % '|'.join(identifiers), r'%(\1)\2', t)
|
|
|
|
|
|
|
|
t.replace('$$', '$')
|
|
|
|
|
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# @initialization is a regular template like @media one
|
|
|
|
|
|
|
|
# so it should be handled just the same way (see
|
|
|
|
|
|
|
|
# https://github.com/rg3/youtube-dl/issues/11605)
|
|
|
|
|
|
|
|
if 'initialization' in representation_ms_info:
|
|
|
|
|
|
|
|
initialization_template = prepare_template(
|
|
|
|
|
|
|
|
'initialization',
|
|
|
|
|
|
|
|
# As per [1, 5.3.9.4.2, Table 15, page 54] $Number$ and
|
|
|
|
|
|
|
|
# $Time$ shall not be included for @initialization thus
|
|
|
|
|
|
|
|
# only $Bandwidth$ remains
|
|
|
|
|
|
|
|
('Bandwidth', ))
|
|
|
|
|
|
|
|
representation_ms_info['initialization_url'] = initialization_template % {
|
|
|
|
|
|
|
|
'Bandwidth': bandwidth,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if 'segment_urls' not in representation_ms_info and 'media' in representation_ms_info:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
media_template = prepare_template('media', ('Number', 'Bandwidth', 'Time'))
|
|
|
|
|
|
|
|
|
|
|
|
# As per [1, 5.3.9.4.4, Table 16, page 55] $Number$ and $Time$
|
|
|
|
# As per [1, 5.3.9.4.4, Table 16, page 55] $Number$ and $Time$
|
|
|
|
# can't be used at the same time
|
|
|
|
# can't be used at the same time
|
|
|
@ -1720,7 +1740,7 @@ class InfoExtractor(object):
|
|
|
|
representation_ms_info['fragments'] = [{
|
|
|
|
representation_ms_info['fragments'] = [{
|
|
|
|
'url': media_template % {
|
|
|
|
'url': media_template % {
|
|
|
|
'Number': segment_number,
|
|
|
|
'Number': segment_number,
|
|
|
|
'Bandwidth': int_or_none(representation_attrib.get('bandwidth')),
|
|
|
|
'Bandwidth': bandwidth,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'duration': segment_duration,
|
|
|
|
'duration': segment_duration,
|
|
|
|
} for segment_number in range(
|
|
|
|
} for segment_number in range(
|
|
|
@ -1738,7 +1758,7 @@ class InfoExtractor(object):
|
|
|
|
def add_segment_url():
|
|
|
|
def add_segment_url():
|
|
|
|
segment_url = media_template % {
|
|
|
|
segment_url = media_template % {
|
|
|
|
'Time': segment_time,
|
|
|
|
'Time': segment_time,
|
|
|
|
'Bandwidth': int_or_none(representation_attrib.get('bandwidth')),
|
|
|
|
'Bandwidth': bandwidth,
|
|
|
|
'Number': segment_number,
|
|
|
|
'Number': segment_number,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
representation_ms_info['fragments'].append({
|
|
|
|
representation_ms_info['fragments'].append({
|
|
|
@ -1780,7 +1800,7 @@ class InfoExtractor(object):
|
|
|
|
'protocol': 'http_dash_segments',
|
|
|
|
'protocol': 'http_dash_segments',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if 'initialization_url' in representation_ms_info:
|
|
|
|
if 'initialization_url' in representation_ms_info:
|
|
|
|
initialization_url = representation_ms_info['initialization_url'].replace('$RepresentationID$', representation_id)
|
|
|
|
initialization_url = representation_ms_info['initialization_url']
|
|
|
|
if not f.get('url'):
|
|
|
|
if not f.get('url'):
|
|
|
|
f['url'] = initialization_url
|
|
|
|
f['url'] = initialization_url
|
|
|
|
f['fragments'].append({'url': initialization_url})
|
|
|
|
f['fragments'].append({'url': initialization_url})
|
|
|
|