mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-30 12:01:28 +00:00
[downloader/ffmpeg] Support for DASH manifests (experimental)
Closes #159
This commit is contained in:
parent
330690a214
commit
6251555f1c
|
@ -94,6 +94,10 @@ def _get_suitable_downloader(info_dict, params, default):
|
||||||
if ed.can_download(info_dict, external_downloader):
|
if ed.can_download(info_dict, external_downloader):
|
||||||
return ed
|
return ed
|
||||||
|
|
||||||
|
if protocol == 'http_dash_segments':
|
||||||
|
if info_dict.get('is_live') and external_downloader.lower() != 'native':
|
||||||
|
return FFmpegFD
|
||||||
|
|
||||||
if protocol in ('m3u8', 'm3u8_native'):
|
if protocol in ('m3u8', 'm3u8_native'):
|
||||||
if info_dict.get('is_live'):
|
if info_dict.get('is_live'):
|
||||||
return FFmpegFD
|
return FFmpegFD
|
||||||
|
|
|
@ -342,7 +342,7 @@ def _make_cmd(self, tmpfilename, info_dict):
|
||||||
|
|
||||||
|
|
||||||
class FFmpegFD(ExternalFD):
|
class FFmpegFD(ExternalFD):
|
||||||
SUPPORTED_PROTOCOLS = ('http', 'https', 'ftp', 'ftps', 'm3u8', 'm3u8_native', 'rtsp', 'rtmp', 'rtmp_ffmpeg', 'mms')
|
SUPPORTED_PROTOCOLS = ('http', 'https', 'ftp', 'ftps', 'm3u8', 'm3u8_native', 'rtsp', 'rtmp', 'rtmp_ffmpeg', 'mms', 'http_dash_segments')
|
||||||
can_download_to_stdout = True
|
can_download_to_stdout = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -462,12 +462,11 @@ def _call_downloader(self, tmpfilename, info_dict):
|
||||||
args += self._configuration_args((f'_i{i + 1}', '_i')) + ['-i', url]
|
args += self._configuration_args((f'_i{i + 1}', '_i')) + ['-i', url]
|
||||||
|
|
||||||
args += ['-c', 'copy']
|
args += ['-c', 'copy']
|
||||||
if info_dict.get('requested_formats'):
|
if info_dict.get('requested_formats') or protocol == 'http_dash_segments':
|
||||||
for (i, fmt) in enumerate(info_dict['requested_formats']):
|
for (i, fmt) in enumerate(info_dict.get('requested_formats') or [info_dict]):
|
||||||
if fmt.get('acodec') != 'none':
|
stream_number = fmt.get('manifest_stream_number', 0)
|
||||||
args.extend(['-map', '%d:a:0' % i])
|
a_or_v = 'a' if fmt.get('acodec') != 'none' else 'v'
|
||||||
if fmt.get('vcodec') != 'none':
|
args.extend(['-map', f'{i}:{a_or_v}:{stream_number}'])
|
||||||
args.extend(['-map', '%d:v:0' % i])
|
|
||||||
|
|
||||||
if self.params.get('test', False):
|
if self.params.get('test', False):
|
||||||
args += ['-fs', compat_str(self._TEST_FILE_SIZE)]
|
args += ['-fs', compat_str(self._TEST_FILE_SIZE)]
|
||||||
|
@ -490,7 +489,7 @@ def _call_downloader(self, tmpfilename, info_dict):
|
||||||
else:
|
else:
|
||||||
args += ['-f', EXT_TO_OUT_FORMATS.get(ext, ext)]
|
args += ['-f', EXT_TO_OUT_FORMATS.get(ext, ext)]
|
||||||
|
|
||||||
args += self._configuration_args((f'_o1', '_o', ''))
|
args += self._configuration_args(('_o1', '_o', ''))
|
||||||
|
|
||||||
args = [encodeArgument(opt) for opt in args]
|
args = [encodeArgument(opt) for opt in args]
|
||||||
args.append(encodeFilename(ffpp._ffmpeg_filename_argument(tmpfilename), True))
|
args.append(encodeFilename(ffpp._ffmpeg_filename_argument(tmpfilename), True))
|
||||||
|
|
|
@ -2584,8 +2584,8 @@ def extract_Initialization(source):
|
||||||
return ms_info
|
return ms_info
|
||||||
|
|
||||||
mpd_duration = parse_duration(mpd_doc.get('mediaPresentationDuration'))
|
mpd_duration = parse_duration(mpd_doc.get('mediaPresentationDuration'))
|
||||||
formats = []
|
formats, subtitles = [], {}
|
||||||
subtitles = {}
|
stream_numbers = {'audio': 0, 'video': 0}
|
||||||
for period in mpd_doc.findall(_add_ns('Period')):
|
for period in mpd_doc.findall(_add_ns('Period')):
|
||||||
period_duration = parse_duration(period.get('duration')) or mpd_duration
|
period_duration = parse_duration(period.get('duration')) or mpd_duration
|
||||||
period_ms_info = extract_multisegment_info(period, {
|
period_ms_info = extract_multisegment_info(period, {
|
||||||
|
@ -2647,8 +2647,10 @@ def extract_Initialization(source):
|
||||||
'format_note': 'DASH %s' % content_type,
|
'format_note': 'DASH %s' % content_type,
|
||||||
'filesize': filesize,
|
'filesize': filesize,
|
||||||
'container': mimetype2ext(mime_type) + '_dash',
|
'container': mimetype2ext(mime_type) + '_dash',
|
||||||
|
'manifest_stream_number': stream_numbers[content_type]
|
||||||
}
|
}
|
||||||
f.update(parse_codecs(codecs))
|
f.update(parse_codecs(codecs))
|
||||||
|
stream_numbers[content_type] += 1
|
||||||
elif content_type == 'text':
|
elif content_type == 'text':
|
||||||
f = {
|
f = {
|
||||||
'ext': mimetype2ext(mime_type),
|
'ext': mimetype2ext(mime_type),
|
||||||
|
|
|
@ -4987,6 +4987,7 @@ def cli_configuration_args(argdict, keys, default=[], use_compat=True):
|
||||||
return [arg for args in arg_list for arg in args]
|
return [arg for args in arg_list for arg in args]
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def _configuration_args(main_key, argdict, exe, keys=None, default=[], use_compat=True):
|
def _configuration_args(main_key, argdict, exe, keys=None, default=[], use_compat=True):
|
||||||
main_key, exe = main_key.lower(), exe.lower()
|
main_key, exe = main_key.lower(), exe.lower()
|
||||||
root_key = exe if main_key == exe else f'{main_key}+{exe}'
|
root_key = exe if main_key == exe else f'{main_key}+{exe}'
|
||||||
|
|
Loading…
Reference in a new issue