[downloader/ffmpeg] Allow passing custom arguments before -i
Closes #686
This commit is contained in:
parent
91d4b32bb6
commit
330690a214
5 changed files with 34 additions and 27 deletions
|
@ -439,9 +439,12 @@ Then simply run `make`. You can also run `make yt-dlp` instead to compile only t
|
||||||
(Alias: --external-downloader)
|
(Alias: --external-downloader)
|
||||||
--downloader-args NAME:ARGS Give these arguments to the external
|
--downloader-args NAME:ARGS Give these arguments to the external
|
||||||
downloader. Specify the downloader name and
|
downloader. Specify the downloader name and
|
||||||
the arguments separated by a colon ":". You
|
the arguments separated by a colon ":". For
|
||||||
can use this option multiple times to give
|
ffmpeg, arguments can be passed to
|
||||||
different arguments to different downloaders
|
different positions using the same syntax
|
||||||
|
as --postprocessor-args. You can use this
|
||||||
|
option multiple times to give different
|
||||||
|
arguments to different downloaders
|
||||||
(Alias: --external-downloader-args)
|
(Alias: --external-downloader-args)
|
||||||
|
|
||||||
## Filesystem Options:
|
## Filesystem Options:
|
||||||
|
|
|
@ -22,7 +22,7 @@ from ..utils import (
|
||||||
cli_option,
|
cli_option,
|
||||||
cli_valueless_option,
|
cli_valueless_option,
|
||||||
cli_bool_option,
|
cli_bool_option,
|
||||||
cli_configuration_args,
|
_configuration_args,
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
encodeArgument,
|
encodeArgument,
|
||||||
handle_youtubedl_headers,
|
handle_youtubedl_headers,
|
||||||
|
@ -111,11 +111,10 @@ class ExternalFD(FileDownloader):
|
||||||
def _valueless_option(self, command_option, param, expected_value=True):
|
def _valueless_option(self, command_option, param, expected_value=True):
|
||||||
return cli_valueless_option(self.params, command_option, param, expected_value)
|
return cli_valueless_option(self.params, command_option, param, expected_value)
|
||||||
|
|
||||||
def _configuration_args(self, *args, **kwargs):
|
def _configuration_args(self, keys=None, *args, **kwargs):
|
||||||
return cli_configuration_args(
|
return _configuration_args(
|
||||||
self.params.get('external_downloader_args'),
|
self.get_basename(), self.params.get('external_downloader_args'), self.get_basename(),
|
||||||
[self.get_basename(), 'default'],
|
keys, *args, **kwargs)
|
||||||
*args, **kwargs)
|
|
||||||
|
|
||||||
def _call_downloader(self, tmpfilename, info_dict):
|
def _call_downloader(self, tmpfilename, info_dict):
|
||||||
""" Either overwrite this or implement _make_cmd """
|
""" Either overwrite this or implement _make_cmd """
|
||||||
|
@ -459,10 +458,10 @@ class FFmpegFD(ExternalFD):
|
||||||
elif isinstance(conn, compat_str):
|
elif isinstance(conn, compat_str):
|
||||||
args += ['-rtmp_conn', conn]
|
args += ['-rtmp_conn', conn]
|
||||||
|
|
||||||
for url in urls:
|
for i, url in enumerate(urls):
|
||||||
args += ['-i', url]
|
args += self._configuration_args((f'_i{i + 1}', '_i')) + ['-i', url]
|
||||||
|
|
||||||
args += self._configuration_args() + ['-c', 'copy']
|
args += ['-c', 'copy']
|
||||||
if info_dict.get('requested_formats'):
|
if info_dict.get('requested_formats'):
|
||||||
for (i, fmt) in enumerate(info_dict['requested_formats']):
|
for (i, fmt) in enumerate(info_dict['requested_formats']):
|
||||||
if fmt.get('acodec') != 'none':
|
if fmt.get('acodec') != 'none':
|
||||||
|
@ -491,9 +490,10 @@ class FFmpegFD(ExternalFD):
|
||||||
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 = [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))
|
||||||
|
|
||||||
self._debug_cmd(args)
|
self._debug_cmd(args)
|
||||||
|
|
||||||
proc = subprocess.Popen(args, stdin=subprocess.PIPE, env=env)
|
proc = subprocess.Popen(args, stdin=subprocess.PIPE, env=env)
|
||||||
|
|
|
@ -742,12 +742,13 @@ def parseOpts(overrideArguments=None):
|
||||||
metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str',
|
metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str',
|
||||||
action='callback', callback=_dict_from_options_callback,
|
action='callback', callback=_dict_from_options_callback,
|
||||||
callback_kwargs={
|
callback_kwargs={
|
||||||
'allowed_keys': '|'.join(list_external_downloaders()),
|
'allowed_keys': r'ffmpeg_[io]\d*|%s' % '|'.join(list_external_downloaders()),
|
||||||
'default_key': 'default',
|
'default_key': 'default',
|
||||||
'process': compat_shlex_split
|
'process': compat_shlex_split
|
||||||
}, help=(
|
}, help=(
|
||||||
'Give these arguments to the external downloader. '
|
'Give these arguments to the external downloader. '
|
||||||
'Specify the downloader name and the arguments separated by a colon ":". '
|
'Specify the downloader name and the arguments separated by a colon ":". '
|
||||||
|
'For ffmpeg, arguments can be passed to different positions using the same syntax as --postprocessor-args. '
|
||||||
'You can use this option multiple times to give different arguments to different downloaders '
|
'You can use this option multiple times to give different arguments to different downloaders '
|
||||||
'(Alias: --external-downloader-args)'))
|
'(Alias: --external-downloader-args)'))
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import os
|
||||||
|
|
||||||
from ..compat import compat_str
|
from ..compat import compat_str
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
cli_configuration_args,
|
_configuration_args,
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
PostProcessingError,
|
PostProcessingError,
|
||||||
)
|
)
|
||||||
|
@ -110,18 +110,9 @@ class PostProcessor(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
self.report_warning(errnote)
|
self.report_warning(errnote)
|
||||||
|
|
||||||
def _configuration_args(self, exe, keys=None, default=[], use_compat=True):
|
def _configuration_args(self, exe, *args, **kwargs):
|
||||||
pp_key = self.pp_key().lower()
|
return _configuration_args(
|
||||||
exe = exe.lower()
|
self.pp_key(), self.get_param('postprocessor_args'), exe, *args, **kwargs)
|
||||||
root_key = exe if pp_key == exe else '%s+%s' % (pp_key, exe)
|
|
||||||
keys = ['%s%s' % (root_key, k) for k in (keys or [''])]
|
|
||||||
if root_key in keys:
|
|
||||||
keys += [root_key] + ([] if pp_key == exe else [(self.pp_key(), exe)]) + ['default']
|
|
||||||
else:
|
|
||||||
use_compat = False
|
|
||||||
return cli_configuration_args(
|
|
||||||
self.get_param('postprocessor_args'),
|
|
||||||
keys, default, use_compat)
|
|
||||||
|
|
||||||
|
|
||||||
class AudioConversionError(PostProcessingError):
|
class AudioConversionError(PostProcessingError):
|
||||||
|
|
|
@ -4987,6 +4987,18 @@ 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):
|
||||||
|
main_key, exe = main_key.lower(), exe.lower()
|
||||||
|
root_key = exe if main_key == exe else f'{main_key}+{exe}'
|
||||||
|
keys = [f'{root_key}{k}' for k in (keys or [''])]
|
||||||
|
if root_key in keys:
|
||||||
|
if main_key != exe:
|
||||||
|
keys.append((main_key, exe))
|
||||||
|
keys.append('default')
|
||||||
|
else:
|
||||||
|
use_compat = False
|
||||||
|
return cli_configuration_args(argdict, keys, default, use_compat)
|
||||||
|
|
||||||
|
|
||||||
class ISO639Utils(object):
|
class ISO639Utils(object):
|
||||||
# See http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt
|
# See http://www.loc.gov/standards/iso639-2/ISO-639-2_utf-8.txt
|
||||||
|
|
Loading…
Reference in a new issue