from .version import __version__
from .downloader.external import list_external_downloaders
-from .postprocessor.ffmpeg import (
+from .postprocessor import (
FFmpegExtractAudioPP,
FFmpegSubtitlesConvertorPP,
FFmpegThumbnailsConvertorPP,
parser.values, option.dest,
current + value if append is True else value + current)
+ def _set_from_options_callback(
+ option, opt_str, value, parser,
+ delim=',', allowed_values=None, process=str.lower, aliases={}):
+ current = getattr(parser.values, option.dest)
+ values = [process(value)] if delim is None else process(value).split(delim)[::-1]
+ while values:
+ actual_val = val = values.pop()
+ if val == 'all':
+ current.update(allowed_values)
+ elif val == '-all':
+ current = set()
+ elif val in aliases:
+ values.extend(aliases[val])
+ else:
+ if val[0] == '-':
+ val = val[1:]
+ current.discard(val)
+ else:
+ current.update([val])
+ if allowed_values is not None and val not in allowed_values:
+ raise optparse.OptionValueError(f'wrong {option.metavar} for {opt_str}: {actual_val}')
+
+ setattr(parser.values, option.dest, current)
+
def _dict_from_options_callback(
option, opt_str, value, parser,
allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None, multiple_keys=True):
general.add_option(
'--dump-user-agent',
action='store_true', dest='dump_user_agent', default=False,
- help='Display the current browser identification')
+ help='Display the current user-agent and exit')
general.add_option(
'--list-extractors',
action='store_true', dest='list_extractors', default=False,
- help='List all supported extractors')
+ help='List all supported extractors and exit')
general.add_option(
'--extractor-descriptions',
action='store_true', dest='list_extractor_descriptions', default=False,
- help='Output descriptions of all supported extractors')
+ help='Output descriptions of all supported extractors and exit')
general.add_option(
'--force-generic-extractor',
action='store_true', dest='force_generic_extractor', default=False,
'--flat-playlist',
action='store_const', dest='extract_flat', const='in_playlist', default=False,
help='Do not extract the videos of a playlist, only list them')
- general.add_option(
- '--flat-videos',
- action='store_true', dest='extract_flat',
- # help='Do not resolve the video urls')
- # doesn't work
- help=optparse.SUPPRESS_HELP)
general.add_option(
'--no-flat-playlist',
action='store_false', dest='extract_flat',
help='Do not emit color codes in output')
general.add_option(
'--compat-options',
- metavar='OPTS', dest='compat_opts', default=[],
- action='callback', callback=_list_from_options_callback, type='str',
- help=(
- 'Options that can help keep compatibility with youtube-dl and youtube-dlc '
+ metavar='OPTS', dest='compat_opts', default=set(), type='str',
+ action='callback', callback=_set_from_options_callback,
+ callback_kwargs={
+ 'allowed_values': {
+ 'filename', 'format-sort', 'abort-on-error', 'format-spec', 'no-playlist-metafiles',
+ 'multistreams', 'no-live-chat', 'playlist-index', 'list-formats', 'no-direct-merge',
+ 'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-attach-info-json',
+ 'embed-thumbnail-atomicparsley', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs',
+ },
+ 'aliases': {
+ 'youtube-dl': ['-multistreams', 'all'],
+ 'youtube-dlc': ['-no-youtube-channel-redirect', '-no-live-chat', 'all'],
+ }
+ }, help=(
+ 'Options that can help keep compatibility with youtube-dl or youtube-dlc '
'configurations by reverting some of the changes made in yt-dlp. '
'See "Differences in default behavior" for details'))
selection.add_option(
'--match-title',
dest='matchtitle', metavar='REGEX',
- help='Download only matching titles (regex or caseless sub-string)')
+ help=optparse.SUPPRESS_HELP)
selection.add_option(
'--reject-title',
dest='rejecttitle', metavar='REGEX',
- help='Skip download for matching titles (regex or caseless sub-string)')
+ help=optparse.SUPPRESS_HELP)
selection.add_option(
'--max-downloads',
dest='max_downloads', metavar='NUMBER', type=int, default=None,
selection.add_option(
'--min-views',
metavar='COUNT', dest='min_views', default=None, type=int,
- help='Do not download any videos with less than COUNT views')
+ help=optparse.SUPPRESS_HELP)
selection.add_option(
'--max-views',
metavar='COUNT', dest='max_views', default=None, type=int,
- help='Do not download any videos with more than COUNT views')
+ help=optparse.SUPPRESS_HELP)
selection.add_option(
'--match-filter',
metavar='FILTER', dest='match_filter', default=None,
'Generic video filter. Any field (see "OUTPUT TEMPLATE") can be compared with a '
'number or a string using the operators defined in "Filtering formats". '
'You can also simply specify a field to match if the field is present '
- 'and "!field" to check if the field is not present. '
- 'Multiple filters can be checked using "&". '
- 'For example, to only match videos that are not live, '
- 'has a like count more than 100, a dislike count less than 50 '
- '(or the dislike field is not available), and also has a description '
- 'that contains "python", use --match-filter "!is_live & '
- 'like_count>100 & dislike_count<?50 & description*=\'python\'"'))
+ 'and "!field" to check if the field is not present. In addition, '
+ 'Python style regular expression matching can be done using "~=", '
+ 'and multiple filters can be checked with "&". '
+ 'Use a "\\" to escape "&" or quotes if needed. Eg: --match-filter '
+ r'"!is_live & like_count>?100 & description~=\'(?i)\bcats \& dogs\b\'" '
+ 'matches only videos that are not live, has a like count more than 100 '
+ '(or the like field is not available), and also has a description '
+ 'that contains the phrase "cats & dogs" (ignoring case)'))
selection.add_option(
'--no-match-filter',
metavar='FILTER', dest='match_filter', action='store_const', const=None,
video_format.add_option(
'-F', '--list-formats',
action='store_true', dest='listformats',
- help='List all available formats of requested videos')
+ help='List available formats of each video. Simulate unless --no-simulate is used')
video_format.add_option(
'--list-formats-as-table',
action='store_true', dest='listformats_table', default=True,
subtitles.add_option(
'--list-subs',
action='store_true', dest='listsubtitles', default=False,
- help='List all available subtitles for the video')
+ help='List available subtitles of each video. Simulate unless --no-simulate is used')
subtitles.add_option(
'--sub-format',
action='store', dest='subtitlesformat', metavar='FORMAT', default='best',
verbosity.add_option(
'-q', '--quiet',
action='store_true', dest='quiet', default=False,
- help='Activate quiet mode')
+ help='Activate quiet mode. If used with --verbose, print the log to stderr')
verbosity.add_option(
'--no-warnings',
dest='no_warnings', action='store_true', default=False,
help='Ignore warnings')
verbosity.add_option(
'-s', '--simulate',
- action='store_true', dest='simulate', default=False,
+ action='store_true', dest='simulate', default=None,
help='Do not download the video and do not write anything to disk')
+ verbosity.add_option(
+ '--no-simulate',
+ action='store_false', dest='simulate',
+ help='Download the video even if printing/listing options are used')
verbosity.add_option(
'--ignore-no-formats-error',
action='store_true', dest='ignore_no_formats_error', default=False,
help=(
'Ignore "No video formats" error. Usefull for extracting metadata '
- 'even if the video is not actually available for download (experimental)'))
+ 'even if the videos are not actually available for download (experimental)'))
verbosity.add_option(
'--no-ignore-no-formats-error',
action='store_false', dest='ignore_no_formats_error',
action='store_true', dest='skip_download', default=False,
help='Do not download the video but write all related files (Alias: --no-download)')
verbosity.add_option(
- '-O', '--print', metavar='TEMPLATE',
- action='callback', dest='forceprint', type='str', default=[],
- callback=_list_from_options_callback, callback_kwargs={'delim': None},
+ '-O', '--print',
+ metavar='TEMPLATE', action='append', dest='forceprint',
help=(
- 'Simulate, quiet but print the given fields. Either a field name '
- 'or similar formatting as the output template can be used'))
+ 'Quiet, but print the given fields for each video. Simulate unless --no-simulate is used. '
+ 'Either a field name or same syntax as the output template can be used'))
verbosity.add_option(
'-g', '--get-url',
action='store_true', dest='geturl', default=False,
verbosity.add_option(
'-j', '--dump-json',
action='store_true', dest='dumpjson', default=False,
- help='Simulate, quiet but print JSON information. See "OUTPUT TEMPLATE" for a description of available keys')
+ help='Quiet, but print JSON information for each video. Simulate unless --no-simulate is used. See "OUTPUT TEMPLATE" for a description of available keys')
verbosity.add_option(
'-J', '--dump-single-json',
action='store_true', dest='dump_single_json', default=False,
help=(
- 'Simulate, quiet but print JSON information for each command-line argument. '
- 'If the URL refers to a playlist, dump the whole playlist information in a single line'))
+ 'Quiet, but print JSON information for each url or infojson passed. Simulate unless --no-simulate is used. '
+ 'If the URL refers to a playlist, the whole playlist information is dumped in a single line'))
verbosity.add_option(
'--print-json',
action='store_true', dest='print_json', default=False,
- help='Be quiet and print the video information as JSON (video is still being downloaded)')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--force-write-archive', '--force-write-download-archive', '--force-download-archive',
action='store_true', dest='force_write_download_archive', default=False,
thumbnail.add_option(
'--list-thumbnails',
action='store_true', dest='list_thumbnails', default=False,
- help='Simulate and list all available thumbnail formats')
+ help='List available thumbnails of each video. Simulate unless --no-simulate is used')
link = optparse.OptionGroup(parser, 'Internet Shortcut Options')
link.add_option(
help=optparse.SUPPRESS_HELP)
postproc.add_option(
'--parse-metadata',
- metavar='FROM:TO', dest='metafromfield', action='append',
+ metavar='FROM:TO', dest='parse_metadata', action='append',
help=(
'Parse additional metadata like title/artist from other fields; '
'see "MODIFYING METADATA" for details'))
+ postproc.add_option(
+ '--replace-in-metadata',
+ dest='parse_metadata', metavar='FIELDS REGEX REPLACE', action='append', nargs=3,
+ help='Replace text in a metadata field using the given regex. This option can be used multiple times')
postproc.add_option(
'--xattrs',
action='store_true', dest='xattrs', default=False,
dest='ffmpeg_location',
help='Location of the ffmpeg binary; either the path to the binary or its containing directory')
postproc.add_option(
- '--exec',
- metavar='CMD', dest='exec_cmd',
+ '--exec', metavar='CMD',
+ action='append', dest='exec_cmd',
help=(
'Execute a command on the file after downloading and post-processing. '
- 'Similar syntax to the output template can be used to pass any field as arguments to the command. '
+ 'Same syntax as the output template can be used to pass any field as arguments to the command. '
'An additional field "filepath" that contains the final path of the downloaded file is also available. '
- 'If no fields are passed, %(filepath)q is appended to the end of the command'))
+ 'If no fields are passed, %(filepath)q is appended to the end of the command. '
+ 'This option can be used multiple times'))
+ postproc.add_option(
+ '--no-exec',
+ action='store_const', dest='exec_cmd', const=[],
+ help='Remove any previously defined --exec')
+ postproc.add_option(
+ '--exec-before-download', metavar='CMD',
+ action='append', dest='exec_before_dl_cmd',
+ help=(
+ 'Execute a command before the actual download. '
+ 'The syntax is the same as --exec but "filepath" is not available. '
+ 'This option can be used multiple times'))
postproc.add_option(
- '--exec-before-download',
- metavar='CMD', dest='exec_before_dl_cmd',
- help='Execute a command before the actual download. The syntax is the same as --exec but "filepath" is not available')
+ '--no-exec-before-download',
+ action='store_const', dest='exec_before_dl_cmd', const=[],
+ help='Remove any previously defined --exec-before-download')
postproc.add_option(
'--convert-subs', '--convert-sub', '--convert-subtitles',
metavar='FORMAT', dest='convertsubtitles', default=None,
'--no-hls-split-discontinuity',
dest='hls_split_discontinuity', action='store_false',
help='Do not split HLS playlists to different formats at discontinuities such as ad breaks (default)')
- _extractor_arg_parser = lambda key, vals='': (key.strip().lower(), [val.strip() for val in vals.split(',')])
+ _extractor_arg_parser = lambda key, vals='': (key.strip().lower().replace('-', '_'), [val.strip() for val in vals.split(',')])
extractor.add_option(
'--extractor-args',
metavar='KEY:ARGS', dest='extractor_args', default={}, type='str',