]> jfr.im git - yt-dlp.git/blame - yt_dlp/options.py
[ie/cnbc] Overhaul extractors (#8741)
[yt-dlp.git] / yt_dlp / options.py
CommitLineData
9e491463 1import collections
2import contextlib
34a741a8 3import optparse
f8271158 4import os.path
3aa9a735 5import re
f9934b96 6import shlex
ac668111 7import shutil
9e491463 8import string
34a741a8
PH
9import sys
10
ac668111 11from .compat import compat_expanduser
f59f5ef8 12from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
81a23040 13from .downloader.external import list_external_downloaders
ad3dc496 14from .postprocessor import (
81a23040 15 FFmpegExtractAudioPP,
4f04be6a 16 FFmpegMergerPP,
81a23040 17 FFmpegSubtitlesConvertorPP,
18 FFmpegThumbnailsConvertorPP,
19 FFmpegVideoRemuxerPP,
7a340e0d 20 SponsorBlockPP,
81a23040 21)
7a340e0d 22from .postprocessor.modify_chapters import DEFAULT_SPONSORBLOCK_CHAPTER_TITLE
77df20f1 23from .update import UPDATE_SOURCES, detect_variant, is_non_updateable
f8271158 24from .utils import (
25 OUTTMPL_TYPES,
26 POSTPROCESS_WHEN,
27 Config,
da4db748 28 deprecation_warning,
f8271158 29 expand_path,
70b23409 30 format_field,
f8271158 31 get_executable_path,
8e40b9d1
M
32 get_system_config_dirs,
33 get_user_config_dirs,
19a03940 34 join_nonempty,
5314b521 35 orderedSet_from_options,
f8271158 36 remove_end,
8417f26b 37 variadic,
f8271158 38 write_string,
39)
77df20f1 40from .version import CHANNEL, __version__
81a23040 41
34a741a8 42
06e57990 43def parseOpts(overrideArguments=None, ignore_config_files='if_override'):
773c272d
SS
44 PACKAGE_NAME = 'yt-dlp'
45
9e491463 46 root = Config(create_parser())
06e57990 47 if ignore_config_files == 'if_override':
48 ignore_config_files = overrideArguments is not None
34a741a8 49
773c272d
SS
50 def read_config(*paths):
51 path = os.path.join(*paths)
52 conf = Config.read_file(path, default=None)
53 if conf is not None:
54 return conf, path
55
8e40b9d1
M
56 def _load_from_config_dirs(config_dirs):
57 for config_dir in config_dirs:
773c272d
SS
58 head, tail = os.path.split(config_dir)
59 assert tail == PACKAGE_NAME or config_dir == os.path.join(compat_expanduser('~'), f'.{PACKAGE_NAME}')
34a741a8 60
773c272d
SS
61 yield read_config(head, f'{PACKAGE_NAME}.conf')
62 if tail.startswith('.'): # ~/.PACKAGE_NAME
63 yield read_config(head, f'{PACKAGE_NAME}.conf.txt')
64 yield read_config(config_dir, 'config')
65 yield read_config(config_dir, 'config.txt')
34a741a8 66
8e40b9d1 67 def add_config(label, path=None, func=None):
06e57990 68 """ Adds config and returns whether to continue """
9e491463 69 if root.parse_known_args()[0].ignoreconfig:
06e57990 70 return False
8e40b9d1
M
71 elif func:
72 assert path is None
773c272d
SS
73 args, current_path = next(
74 filter(None, _load_from_config_dirs(func(PACKAGE_NAME))), (None, None))
8e40b9d1
M
75 else:
76 current_path = os.path.join(path, 'yt-dlp.conf')
77 args = Config.read_file(current_path, default=None)
78 if args is not None:
79 root.append_config(args, current_path, label=label)
06e57990 80 return True
81
82 def load_configs():
83 yield not ignore_config_files
84 yield add_config('Portable', get_executable_path())
9e491463 85 yield add_config('Home', expand_path(root.parse_known_args()[0].paths.get('home', '')).strip())
773c272d
SS
86 yield add_config('User', func=get_user_config_dirs)
87 yield add_config('System', func=get_system_config_dirs)
06e57990 88
9e491463 89 opts = optparse.Values({'verbose': True, 'print_help': False})
90 try:
44a6fcff 91 try:
08e29b9f 92 if overrideArguments is not None:
44a6fcff 93 root.append_config(overrideArguments, label='Override')
94 else:
95 root.append_config(sys.argv[1:], label='Command-line')
96 loaded_all_configs = all(load_configs())
97 except ValueError as err:
98 raise root.parser.error(err)
9e491463 99
44a6fcff 100 if loaded_all_configs:
9e491463 101 # If ignoreconfig is found inside the system configuration file,
102 # the user configuration is removed
103 if root.parse_known_args()[0].ignoreconfig:
104 user_conf = next((i for i, conf in enumerate(root.configs) if conf.label == 'User'), None)
105 if user_conf is not None:
106 root.configs.pop(user_conf)
06e57990 107
284a60c5 108 try:
109 root.configs[0].load_configs() # Resolve any aliases using --config-location
110 except ValueError as err:
111 raise root.parser.error(err)
112
9e491463 113 opts, args = root.parse_args()
114 except optparse.OptParseError:
115 with contextlib.suppress(optparse.OptParseError):
116 opts, _ = root.parse_known_args(strict=False)
117 raise
118 except (SystemExit, KeyboardInterrupt):
119 opts.verbose = False
120 raise
121 finally:
122 verbose = opts.verbose and f'\n{root}'.replace('\n| ', '\n[debug] ')[1:]
123 if verbose:
124 write_string(f'{verbose}\n')
125 if opts.print_help:
126 if verbose:
127 write_string('\n')
128 root.parser.print_help()
129 if opts.print_help:
130 sys.exit()
131 return root.parser, opts, args
06e57990 132
133
19a03940 134class _YoutubeDLHelpFormatter(optparse.IndentedHelpFormatter):
135 def __init__(self):
136 # No need to wrap help messages if we're on a wide console
ac668111 137 max_width = shutil.get_terminal_size().columns or 80
2dd5a2e3 138 # The % is chosen to get a pretty output in README.md
139 super().__init__(width=max_width, max_help_position=int(0.45 * max_width))
19a03940 140
141 @staticmethod
142 def format_option_strings(option):
143 """ ('-o', '--option') -> -o, --format METAVAR """
144 opts = join_nonempty(
145 option._short_opts and option._short_opts[0],
146 option._long_opts and option._long_opts[0],
147 delim=', ')
148 if option.takes_value():
149 opts += f' {option.metavar}'
150 return opts
151
152
db2e129c 153class _YoutubeDLOptionParser(optparse.OptionParser):
154 # optparse is deprecated since python 3.2. So assume a stable interface even for private methods
ca7f8b8f 155 ALIAS_DEST = '_triggered_aliases'
9e491463 156 ALIAS_TRIGGER_LIMIT = 100
db2e129c 157
19a03940 158 def __init__(self):
159 super().__init__(
9e491463 160 prog='yt-dlp' if detect_variant() == 'source' else None,
19a03940 161 version=__version__,
162 usage='%prog [OPTIONS] URL [URL...]',
163 epilog='See full documentation at https://github.com/yt-dlp/yt-dlp#readme',
164 formatter=_YoutubeDLHelpFormatter(),
165 conflict_handler='resolve',
166 )
ca7f8b8f 167 self.set_default(self.ALIAS_DEST, collections.defaultdict(int))
19a03940 168
9e491463 169 _UNKNOWN_OPTION = (optparse.BadOptionError, optparse.AmbiguousOptionError)
170 _BAD_OPTION = optparse.OptionValueError
171
172 def parse_known_args(self, args=None, values=None, strict=True):
173 """Same as parse_args, but ignore unknown switches. Similar to argparse.parse_known_args"""
174 self.rargs, self.largs = self._get_args(args), []
175 self.values = values or self.get_default_values()
176 while self.rargs:
c800598c 177 arg = self.rargs[0]
9e491463 178 try:
c800598c 179 if arg == '--':
180 del self.rargs[0]
181 break
182 elif arg.startswith('--'):
183 self._process_long_opt(self.rargs, self.values)
184 elif arg.startswith('-') and arg != '-':
185 self._process_short_opts(self.rargs, self.values)
186 elif self.allow_interspersed_args:
187 self.largs.append(self.rargs.pop(0))
188 else:
189 break
9e491463 190 except optparse.OptParseError as err:
191 if isinstance(err, self._UNKNOWN_OPTION):
192 self.largs.append(err.opt_str)
193 elif strict:
194 if isinstance(err, self._BAD_OPTION):
195 self.error(str(err))
196 raise
197 return self.check_values(self.values, self.largs)
198
199 def error(self, msg):
44a6fcff 200 msg = f'{self.get_prog_name()}: error: {str(msg).strip()}\n'
9e491463 201 raise optparse.OptParseError(f'{self.get_usage()}\n{msg}' if self.usage else msg)
202
19a03940 203 def _get_args(self, args):
204 return sys.argv[1:] if args is None else list(args)
205
db2e129c 206 def _match_long_opt(self, opt):
962ffcf8 207 """Improve ambiguous argument resolution by comparing option objects instead of argument strings"""
db2e129c 208 try:
209 return super()._match_long_opt(opt)
210 except optparse.AmbiguousOptionError as e:
86e5f3ed 211 if len({self._long_opt[p] for p in e.possibilities}) == 1:
db2e129c 212 return e.possibilities[0]
213 raise
214
215
06e57990 216def create_parser():
d21bba78 217 def _list_from_options_callback(option, opt_str, value, parser, append=True, delim=',', process=str.strip):
e632bce2 218 # append can be True, False or -1 (prepend)
9e907ebd 219 current = list(getattr(parser.values, option.dest)) if append else []
1f8471e2 220 value = list(filter(None, [process(value)] if delim is None else map(process, value.split(delim))))
d818eb74 221 setattr(
222 parser.values, option.dest,
e632bce2 223 current + value if append is True else value + current)
34a741a8 224
31654882 225 def _set_from_options_callback(
5314b521 226 option, opt_str, value, parser, allowed_values, delim=',', aliases={},
d21bba78 227 process=lambda x: x.lower().strip()):
5314b521 228 values = [process(value)] if delim is None else map(process, value.split(delim))
229 try:
230 requested = orderedSet_from_options(values, collections.ChainMap(aliases, {'all': allowed_values}),
231 start=getattr(parser.values, option.dest))
232 except ValueError as e:
233 raise optparse.OptionValueError(f'wrong {option.metavar} for {opt_str}: {e.args[0]}')
31654882 234
5314b521 235 setattr(parser.values, option.dest, set(requested))
31654882 236
e632bce2 237 def _dict_from_options_callback(
d818eb74 238 option, opt_str, value, parser,
44bcb8d1 239 allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None, multiple_keys=True,
ca30f449 240 process_key=str.lower, append=False):
45016689 241
ca30f449 242 out_dict = dict(getattr(parser.values, option.dest))
bb66c247 243 multiple_args = not isinstance(value, str)
d818eb74 244 if multiple_keys:
86e5f3ed 245 allowed_keys = fr'({allowed_keys})(,({allowed_keys}))*'
bb66c247 246 mobj = re.match(
78fde6e3 247 fr'(?is)(?P<keys>{allowed_keys}){delimiter}(?P<val>.*)$',
bb66c247 248 value[0] if multiple_args else value)
45016689 249 if mobj is not None:
44bcb8d1 250 keys, val = mobj.group('keys').split(','), mobj.group('val')
bb66c247 251 if multiple_args:
252 val = [val, *value[1:]]
45016689 253 elif default_key is not None:
8417f26b 254 keys, val = variadic(default_key), value
45016689 255 else:
256 raise optparse.OptionValueError(
86e5f3ed 257 f'wrong {opt_str} formatting; it should be {option.metavar}, not "{value}"')
4bb6b02f 258 try:
44bcb8d1 259 keys = map(process_key, keys) if process_key else keys
4bb6b02f 260 val = process(val) if process else val
261 except Exception as err:
44bcb8d1 262 raise optparse.OptionValueError(f'wrong {opt_str} formatting; {err}')
d818eb74 263 for key in keys:
ca30f449 264 out_dict[key] = out_dict.get(key, []) + [val] if append else val
265 setattr(parser.values, option.dest, out_dict)
45016689 266
119e40ef 267 def when_prefix(default):
268 return {
269 'default': {},
270 'type': 'str',
271 'action': 'callback',
272 'callback': _dict_from_options_callback,
273 'callback_kwargs': {
274 'allowed_keys': '|'.join(map(re.escape, POSTPROCESS_WHEN)),
275 'default_key': default,
276 'multiple_keys': False,
277 'append': True,
278 },
279 }
280
19a03940 281 parser = _YoutubeDLOptionParser()
9e491463 282 alias_group = optparse.OptionGroup(parser, 'Aliases')
283 Formatter = string.Formatter()
284
285 def _create_alias(option, opt_str, value, parser):
286 aliases, opts = value
287 try:
288 nargs = len({i if f == '' else f
289 for i, (_, f, _, _) in enumerate(Formatter.parse(opts)) if f is not None})
290 opts.format(*map(str, range(nargs))) # validate
291 except Exception as err:
292 raise optparse.OptionValueError(f'wrong {opt_str} OPTIONS formatting; {err}')
293 if alias_group not in parser.option_groups:
294 parser.add_option_group(alias_group)
295
296 aliases = (x if x.startswith('-') else f'--{x}' for x in map(str.strip, aliases.split(',')))
297 try:
46d09f87 298 args = [f'ARG{i}' for i in range(nargs)]
9e491463 299 alias_group.add_option(
46d09f87 300 *aliases, nargs=nargs, dest=parser.ALIAS_DEST, type='str' if nargs else None,
301 metavar=' '.join(args), help=opts.format(*args), action='callback',
9e491463 302 callback=_alias_callback, callback_kwargs={'opts': opts, 'nargs': nargs})
303 except Exception as err:
304 raise optparse.OptionValueError(f'wrong {opt_str} formatting; {err}')
305
306 def _alias_callback(option, opt_str, value, parser, opts, nargs):
307 counter = getattr(parser.values, option.dest)
308 counter[opt_str] += 1
309 if counter[opt_str] > parser.ALIAS_TRIGGER_LIMIT:
310 raise optparse.OptionValueError(f'Alias {opt_str} exceeded invocation limit')
311 if nargs == 1:
312 value = [value]
313 assert (nargs == 0 and value is None) or len(value) == nargs
314 parser.rargs[:0] = shlex.split(
315 opts if value is None else opts.format(*map(shlex.quote, value)))
34a741a8 316
8450c15c
PH
317 general = optparse.OptionGroup(parser, 'General Options')
318 general.add_option(
9e491463 319 '-h', '--help', dest='print_help', action='store_true',
17941321 320 help='Print this help text and exit')
8450c15c 321 general.add_option(
b76f0e58 322 '--version',
8450c15c 323 action='version',
17941321 324 help='Print program version and exit')
8450c15c
PH
325 general.add_option(
326 '-U', '--update',
665472a7 327 action='store_const', dest='update_self', const=CHANNEL,
70b23409 328 help=format_field(
329 is_non_updateable(), None, 'Check if updates are available. %s',
77df20f1 330 default=f'Update this program to the latest {CHANNEL} version'))
d32f30ac 331 general.add_option(
332 '--no-update',
333 action='store_false', dest='update_self',
70b23409 334 help='Do not check for updates (default)')
77df20f1
SS
335 general.add_option(
336 '--update-to',
337 action='store', dest='update_self', metavar='[CHANNEL]@[TAG]',
338 help=(
665472a7
SS
339 'Upgrade/downgrade to a specific version. CHANNEL can be a repository as well. '
340 f'CHANNEL and TAG default to "{CHANNEL.partition("@")[0]}" and "latest" respectively if omitted; '
341 f'See "UPDATE" for details. Supported channels: {", ".join(UPDATE_SOURCES)}'))
8450c15c 342 general.add_option(
b1940459 343 '-i', '--ignore-errors',
344 action='store_true', dest='ignoreerrors',
0930b11f 345 help='Ignore download and postprocessing errors. The download will be considered successful even if the postprocessing fails')
b1940459 346 general.add_option(
347 '--no-abort-on-error',
348 action='store_const', dest='ignoreerrors', const='only_download',
349 help='Continue with next video on download errors; e.g. to skip unavailable videos in a playlist (default)')
8450c15c 350 general.add_option(
6623ac34 351 '--abort-on-error', '--no-ignore-errors',
8450c15c 352 action='store_false', dest='ignoreerrors',
8a51f564 353 help='Abort downloading of further videos if an error occurs (Alias: --no-ignore-errors)')
8450c15c
PH
354 general.add_option(
355 '--dump-user-agent',
356 action='store_true', dest='dump_user_agent', default=False,
34488702 357 help='Display the current user-agent and exit')
34a741a8 358 general.add_option(
8450c15c
PH
359 '--list-extractors',
360 action='store_true', dest='list_extractors', default=False,
b7b04c78 361 help='List all supported extractors and exit')
8450c15c
PH
362 general.add_option(
363 '--extractor-descriptions',
364 action='store_true', dest='list_extractor_descriptions', default=False,
b7b04c78 365 help='Output descriptions of all supported extractors and exit')
fe7866d0 366 general.add_option(
367 '--use-extractors', '--ies',
368 action='callback', dest='allowed_extractors', metavar='NAMES', type='str',
369 default=[], callback=_list_from_options_callback,
370 help=(
371 'Extractor names to use separated by commas. '
372 'You can also use regexes, "all", "default" and "end" (end URL matching); '
373 'e.g. --ies "holodex.*,end,youtube". '
374 'Prefix the name with a "-" to exclude it, e.g. --ies default,-generic. '
2516cafb 375 'Use --list-extractors for a list of extractor names. (Alias: --ies)'))
d22dec74
S
376 general.add_option(
377 '--force-generic-extractor',
378 action='store_true', dest='force_generic_extractor', default=False,
fe7866d0 379 help=optparse.SUPPRESS_HELP)
34a741a8
PH
380 general.add_option(
381 '--default-search',
382 dest='default_search', metavar='PREFIX',
2dd5a2e3 383 help=(
384 'Use this prefix for unqualified URLs. '
62b58c09 385 'E.g. "gvsearch2:python" downloads two videos from google videos for the search term "python". '
2dd5a2e3 386 'Use the value "auto" to let yt-dlp guess ("auto_warning" to emit a warning when guessing). '
387 '"error" just throws an error. The default value "fixup_error" repairs broken URLs, '
388 'but emits an error if this is not possible instead of searching'))
34a741a8 389 general.add_option(
6623ac34 390 '--ignore-config', '--no-config',
7303f84a 391 action='store_true', dest='ignoreconfig',
6623ac34 392 help=(
9e907ebd 393 'Don\'t load any more configuration files except those given by --config-locations. '
ed8d87f9 394 'For backward compatibility, if this option is found inside the system configuration file, the user configuration is not loaded. '
fc5fa964 395 '(Alias: --no-config)'))
e66dca5e 396 general.add_option(
06e57990 397 '--no-config-locations',
398 action='store_const', dest='config_locations', const=[],
399 help=(
400 'Do not load any custom configuration files (default). When given inside a '
401 'configuration file, ignore all previous --config-locations defined in the current file'))
402 general.add_option(
403 '--config-locations',
404 dest='config_locations', metavar='PATH', action='append',
405 help=(
6b9e832d 406 'Location of the main configuration file; either the path to the config or its containing directory '
407 '("-" for stdin). Can be used multiple times and inside other configuration files'))
057a5206
PH
408 general.add_option(
409 '--flat-playlist',
6623ac34 410 action='store_const', dest='extract_flat', const='in_playlist', default=False,
8a51f564 411 help='Do not extract the videos of a playlist, only list them')
6623ac34 412 general.add_option(
413 '--no-flat-playlist',
414 action='store_false', dest='extract_flat',
c8bc203f 415 help='Fully extract the videos of a playlist (default)')
adbc4ec4
THD
416 general.add_option(
417 '--live-from-start',
418 action='store_true', dest='live_from_start',
9e907ebd 419 help='Download livestreams from the start. Currently only supported for YouTube (Experimental)')
adbc4ec4
THD
420 general.add_option(
421 '--no-live-from-start',
422 action='store_false', dest='live_from_start',
423 help='Download livestreams from the current time (default)')
f2ebc5c7 424 general.add_option(
425 '--wait-for-video',
426 dest='wait_for_video', metavar='MIN[-MAX]', default=None,
427 help=(
428 'Wait for scheduled streams to become available. '
429 'Pass the minimum number of seconds (or range) to wait between retries'))
430 general.add_option(
431 '--no-wait-for-video',
432 dest='wait_for_video', action='store_const', const=None,
433 help='Do not wait for scheduled streams (default)')
d77ab8e2
S
434 general.add_option(
435 '--mark-watched',
436 action='store_true', dest='mark_watched', default=False,
e248be33 437 help='Mark videos watched (even with --simulate)')
90f794c6
S
438 general.add_option(
439 '--no-mark-watched',
597c1866 440 action='store_false', dest='mark_watched',
441 help='Do not mark videos watched (default)')
7e5db8c9 442 general.add_option(
f2df4071 443 '--no-colors', '--no-colours',
8417f26b
SS
444 action='store_const', dest='color', const={
445 'stdout': 'no_color',
446 'stderr': 'no_color',
447 },
448 help=optparse.SUPPRESS_HELP)
449 general.add_option(
450 '--color',
451 dest='color', metavar='[STREAM:]POLICY', default={}, type='str',
452 action='callback', callback=_dict_from_options_callback,
453 callback_kwargs={
454 'allowed_keys': 'stdout|stderr',
455 'default_key': ['stdout', 'stderr'],
456 'process': str.strip,
457 }, help=(
458 'Whether to emit color codes in output, optionally prefixed by '
459 'the STREAM (stdout or stderr) to apply the setting to. '
460 'Can be one of "always", "auto" (default), "never", or '
461 '"no_color" (use non color terminal sequences). '
462 'Can be used multiple times'))
53ed7066 463 general.add_option(
464 '--compat-options',
31654882 465 metavar='OPTS', dest='compat_opts', default=set(), type='str',
466 action='callback', callback=_set_from_options_callback,
467 callback_kwargs={
468 'allowed_values': {
5c3895ff 469 'filename', 'filename-sanitization', 'format-sort', 'abort-on-error', 'format-spec', 'no-playlist-metafiles',
93b39cdb 470 'multistreams', 'no-live-chat', 'playlist-index', 'list-formats', 'no-direct-merge', 'playlist-match-filter',
8c53322c
L
471 'no-attach-info-json', 'embed-thumbnail-atomicparsley', 'no-external-downloader-progress',
472 'embed-metadata', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', 'no-certifi',
d2c8aadf 473 'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-youtube-prefer-utc-upload-date',
10025b71 474 'prefer-legacy-http-handler', 'manifest-filesize-approx'
d21bba78 475 }, 'aliases': {
10025b71 476 'youtube-dl': ['all', '-multistreams', '-playlist-match-filter', '-manifest-filesize-approx'],
477 'youtube-dlc': ['all', '-no-youtube-channel-redirect', '-no-live-chat', '-playlist-match-filter', '-manifest-filesize-approx'],
2a06bb4e 478 '2021': ['2022', 'no-certifi', 'filename-sanitization', 'no-youtube-prefer-utc-upload-date'],
ffff1bc6 479 '2022': ['2023', 'no-external-downloader-progress', 'playlist-match-filter', 'prefer-legacy-http-handler', 'manifest-filesize-approx'],
480 '2023': [],
31654882 481 }
482 }, help=(
483 'Options that can help keep compatibility with youtube-dl or youtube-dlc '
53ed7066 484 'configurations by reverting some of the changes made in yt-dlp. '
485 'See "Differences in default behavior" for details'))
9e491463 486 general.add_option(
487 '--alias', metavar='ALIASES OPTIONS', dest='_', type='str', nargs=2,
488 action='callback', callback=_create_alias,
489 help=(
490 'Create aliases for an option string. Unless an alias starts with a dash "-", it is prefixed with "--". '
491 'Arguments are parsed according to the Python string formatting mini-language. '
62b58c09 492 'E.g. --alias get-audio,-X "-S=aext:{0},abr -x --audio-format {0}" creates options '
9e491463 493 '"--get-audio" and "-X" that takes an argument (ARG0) and expands to '
494 '"-S=aext:ARG0,abr -x --audio-format ARG0". All defined aliases are listed in the --help output. '
962ffcf8 495 'Alias options can trigger more aliases; so be careful to avoid defining recursive options. '
9e491463 496 f'As a safety measure, each alias may be triggered a maximum of {_YoutubeDLOptionParser.ALIAS_TRIGGER_LIMIT} times. '
497 'This option can be used multiple times'))
34a741a8 498
be4a824d
PH
499 network = optparse.OptionGroup(parser, 'Network Options')
500 network.add_option(
501 '--proxy', dest='proxy',
502 default=None, metavar='URL',
6623ac34 503 help=(
62b58c09
L
504 'Use the specified HTTP/HTTPS/SOCKS proxy. To enable SOCKS proxy, specify a proper scheme, '
505 'e.g. socks5://user:pass@127.0.0.1:1080/. Pass in an empty string (--proxy "") for direct connection'))
be4a824d
PH
506 network.add_option(
507 '--socket-timeout',
508 dest='socket_timeout', type=float, default=None, metavar='SECONDS',
509 help='Time to wait before giving up, in seconds')
510 network.add_option(
511 '--source-address',
512 metavar='IP', dest='source_address', default=None,
24ee6b97 513 help='Client-side IP address to bind to',
be4a824d 514 )
500b8b41
PH
515 network.add_option(
516 '-4', '--force-ipv4',
517 action='store_const', const='0.0.0.0', dest='source_address',
24ee6b97 518 help='Make all connections via IPv4',
500b8b41
PH
519 )
520 network.add_option(
521 '-6', '--force-ipv6',
522 action='store_const', const='::', dest='source_address',
24ee6b97 523 help='Make all connections via IPv6',
500b8b41 524 )
8300774c
M
525 network.add_option(
526 '--enable-file-urls', action='store_true',
527 dest='enable_file_urls', default=False,
528 help='Enable file:// URLs. This is disabled by default for security reasons.'
529 )
0aa10994 530
b31fdeed 531 geo = optparse.OptionGroup(parser, 'Geo-restriction')
0aa10994 532 geo.add_option(
38cce791
YCH
533 '--geo-verification-proxy',
534 dest='geo_verification_proxy', default=None, metavar='URL',
6623ac34 535 help=(
536 'Use this proxy to verify the IP address for some geo-restricted sites. '
8a51f564 537 'The default proxy specified by --proxy (or none, if the option is not present) is used for the actual downloading'))
0aa10994 538 geo.add_option(
91410c9b
PH
539 '--cn-verification-proxy',
540 dest='cn_verification_proxy', default=None, metavar='URL',
0aa10994 541 help=optparse.SUPPRESS_HELP)
c1664464 542 geo.add_option(
543 '--xff', metavar='VALUE',
c8bc203f 544 dest='geo_bypass', default='default',
c1664464 545 help=(
546 'How to fake X-Forwarded-For HTTP header to try bypassing geographic restriction. '
c8bc203f 547 'One of "default" (only when known to be useful), "never", '
548 'an IP block in CIDR notation, or a two-letter ISO 3166-2 country code'))
0aa10994
S
549 geo.add_option(
550 '--geo-bypass',
c1664464 551 action='store_const', dest='geo_bypass', const='default',
552 help=optparse.SUPPRESS_HELP)
0aa10994
S
553 geo.add_option(
554 '--no-geo-bypass',
c1664464 555 action='store_const', dest='geo_bypass', const='never',
556 help=optparse.SUPPRESS_HELP)
0aa10994 557 geo.add_option(
c1664464 558 '--geo-bypass-country', metavar='CODE', dest='geo_bypass',
559 help=optparse.SUPPRESS_HELP)
5f95927a 560 geo.add_option(
c1664464 561 '--geo-bypass-ip-block', metavar='IP_BLOCK', dest='geo_bypass',
562 help=optparse.SUPPRESS_HELP)
be4a824d 563
8450c15c 564 selection = optparse.OptionGroup(parser, 'Video Selection')
34a741a8
PH
565 selection.add_option(
566 '--playlist-start',
567 dest='playliststart', metavar='NUMBER', default=1, type=int,
7e88d7d7 568 help=optparse.SUPPRESS_HELP)
34a741a8
PH
569 selection.add_option(
570 '--playlist-end',
571 dest='playlistend', metavar='NUMBER', default=None, type=int,
7e88d7d7 572 help=optparse.SUPPRESS_HELP)
c14e88f0 573 selection.add_option(
7e88d7d7 574 '-I', '--playlist-items',
c14e88f0 575 dest='playlist_items', metavar='ITEM_SPEC', default=None,
7e88d7d7 576 help=(
71df9b7f 577 'Comma separated playlist_index of the items to download. '
7e88d7d7 578 'You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. '
579 'Use negative indices to count from the right and negative STEP to download in reverse order. '
71df9b7f 580 'E.g. "-I 1:3,7,-5::2" used on a playlist of size 15 will download the items at index 1,2,3,7,11,13,15'))
34a741a8 581 selection.add_option(
8450c15c
PH
582 '--match-title',
583 dest='matchtitle', metavar='REGEX',
8f18aca8 584 help=optparse.SUPPRESS_HELP)
8450c15c
PH
585 selection.add_option(
586 '--reject-title',
587 dest='rejecttitle', metavar='REGEX',
8f18aca8 588 help=optparse.SUPPRESS_HELP)
8450c15c
PH
589 selection.add_option(
590 '--min-filesize',
591 metavar='SIZE', dest='min_filesize', default=None,
46d09f87 592 help='Abort download if filesize is smaller than SIZE, e.g. 50k or 44.6M')
8450c15c
PH
593 selection.add_option(
594 '--max-filesize',
595 metavar='SIZE', dest='max_filesize', default=None,
71df9b7f 596 help='Abort download if filesize is larger than SIZE, e.g. 50k or 44.6M')
8450c15c
PH
597 selection.add_option(
598 '--date',
599 metavar='DATE', dest='date', default=None,
c76eb41b 600 help=(
8e174ba7 601 'Download only videos uploaded on this date. '
602 'The date can be "YYYYMMDD" or in the format [now|today|yesterday][-N[day|week|month|year]]. '
603 'E.g. "--date today-2weeks" downloads only videos uploaded on the same day two weeks ago'))
8450c15c
PH
604 selection.add_option(
605 '--datebefore',
606 metavar='DATE', dest='datebefore', default=None,
c76eb41b 607 help=(
608 'Download only videos uploaded on or before this date. '
609 'The date formats accepted is the same as --date'))
34a741a8 610 selection.add_option(
8450c15c
PH
611 '--dateafter',
612 metavar='DATE', dest='dateafter', default=None,
c76eb41b 613 help=(
614 'Download only videos uploaded on or after this date. '
615 'The date formats accepted is the same as --date'))
34a741a8 616 selection.add_option(
8450c15c
PH
617 '--min-views',
618 metavar='COUNT', dest='min_views', default=None, type=int,
8f18aca8 619 help=optparse.SUPPRESS_HELP)
34a741a8 620 selection.add_option(
8450c15c
PH
621 '--max-views',
622 metavar='COUNT', dest='max_views', default=None, type=int,
8f18aca8 623 help=optparse.SUPPRESS_HELP)
347de493 624 selection.add_option(
b1a7cd05 625 '--match-filters',
626 metavar='FILTER', dest='match_filter', action='append',
347de493 627 help=(
2dd5a2e3 628 'Generic video filter. Any "OUTPUT TEMPLATE" field can be compared with a '
d4ada357 629 'number or a string using the operators defined in "Filtering Formats". '
b1a7cd05 630 'You can also simply specify a field to match if the field is present, '
631 'use "!field" to check if the field is not present, and "&" to check multiple conditions. '
632 'Use a "\\" to escape "&" or quotes if needed. If used multiple times, '
62b58c09 633 'the filter matches if atleast one of the conditions are met. E.g. --match-filter '
b1a7cd05 634 '!is_live --match-filter "like_count>?100 & description~=\'(?i)\\bcats \\& dogs\\b\'" '
635 'matches only videos that are not live OR those that have a like count more than 100 '
636 '(or the like field is not available) and also has a description '
2dd5a2e3 637 'that contains the phrase "cats & dogs" (caseless). '
492272fe 638 'Use "--match-filter -" to interactively ask whether to download each video'))
6623ac34 639 selection.add_option(
c8bc203f 640 '--no-match-filters',
fe2ce85a 641 dest='match_filter', action='store_const', const=None,
642 help='Do not use any --match-filter (default)')
643 selection.add_option(
644 '--break-match-filters',
645 metavar='FILTER', dest='breaking_match_filter', action='append',
646 help='Same as "--match-filters" but stops the download process when a video is rejected')
647 selection.add_option(
648 '--no-break-match-filters',
649 dest='breaking_match_filter', action='store_const', const=None,
650 help='Do not use any --break-match-filters (default)')
34a741a8 651 selection.add_option(
8450c15c
PH
652 '--no-playlist',
653 action='store_true', dest='noplaylist', default=False,
8a51f564 654 help='Download only the video, if the URL refers to a video and a playlist')
df4bd0d5
PH
655 selection.add_option(
656 '--yes-playlist',
f0884c8b 657 action='store_false', dest='noplaylist',
8a51f564 658 help='Download the playlist, if the URL refers to a video and a playlist')
8450c15c
PH
659 selection.add_option(
660 '--age-limit',
661 metavar='YEARS', dest='age_limit', default=None, type=int,
17941321 662 help='Download only videos suitable for the given age')
8450c15c
PH
663 selection.add_option(
664 '--download-archive', metavar='FILE',
665 dest='download_archive',
8a51f564 666 help='Download only videos not listed in the archive file. Record the IDs of all downloaded videos in it')
f304da8a 667 selection.add_option(
668 '--no-download-archive',
669 dest='download_archive', action="store_const", const=None,
670 help='Do not use archive file (default)')
671 selection.add_option(
672 '--max-downloads',
673 dest='max_downloads', metavar='NUMBER', type=int, default=None,
674 help='Abort after downloading NUMBER files')
ea6e0c2b 675 selection.add_option(
676 '--break-on-existing',
677 action='store_true', dest='break_on_existing', default=False,
8a51f564 678 help='Stop the download process when encountering a file that is in the archive')
8b0d7497 679 selection.add_option(
680 '--break-on-reject',
681 action='store_true', dest='break_on_reject', default=False,
fe2ce85a 682 help=optparse.SUPPRESS_HELP)
b222c271 683 selection.add_option(
684 '--break-per-input',
685 action='store_true', dest='break_per_url', default=False,
fe2ce85a 686 help='Alters --max-downloads, --break-on-existing, --break-match-filter, and autonumber to reset per input URL')
b222c271 687 selection.add_option(
688 '--no-break-per-input',
689 action='store_false', dest='break_per_url',
490110c5 690 help='--break-on-existing and similar options terminates the entire download queue')
26e2805c 691 selection.add_option(
692 '--skip-playlist-after-errors', metavar='N',
693 dest='skip_playlist_after_errors', default=None, type=int,
694 help='Number of allowed failures until the rest of the playlist is skipped')
8450c15c
PH
695 selection.add_option(
696 '--include-ads',
697 dest='include_ads', action='store_true',
d9aa2332 698 help=optparse.SUPPRESS_HELP)
6623ac34 699 selection.add_option(
700 '--no-include-ads',
701 dest='include_ads', action='store_false',
d9aa2332 702 help=optparse.SUPPRESS_HELP)
34a741a8 703
8450c15c
PH
704 authentication = optparse.OptionGroup(parser, 'Authentication Options')
705 authentication.add_option(
706 '-u', '--username',
707 dest='username', metavar='USERNAME',
17941321 708 help='Login with this account ID')
8450c15c
PH
709 authentication.add_option(
710 '-p', '--password',
711 dest='password', metavar='PASSWORD',
7a5c1cfe 712 help='Account password. If this option is left out, yt-dlp will ask interactively')
8450c15c
PH
713 authentication.add_option(
714 '-2', '--twofactor',
715 dest='twofactor', metavar='TWOFACTOR',
3540fe26 716 help='Two-factor authentication code')
8450c15c
PH
717 authentication.add_option(
718 '-n', '--netrc',
719 action='store_true', dest='usenetrc', default=False,
17941321 720 help='Use .netrc authentication data')
0001fcb5 721 authentication.add_option(
722 '--netrc-location',
723 dest='netrc_location', metavar='PATH',
724 help='Location of .netrc authentication data; either the path or its containing directory. Defaults to ~/.netrc')
db3ad8a6
ND
725 authentication.add_option(
726 '--netrc-cmd',
727 dest='netrc_cmd', metavar='NETRC_CMD',
728 help='Command to execute to get the credentials for an extractor.')
8450c15c
PH
729 authentication.add_option(
730 '--video-password',
731 dest='videopassword', metavar='PASSWORD',
b634ba74 732 help='Video-specific password')
b31fdeed 733 authentication.add_option(
797c636b
RA
734 '--ap-mso',
735 dest='ap_mso', metavar='MSO',
537f7533 736 help='Adobe Pass multiple-system operator (TV provider) identifier, use --ap-list-mso for a list of available MSOs')
b31fdeed 737 authentication.add_option(
1b6712ab 738 '--ap-username',
797c636b 739 dest='ap_username', metavar='USERNAME',
537f7533 740 help='Multiple-system operator account login')
b31fdeed 741 authentication.add_option(
1b6712ab 742 '--ap-password',
797c636b 743 dest='ap_password', metavar='PASSWORD',
7a5c1cfe 744 help='Multiple-system operator account password. If this option is left out, yt-dlp will ask interactively')
b31fdeed 745 authentication.add_option(
87148bb7
RA
746 '--ap-list-mso',
747 action='store_true', dest='ap_list_mso', default=False,
537f7533 748 help='List all supported multiple-system operators')
bb58c9ed 749 authentication.add_option(
750 '--client-certificate',
751 dest='client_certificate', metavar='CERTFILE',
752 help='Path to client certificate file in PEM format. May include the private key')
753 authentication.add_option(
754 '--client-certificate-key',
755 dest='client_certificate_key', metavar='KEYFILE',
756 help='Path to private key file for client certificate')
757 authentication.add_option(
758 '--client-certificate-password',
759 dest='client_certificate_password', metavar='PASSWORD',
760 help='Password for client certificate private key, if encrypted. '
2dd5a2e3 761 'If not provided, and the key is encrypted, yt-dlp will ask interactively')
8450c15c
PH
762
763 video_format = optparse.OptionGroup(parser, 'Video Format Options')
764 video_format.add_option(
765 '-f', '--format',
766 action='store', dest='format', metavar='FORMAT', default=None,
eb8a4433 767 help='Video format code, see "FORMAT SELECTION" for more details')
768 video_format.add_option(
c76eb41b 769 '-S', '--format-sort', metavar='SORTORDER',
e632bce2 770 dest='format_sort', default=[], type='str', action='callback',
771 callback=_list_from_options_callback, callback_kwargs={'append': -1},
eb8a4433 772 help='Sort the formats by the fields given, see "Sorting Formats" for more details')
773 video_format.add_option(
774 '--format-sort-force', '--S-force',
775 action='store_true', dest='format_sort_force', metavar='FORMAT', default=False,
776 help=(
777 'Force user specified sort order to have precedence over all fields, '
2dd5a2e3 778 'see "Sorting Formats" for more details (Alias: --S-force)'))
eb8a4433 779 video_format.add_option(
780 '--no-format-sort-force',
781 action='store_false', dest='format_sort_force', metavar='FORMAT', default=False,
2dd5a2e3 782 help='Some fields have precedence over the user specified sort order (default)')
909d24dd 783 video_format.add_option(
784 '--video-multistreams',
53ed7066 785 action='store_true', dest='allow_multiple_video_streams', default=None,
91ebc640 786 help='Allow multiple video streams to be merged into a single file')
909d24dd 787 video_format.add_option(
788 '--no-video-multistreams',
789 action='store_false', dest='allow_multiple_video_streams',
91ebc640 790 help='Only one video stream is downloaded for each output file (default)')
909d24dd 791 video_format.add_option(
792 '--audio-multistreams',
53ed7066 793 action='store_true', dest='allow_multiple_audio_streams', default=None,
91ebc640 794 help='Allow multiple audio streams to be merged into a single file')
909d24dd 795 video_format.add_option(
796 '--no-audio-multistreams',
797 action='store_false', dest='allow_multiple_audio_streams',
91ebc640 798 help='Only one audio stream is downloaded for each output file (default)')
8450c15c
PH
799 video_format.add_option(
800 '--all-formats',
801 action='store_const', dest='format', const='all',
d9aa2332 802 help=optparse.SUPPRESS_HELP)
8450c15c
PH
803 video_format.add_option(
804 '--prefer-free-formats',
805 action='store_true', dest='prefer_free_formats', default=False,
da9be05e 806 help=(
807 'Prefer video formats with free containers over non-free ones of same quality. '
808 'Use with "-S ext" to strictly prefer free containers irrespective of quality'))
809 video_format.add_option(
810 '--no-prefer-free-formats',
1c36c1f3 811 action='store_false', dest='prefer_free_formats', default=False,
da9be05e 812 help="Don't give any special preference to free containers (default)")
e8e73840 813 video_format.add_option(
814 '--check-formats',
9f1a1c36 815 action='store_const', const='selected', dest='check_formats', default=None,
ebc7d3ff 816 help='Make sure formats are selected only from those that are actually downloadable')
9f1a1c36 817 video_format.add_option(
818 '--check-all-formats',
819 action='store_true', dest='check_formats',
820 help='Check all formats for whether they are actually downloadable')
0ba692ac 821 video_format.add_option(
822 '--no-check-formats',
823 action='store_false', dest='check_formats',
9f1a1c36 824 help='Do not check that the formats are actually downloadable')
8450c15c
PH
825 video_format.add_option(
826 '-F', '--list-formats',
827 action='store_true', dest='listformats',
b7b04c78 828 help='List available formats of each video. Simulate unless --no-simulate is used')
76d321f6 829 video_format.add_option(
830 '--list-formats-as-table',
91ebc640 831 action='store_true', dest='listformats_table', default=True,
53ed7066 832 help=optparse.SUPPRESS_HELP)
76d321f6 833 video_format.add_option(
6623ac34 834 '--list-formats-old', '--no-list-formats-as-table',
76d321f6 835 action='store_false', dest='listformats_table',
53ed7066 836 help=optparse.SUPPRESS_HELP)
d120e901 837 video_format.add_option(
bd1a281e
PH
838 '--merge-output-format',
839 action='store', dest='merge_output_format', metavar='FORMAT', default=None,
d120e901 840 help=(
62b58c09 841 'Containers that may be used when merging formats, separated by "/", e.g. "mp4/mkv". '
fc61aff4 842 'Ignored if no merge is required. '
4f04be6a 843 f'(currently supported: {", ".join(sorted(FFmpegMergerPP.SUPPORTED_EXTS))})'))
63ad4d43 844 video_format.add_option(
845 '--allow-unplayable-formats',
846 action='store_true', dest='allow_unplayable_formats', default=False,
88acdbc2 847 help=optparse.SUPPRESS_HELP)
63ad4d43 848 video_format.add_option(
849 '--no-allow-unplayable-formats',
850 action='store_false', dest='allow_unplayable_formats',
88acdbc2 851 help=optparse.SUPPRESS_HELP)
8450c15c
PH
852
853 subtitles = optparse.OptionGroup(parser, 'Subtitle Options')
854 subtitles.add_option(
6623ac34 855 '--write-subs', '--write-srt',
8450c15c 856 action='store_true', dest='writesubtitles', default=False,
17941321 857 help='Write subtitle file')
8450c15c 858 subtitles.add_option(
6623ac34 859 '--no-write-subs', '--no-write-srt',
860 action='store_false', dest='writesubtitles',
861 help='Do not write subtitle file (default)')
862 subtitles.add_option(
863 '--write-auto-subs', '--write-automatic-subs',
8450c15c 864 action='store_true', dest='writeautomaticsub', default=False,
e167860c 865 help='Write automatically generated subtitle file (Alias: --write-automatic-subs)')
6623ac34 866 subtitles.add_option(
867 '--no-write-auto-subs', '--no-write-automatic-subs',
868 action='store_false', dest='writeautomaticsub', default=False,
e167860c 869 help='Do not write auto-generated subtitles (default) (Alias: --no-write-automatic-subs)')
8450c15c
PH
870 subtitles.add_option(
871 '--all-subs',
872 action='store_true', dest='allsubtitles', default=False,
c32b0aab 873 help=optparse.SUPPRESS_HELP)
8450c15c
PH
874 subtitles.add_option(
875 '--list-subs',
876 action='store_true', dest='listsubtitles', default=False,
b7b04c78 877 help='List available subtitles of each video. Simulate unless --no-simulate is used')
8450c15c
PH
878 subtitles.add_option(
879 '--sub-format',
a504ced0 880 action='store', dest='subtitlesformat', metavar='FORMAT', default='best',
62b58c09 881 help='Subtitle format; accepts formats preference, e.g. "srt" or "ass/srt/best"')
8450c15c 882 subtitles.add_option(
e167860c 883 '--sub-langs', '--srt-langs',
8450c15c 884 action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
e632bce2 885 default=[], callback=_list_from_options_callback,
c32b0aab 886 help=(
62b58c09
L
887 'Languages of the subtitles to download (can be regex) or "all" separated by commas, e.g. --sub-langs "en.*,ja". '
888 'You can prefix the language code with a "-" to exclude it from the requested languages, e.g. --sub-langs all,-live_chat. '
c32b0aab 889 'Use --list-subs for a list of available language tags'))
8450c15c
PH
890
891 downloader = optparse.OptionGroup(parser, 'Download Options')
4cf1e5d2 892 downloader.add_option(
893 '-N', '--concurrent-fragments',
894 dest='concurrent_fragment_downloads', metavar='N', default=1, type=int,
b69fd25c 895 help='Number of fragments of a dash/hlsnative video that should be downloaded concurrently (default is %default)')
8450c15c 896 downloader.add_option(
8ec2b2c4
S
897 '-r', '--limit-rate', '--rate-limit',
898 dest='ratelimit', metavar='RATE',
62b58c09 899 help='Maximum download rate in bytes per second, e.g. 50K or 4.2M')
51d9739f 900 downloader.add_option(
901 '--throttled-rate',
902 dest='throttledratelimit', metavar='RATE',
62b58c09 903 help='Minimum download rate in bytes per second below which throttling is assumed and the video data is re-extracted, e.g. 100K')
8450c15c
PH
904 downloader.add_option(
905 '-R', '--retries',
906 dest='retries', metavar='RETRIES', default=10,
8a51f564 907 help='Number of retries (default is %default), or "infinite"')
205a0654
EH
908 downloader.add_option(
909 '--file-access-retries',
45806d44 910 dest='file_access_retries', metavar='RETRIES', default=3,
205a0654 911 help='Number of times to retry on file access error (default is %default), or "infinite"')
52bb437e
S
912 downloader.add_option(
913 '--fragment-retries',
914 dest='fragment_retries', metavar='RETRIES', default=10,
12ee65ea 915 help='Number of retries for a fragment (default is %default), or "infinite" (DASH, hlsnative and ISM)')
23326151 916 downloader.add_option(
917 '--retry-sleep',
918 dest='retry_sleep', metavar='[TYPE:]EXPR', default={}, type='str',
919 action='callback', callback=_dict_from_options_callback,
920 callback_kwargs={
be5c1ae8 921 'allowed_keys': 'http|fragment|file_access|extractor',
23326151 922 'default_key': 'http',
923 }, help=(
be5c1ae8 924 'Time to sleep between retries in seconds (optionally) prefixed by the type of retry '
925 '(http (default), fragment, file_access, extractor) to apply the sleep to. '
2dd5a2e3 926 'EXPR can be a number, linear=START[:END[:STEP=1]] or exp=START[:END[:BASE=2]]. '
62b58c09
L
927 'This option can be used multiple times to set the sleep for the different retry types, '
928 'e.g. --retry-sleep linear=1::2 --retry-sleep fragment:exp=1:20'))
9603b660 929 downloader.add_option(
08e29b9f 930 '--skip-unavailable-fragments', '--no-abort-on-unavailable-fragments',
9603b660 931 action='store_true', dest='skip_unavailable_fragments', default=True,
08e29b9f 932 help='Skip unavailable fragments for DASH, hlsnative and ISM downloads (default) (Alias: --no-abort-on-unavailable-fragments)')
732fb3f8 933 downloader.add_option(
08e29b9f 934 '--abort-on-unavailable-fragments', '--no-skip-unavailable-fragments',
9603b660 935 action='store_false', dest='skip_unavailable_fragments',
2dd5a2e3 936 help='Abort download if a fragment is unavailable (Alias: --no-skip-unavailable-fragments)')
0eee52f3
S
937 downloader.add_option(
938 '--keep-fragments',
939 action='store_true', dest='keep_fragments', default=False,
6623ac34 940 help='Keep downloaded fragments on disk after downloading is finished')
941 downloader.add_option(
942 '--no-keep-fragments',
943 action='store_false', dest='keep_fragments',
944 help='Delete downloaded fragments after downloading is finished (default)')
8450c15c
PH
945 downloader.add_option(
946 '--buffer-size',
947 dest='buffersize', metavar='SIZE', default='1024',
62b58c09 948 help='Size of download buffer, e.g. 1024 or 16K (default is %default)')
6623ac34 949 downloader.add_option(
950 '--resize-buffer',
951 action='store_false', dest='noresizebuffer',
952 help='The buffer size is automatically resized from an initial value of --buffer-size (default)')
8450c15c
PH
953 downloader.add_option(
954 '--no-resize-buffer',
955 action='store_true', dest='noresizebuffer', default=False,
6623ac34 956 help='Do not automatically adjust the buffer size')
ba515388
S
957 downloader.add_option(
958 '--http-chunk-size',
959 dest='http_chunk_size', metavar='SIZE', default=None,
6623ac34 960 help=(
62b58c09 961 'Size of a chunk for chunk-based HTTP downloading, e.g. 10485760 or 10M (default is disabled). '
6623ac34 962 'May be useful for bypassing bandwidth throttling imposed by a webserver (experimental)'))
8450c15c
PH
963 downloader.add_option(
964 '--test',
965 action='store_true', dest='test', default=False,
966 help=optparse.SUPPRESS_HELP)
ff815fe6
MS
967 downloader.add_option(
968 '--playlist-reverse',
7e9a6125 969 action='store_true', dest='playlist_reverse',
7e88d7d7 970 help=optparse.SUPPRESS_HELP)
6623ac34 971 downloader.add_option(
972 '--no-playlist-reverse',
c76eb41b 973 action='store_false', dest='playlist_reverse',
7e88d7d7 974 help=optparse.SUPPRESS_HELP)
75822ca7
TC
975 downloader.add_option(
976 '--playlist-random',
7e9a6125 977 action='store_true', dest='playlist_random',
75822ca7 978 help='Download playlist videos in random order')
7e9a6125 979 downloader.add_option(
980 '--lazy-playlist',
981 action='store_true', dest='lazy_playlist',
982 help='Process entries in the playlist as they are received. This disables n_entries, --playlist-random and --playlist-reverse')
983 downloader.add_option(
984 '--no-lazy-playlist',
985 action='store_false', dest='lazy_playlist',
986 help='Process videos in the playlist only after the entire playlist is parsed (default)')
881e6a1f
PH
987 downloader.add_option(
988 '--xattr-set-filesize',
989 dest='xattr_set_filesize', action='store_true',
504f20dd 990 help='Set file xattribute ytdl.filesize with expected file size')
85729c51
PH
991 downloader.add_option(
992 '--hls-prefer-native',
bf09af3a 993 dest='hls_prefer_native', action='store_true', default=None,
52a8a1e1 994 help=optparse.SUPPRESS_HELP)
bf09af3a
S
995 downloader.add_option(
996 '--hls-prefer-ffmpeg',
997 dest='hls_prefer_native', action='store_false', default=None,
52a8a1e1 998 help=optparse.SUPPRESS_HELP)
7d106a65
JMF
999 downloader.add_option(
1000 '--hls-use-mpegts',
9bd20204 1001 dest='hls_use_mpegts', action='store_true', default=None,
6623ac34 1002 help=(
9bd20204 1003 'Use the mpegts container for HLS videos; '
1004 'allowing some players to play the video while downloading, '
1005 'and reducing the chance of file corruption if download is interrupted. '
1006 'This is enabled by default for live streams'))
1007 downloader.add_option(
1008 '--no-hls-use-mpegts',
1009 dest='hls_use_mpegts', action='store_false',
1010 help=(
1011 'Do not use the mpegts container for HLS videos. '
1012 'This is default when not downloading live streams'))
5ec1b6b7 1013 downloader.add_option(
1014 '--download-sections',
1015 metavar='REGEX', dest='download_ranges', action='append',
1016 help=(
b4e0d758 1017 'Download only chapters that match the regular expression. '
1018 'A "*" prefix denotes time-range instead of chapter. Negative timestamps are calculated from the end. '
1019 '"*from-url" can be used to download between the "start_time" and "end_time" extracted from the URL. '
62b58c09 1020 'Needs ffmpeg. This option can be used multiple times to download multiple sections, '
fc2ba496 1021 'e.g. --download-sections "*10:15-inf" --download-sections "intro"'))
222516d9 1022 downloader.add_option(
52a8a1e1 1023 '--downloader', '--external-downloader',
1024 dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str',
e632bce2 1025 action='callback', callback=_dict_from_options_callback,
52a8a1e1 1026 callback_kwargs={
1027 'allowed_keys': 'http|ftp|m3u8|dash|rtsp|rtmp|mms',
cc0ec3e1 1028 'default_key': 'default',
dbf5416a 1029 'process': str.strip
1030 }, help=(
52a8a1e1 1031 'Name or path of the external downloader to use (optionally) prefixed by '
1032 'the protocols (http, ftp, m3u8, dash, rstp, rtmp, mms) to use it for. '
8dc59305 1033 f'Currently supports native, {", ".join(sorted(list_external_downloaders()))}. '
52a8a1e1 1034 'You can use this option multiple times to set different downloaders for different protocols. '
62b58c09 1035 'E.g. --downloader aria2c --downloader "dash,m3u8:native" will use '
52a8a1e1 1036 'aria2c for http/ftp downloads, and the native downloader for dash/m3u8 downloads '
0a41f331 1037 '(Alias: --external-downloader)'))
c75f0b36 1038 downloader.add_option(
46ee996e 1039 '--downloader-args', '--external-downloader-args',
1040 metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str',
e632bce2 1041 action='callback', callback=_dict_from_options_callback,
b8f6bbe6 1042 callback_kwargs={
9e907ebd 1043 'allowed_keys': r'ffmpeg_[io]\d*|%s' % '|'.join(map(re.escape, list_external_downloaders())),
cc0ec3e1 1044 'default_key': 'default',
f9934b96 1045 'process': shlex.split
dbf5416a 1046 }, help=(
46ee996e 1047 'Give these arguments to the external downloader. '
1048 'Specify the downloader name and the arguments separated by a colon ":". '
330690a2 1049 'For ffmpeg, arguments can be passed to different positions using the same syntax as --postprocessor-args. '
5d3a0e79 1050 'You can use this option multiple times to give different arguments to different downloaders '
1051 '(Alias: --external-downloader-args)'))
8450c15c
PH
1052
1053 workarounds = optparse.OptionGroup(parser, 'Workarounds')
34a741a8 1054 workarounds.add_option(
8450c15c
PH
1055 '--encoding',
1056 dest='encoding', metavar='ENCODING',
34a741a8 1057 help='Force the specified encoding (experimental)')
f81c62a6 1058 workarounds.add_option(
1059 '--legacy-server-connect',
1060 action='store_true', dest='legacy_server_connect', default=False,
1061 help='Explicitly allow HTTPS connection to servers that do not support RFC 5746 secure renegotiation')
34a741a8 1062 workarounds.add_option(
e6f21b3d 1063 '--no-check-certificates',
8450c15c 1064 action='store_true', dest='no_check_certificate', default=False,
17941321 1065 help='Suppress HTTPS certificate validation')
34a741a8 1066 workarounds.add_option(
6623ac34 1067 '--prefer-insecure', '--prefer-unsecure',
1068 action='store_true', dest='prefer_insecure',
e167860c 1069 help='Use an unencrypted connection to retrieve information about the video (Currently supported only for YouTube)')
34a741a8 1070 workarounds.add_option(
8450c15c
PH
1071 '--user-agent',
1072 metavar='UA', dest='user_agent',
8b7539d2 1073 help=optparse.SUPPRESS_HELP)
34a741a8 1074 workarounds.add_option(
8450c15c
PH
1075 '--referer',
1076 metavar='URL', dest='referer', default=None,
8b7539d2 1077 help=optparse.SUPPRESS_HELP)
34a741a8 1078 workarounds.add_option(
a5387729 1079 '--add-headers',
45016689 1080 metavar='FIELD:VALUE', dest='headers', default={}, type='str',
e632bce2 1081 action='callback', callback=_dict_from_options_callback,
8b7539d2 1082 callback_kwargs={'multiple_keys': False},
45016689 1083 help='Specify a custom HTTP header and its value, separated by a colon ":". You can use this option multiple times',
34a741a8
PH
1084 )
1085 workarounds.add_option(
8450c15c
PH
1086 '--bidi-workaround',
1087 dest='bidi_workaround', action='store_true',
1088 help='Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH')
1cf376f5 1089 workarounds.add_option(
1090 '--sleep-requests', metavar='SECONDS',
1091 dest='sleep_interval_requests', type=float,
1092 help='Number of seconds to sleep between requests during data extraction')
5f0d813d 1093 workarounds.add_option(
065bc354 1094 '--sleep-interval', '--min-sleep-interval', metavar='SECONDS',
649f7966 1095 dest='sleep_interval', type=float,
7aa589a5 1096 help=(
e167860c 1097 'Number of seconds to sleep before each download. '
1098 'This is the minimum time to sleep when used along with --max-sleep-interval '
1099 '(Alias: --min-sleep-interval)'))
065bc354 1100 workarounds.add_option(
1101 '--max-sleep-interval', metavar='SECONDS',
1102 dest='max_sleep_interval', type=float,
e167860c 1103 help='Maximum number of seconds to sleep. Can only be used along with --min-sleep-interval')
0c9df79e 1104 workarounds.add_option(
c76eb41b 1105 '--sleep-subtitles', metavar='SECONDS',
31108ce9 1106 dest='sleep_interval_subtitles', default=0, type=int,
1cf376f5 1107 help='Number of seconds to sleep before each subtitle download')
34a741a8 1108
0744a815 1109 verbosity = optparse.OptionGroup(parser, 'Verbosity and Simulation Options')
8450c15c
PH
1110 verbosity.add_option(
1111 '-q', '--quiet',
d669772c 1112 action='store_true', dest='quiet', default=None,
34488702 1113 help='Activate quiet mode. If used with --verbose, print the log to stderr')
d669772c 1114 verbosity.add_option(
1115 '--no-quiet',
1116 action='store_false', dest='quiet',
1117 help='Deactivate quiet mode. (Default)')
34a741a8
PH
1118 verbosity.add_option(
1119 '--no-warnings',
1120 dest='no_warnings', action='store_true', default=False,
1121 help='Ignore warnings')
8450c15c
PH
1122 verbosity.add_option(
1123 '-s', '--simulate',
b7b04c78 1124 action='store_true', dest='simulate', default=None,
17941321 1125 help='Do not download the video and do not write anything to disk')
b7b04c78 1126 verbosity.add_option(
1127 '--no-simulate',
1128 action='store_false', dest='simulate',
1129 help='Download the video even if printing/listing options are used')
b7da73eb 1130 verbosity.add_option(
1131 '--ignore-no-formats-error',
1132 action='store_true', dest='ignore_no_formats_error', default=False,
1133 help=(
0930b11f 1134 'Ignore "No video formats" error. Useful for extracting metadata '
34488702 1135 'even if the videos are not actually available for download (experimental)'))
b7da73eb 1136 verbosity.add_option(
1137 '--no-ignore-no-formats-error',
1138 action='store_false', dest='ignore_no_formats_error',
1139 help='Throw error when no downloadable video formats are found (default)')
8450c15c 1140 verbosity.add_option(
6623ac34 1141 '--skip-download', '--no-download',
8450c15c 1142 action='store_true', dest='skip_download', default=False,
e167860c 1143 help='Do not download the video but write all related files (Alias: --no-download)')
53c18592 1144 verbosity.add_option(
ad3dc496 1145 '-O', '--print',
119e40ef 1146 metavar='[WHEN:]TEMPLATE', dest='forceprint', **when_prefix('video'),
1147 help=(
ed5835b4 1148 'Field name or output template to print to screen, optionally prefixed with when to print it, separated by a ":". '
119e40ef 1149 'Supported values of "WHEN" are the same as that of --use-postprocessor (default: video). '
62f6f1cb 1150 'Implies --quiet. Implies --simulate unless --no-simulate or later stages of WHEN are used. '
1151 'This option can be used multiple times'))
bb66c247 1152 verbosity.add_option(
1153 '--print-to-file',
119e40ef 1154 metavar='[WHEN:]TEMPLATE FILE', dest='print_to_file', nargs=2, **when_prefix('video'),
1155 help=(
bb66c247 1156 'Append given template to the file. The values of WHEN and TEMPLATE are same as that of --print. '
1157 'FILE uses the same syntax as the output template. This option can be used multiple times'))
8450c15c
PH
1158 verbosity.add_option(
1159 '-g', '--get-url',
1160 action='store_true', dest='geturl', default=False,
53c18592 1161 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1162 verbosity.add_option(
1163 '-e', '--get-title',
1164 action='store_true', dest='gettitle', default=False,
53c18592 1165 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1166 verbosity.add_option(
1167 '--get-id',
1168 action='store_true', dest='getid', default=False,
53c18592 1169 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1170 verbosity.add_option(
1171 '--get-thumbnail',
1172 action='store_true', dest='getthumbnail', default=False,
53c18592 1173 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1174 verbosity.add_option(
1175 '--get-description',
1176 action='store_true', dest='getdescription', default=False,
53c18592 1177 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1178 verbosity.add_option(
1179 '--get-duration',
1180 action='store_true', dest='getduration', default=False,
53c18592 1181 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1182 verbosity.add_option(
1183 '--get-filename',
1184 action='store_true', dest='getfilename', default=False,
53c18592 1185 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1186 verbosity.add_option(
1187 '--get-format',
1188 action='store_true', dest='getformat', default=False,
53c18592 1189 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1190 verbosity.add_option(
1191 '-j', '--dump-json',
1192 action='store_true', dest='dumpjson', default=False,
b7b04c78 1193 help='Quiet, but print JSON information for each video. Simulate unless --no-simulate is used. See "OUTPUT TEMPLATE" for a description of available keys')
63e0be34
PH
1194 verbosity.add_option(
1195 '-J', '--dump-single-json',
1196 action='store_true', dest='dump_single_json', default=False,
6623ac34 1197 help=(
b7b04c78 1198 'Quiet, but print JSON information for each url or infojson passed. Simulate unless --no-simulate is used. '
1199 'If the URL refers to a playlist, the whole playlist information is dumped in a single line'))
c0bdf32a
PH
1200 verbosity.add_option(
1201 '--print-json',
1202 action='store_true', dest='print_json', default=False,
b7b04c78 1203 help=optparse.SUPPRESS_HELP)
2d30509f 1204 verbosity.add_option(
c76eb41b 1205 '--force-write-archive', '--force-write-download-archive', '--force-download-archive',
2d30509f 1206 action='store_true', dest='force_write_download_archive', default=False,
1207 help=(
e58c22a0 1208 'Force download archive entries to be written as far as no errors occur, '
1209 'even if -s or another simulation option is used (Alias: --force-download-archive)'))
8450c15c
PH
1210 verbosity.add_option(
1211 '--newline',
1212 action='store_true', dest='progress_with_newline', default=False,
17941321 1213 help='Output progress bar as new lines')
8450c15c
PH
1214 verbosity.add_option(
1215 '--no-progress',
819e0531 1216 action='store_true', dest='noprogress', default=None,
17941321 1217 help='Do not print progress bar')
819e0531 1218 verbosity.add_option(
1219 '--progress',
1220 action='store_false', dest='noprogress',
1221 help='Show progress bar, even if in quiet mode')
8450c15c
PH
1222 verbosity.add_option(
1223 '--console-title',
1224 action='store_true', dest='consoletitle', default=False,
17941321 1225 help='Display progress in console titlebar')
819e0531 1226 verbosity.add_option(
1227 '--progress-template',
1228 metavar='[TYPES:]TEMPLATE', dest='progress_template', default={}, type='str',
1229 action='callback', callback=_dict_from_options_callback,
1230 callback_kwargs={
1231 'allowed_keys': '(download|postprocess)(-title)?',
1232 'default_key': 'download'
1233 }, help=(
1234 'Template for progress outputs, optionally prefixed with one of "download:" (default), '
1235 '"download-title:" (the console title), "postprocess:", or "postprocess-title:". '
1236 'The video\'s fields are accessible under the "info" key and '
62b58c09 1237 'the progress attributes are accessible under "progress" key. E.g. '
819e0531 1238 # TODO: Document the fields inside "progress"
1239 '--console-title --progress-template "download-title:%(info.id)s-%(progress.eta)s"'))
8450c15c
PH
1240 verbosity.add_option(
1241 '-v', '--verbose',
1242 action='store_true', dest='verbose', default=False,
17941321 1243 help='Print various debugging information')
8450c15c 1244 verbosity.add_option(
8bba753c 1245 '--dump-pages', '--dump-intermediate-pages',
8450c15c 1246 action='store_true', dest='dump_intermediate_pages', default=False,
79979c68 1247 help='Print downloaded pages encoded using base64 to debug problems (very verbose)')
8450c15c
PH
1248 verbosity.add_option(
1249 '--write-pages',
1250 action='store_true', dest='write_pages', default=False,
1251 help='Write downloaded intermediary pages to files in the current directory to debug problems')
f95b9dee 1252 verbosity.add_option(
1253 '--load-pages',
1254 action='store_true', dest='load_pages', default=False,
1255 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1256 verbosity.add_option(
1257 '--youtube-print-sig-code',
1258 action='store_true', dest='youtube_print_sig_code', default=False,
1259 help=optparse.SUPPRESS_HELP)
1260 verbosity.add_option(
2f543a21 1261 '--print-traffic', '--dump-headers',
8450c15c
PH
1262 dest='debug_printtraffic', action='store_true', default=False,
1263 help='Display sent and read HTTP traffic')
58b1f00d
PH
1264 verbosity.add_option(
1265 '-C', '--call-home',
1266 dest='call_home', action='store_true', default=False,
19a03940 1267 # help='Contact the yt-dlp server for debugging')
8d801631 1268 help=optparse.SUPPRESS_HELP)
8bfa7545
PH
1269 verbosity.add_option(
1270 '--no-call-home',
6623ac34 1271 dest='call_home', action='store_false',
7a5c1cfe 1272 # help='Do not contact the yt-dlp server for debugging (default)')
8d801631 1273 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1274
1275 filesystem = optparse.OptionGroup(parser, 'Filesystem Options')
1276 filesystem.add_option(
1277 '-a', '--batch-file',
1278 dest='batchfile', metavar='FILE',
940a67a3 1279 help=(
1280 'File containing URLs to download ("-" for stdin), one URL per line. '
1281 'Lines starting with "#", ";" or "]" are considered as comments and ignored'))
1e520b55
Z
1282 filesystem.add_option(
1283 '--no-batch-file',
1284 dest='batchfile', action='store_const', const=None,
1285 help='Do not read URLs from batch file (default)')
19b824f6 1286 filesystem.add_option(
1287 '--id', default=False,
1288 action='store_true', dest='useid', help=optparse.SUPPRESS_HELP)
0202b52a 1289 filesystem.add_option(
1290 '-P', '--paths',
d74a58a1 1291 metavar='[TYPES:]PATH', dest='paths', default={}, type='str',
e632bce2 1292 action='callback', callback=_dict_from_options_callback,
d74a58a1 1293 callback_kwargs={
9e907ebd 1294 'allowed_keys': 'home|temp|%s' % '|'.join(map(re.escape, OUTTMPL_TYPES.keys())),
d74a58a1 1295 'default_key': 'home'
1296 }, help=(
0202b52a 1297 'The paths where the files should be downloaded. '
de6000d9 1298 'Specify the type of file and the path separated by a colon ":". '
6a34813a 1299 'All the same TYPES as --output are supported. '
d74a58a1 1300 'Additionally, you can also provide "home" (default) and "temp" paths. '
0202b52a 1301 'All intermediary files are first downloaded to the temp path and '
1302 'then the final files are moved over to the home path after download is finished. '
de6000d9 1303 'This option is ignored if --output is an absolute path'))
8450c15c
PH
1304 filesystem.add_option(
1305 '-o', '--output',
d818eb74 1306 metavar='[TYPES:]TEMPLATE', dest='outtmpl', default={}, type='str',
e632bce2 1307 action='callback', callback=_dict_from_options_callback,
de6000d9 1308 callback_kwargs={
9e907ebd 1309 'allowed_keys': '|'.join(map(re.escape, OUTTMPL_TYPES.keys())),
cc0ec3e1 1310 'default_key': 'default'
dbf5416a 1311 }, help='Output filename template; see "OUTPUT TEMPLATE" for details')
a820dc72
RA
1312 filesystem.add_option(
1313 '--output-na-placeholder',
0bc0a322 1314 dest='outtmpl_na_placeholder', metavar='TEXT', default='NA',
2dd5a2e3 1315 help=('Placeholder for unavailable fields in "OUTPUT TEMPLATE" (default: "%default")'))
8450c15c
PH
1316 filesystem.add_option(
1317 '--autonumber-size',
be5df5ee
S
1318 dest='autonumber_size', metavar='NUMBER', type=int,
1319 help=optparse.SUPPRESS_HELP)
acbb2374
CP
1320 filesystem.add_option(
1321 '--autonumber-start',
1a241a2d 1322 dest='autonumber_start', metavar='NUMBER', default=1, type=int,
a439a3a4 1323 help=optparse.SUPPRESS_HELP)
8450c15c
PH
1324 filesystem.add_option(
1325 '--restrict-filenames',
1326 action='store_true', dest='restrictfilenames', default=False,
1327 help='Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames')
6623ac34 1328 filesystem.add_option(
1329 '--no-restrict-filenames',
c2934512 1330 action='store_false', dest='restrictfilenames',
6623ac34 1331 help='Allow Unicode characters, "&" and spaces in filenames (default)')
c2934512 1332 filesystem.add_option(
1333 '--windows-filenames',
1334 action='store_true', dest='windowsfilenames', default=False,
0930b11f 1335 help='Force filenames to be Windows-compatible')
c2934512 1336 filesystem.add_option(
1337 '--no-windows-filenames',
1338 action='store_false', dest='windowsfilenames',
0930b11f 1339 help='Make filenames Windows-compatible only if using Windows (default)')
c2934512 1340 filesystem.add_option(
1341 '--trim-filenames', '--trim-file-names', metavar='LENGTH',
1342 dest='trim_file_name', default=0, type=int,
1343 help='Limit the filename length (excluding extension) to the specified number of characters')
8450c15c
PH
1344 filesystem.add_option(
1345 '-w', '--no-overwrites',
0c3d0f51 1346 action='store_false', dest='overwrites', default=None,
1347 help='Do not overwrite any files')
1348 filesystem.add_option(
1349 '--force-overwrites', '--yes-overwrites',
1350 action='store_true', dest='overwrites',
1351 help='Overwrite all video and metadata files. This option includes --no-continue')
1352 filesystem.add_option(
1353 '--no-force-overwrites',
1354 action='store_const', dest='overwrites', const=None,
1355 help='Do not overwrite the video, but overwrite related files (default)')
8450c15c
PH
1356 filesystem.add_option(
1357 '-c', '--continue',
1358 action='store_true', dest='continue_dl', default=True,
c25228e5 1359 help='Resume partially downloaded files/fragments (default)')
8450c15c
PH
1360 filesystem.add_option(
1361 '--no-continue',
1362 action='store_false', dest='continue_dl',
c25228e5 1363 help=(
1364 'Do not resume partially downloaded fragments. '
e58c22a0 1365 'If the file is not fragmented, restart download of the entire file'))
6623ac34 1366 filesystem.add_option(
1367 '--part',
1368 action='store_false', dest='nopart', default=False,
1369 help='Use .part files instead of writing directly into output file (default)')
8450c15c
PH
1370 filesystem.add_option(
1371 '--no-part',
6623ac34 1372 action='store_true', dest='nopart',
17941321 1373 help='Do not use .part files - write directly into output file')
6623ac34 1374 filesystem.add_option(
1375 '--mtime',
1376 action='store_true', dest='updatetime', default=True,
1377 help='Use the Last-modified header to set the file modification time (default)')
8450c15c
PH
1378 filesystem.add_option(
1379 '--no-mtime',
6623ac34 1380 action='store_false', dest='updatetime',
17941321 1381 help='Do not use the Last-modified header to set the file modification time')
8450c15c
PH
1382 filesystem.add_option(
1383 '--write-description',
1384 action='store_true', dest='writedescription', default=False,
17941321 1385 help='Write video description to a .description file')
6623ac34 1386 filesystem.add_option(
1387 '--no-write-description',
1388 action='store_false', dest='writedescription',
1389 help='Do not write video description (default)')
8450c15c
PH
1390 filesystem.add_option(
1391 '--write-info-json',
d1b5f70b 1392 action='store_true', dest='writeinfojson', default=None,
c25228e5 1393 help='Write video metadata to a .info.json file (this may contain personal information)')
6623ac34 1394 filesystem.add_option(
1395 '--no-write-info-json',
1396 action='store_false', dest='writeinfojson',
1397 help='Do not write video metadata (default)')
8450c15c
PH
1398 filesystem.add_option(
1399 '--write-annotations',
1400 action='store_true', dest='writeannotations', default=False,
0bb1bc1b 1401 help=optparse.SUPPRESS_HELP)
6623ac34 1402 filesystem.add_option(
1403 '--no-write-annotations',
1404 action='store_false', dest='writeannotations',
0bb1bc1b 1405 help=optparse.SUPPRESS_HELP)
cac96421 1406 filesystem.add_option(
1407 '--write-playlist-metafiles',
53ed7066 1408 action='store_true', dest='allow_playlist_files', default=None,
cac96421 1409 help=(
1410 'Write playlist metadata in addition to the video metadata '
1411 'when using --write-info-json, --write-description etc. (default)'))
1412 filesystem.add_option(
1413 '--no-write-playlist-metafiles',
1414 action='store_false', dest='allow_playlist_files',
e167860c 1415 help='Do not write playlist metadata when using --write-info-json, --write-description etc.')
75d43ca0 1416 filesystem.add_option(
3856407a 1417 '--clean-info-json', '--clean-infojson',
e4f02757 1418 action='store_true', dest='clean_infojson', default=None,
75d43ca0 1419 help=(
ad54c913 1420 'Remove some internal metadata such as filenames from the infojson (default)'))
75d43ca0 1421 filesystem.add_option(
3856407a 1422 '--no-clean-info-json', '--no-clean-infojson',
75d43ca0 1423 action='store_false', dest='clean_infojson',
1424 help='Write all fields to the infojson')
06167fbb 1425 filesystem.add_option(
2305e2e5 1426 '--write-comments', '--get-comments',
06167fbb 1427 action='store_true', dest='getcomments', default=False,
277d6ff5 1428 help=(
2305e2e5 1429 'Retrieve video comments to be placed in the infojson. '
1430 'The comments are fetched even without this option if the extraction is known to be quick (Alias: --get-comments)'))
1431 filesystem.add_option(
1432 '--no-write-comments', '--no-get-comments',
dd594deb 1433 action='store_false', dest='getcomments',
2305e2e5 1434 help='Do not retrieve video comments unless the extraction is known to be quick (Alias: --no-get-comments)')
8450c15c 1435 filesystem.add_option(
244fe977 1436 '--load-info-json', '--load-info',
8450c15c 1437 dest='load_info_filename', metavar='FILE',
1a48181a 1438 help='JSON file containing the video information (created with the "--write-info-json" option)')
8450c15c
PH
1439 filesystem.add_option(
1440 '--cookies',
1441 dest='cookiefile', metavar='FILE',
f304da8a 1442 help='Netscape formatted file to read cookies from and dump cookie jar in')
6623ac34 1443 filesystem.add_option(
1444 '--no-cookies',
1445 action='store_const', const=None, dest='cookiefile', metavar='FILE',
982ee69a
MB
1446 help='Do not read/dump cookies from/to file (default)')
1447 filesystem.add_option(
1448 '--cookies-from-browser',
825d3ce3 1449 dest='cookiesfrombrowser', metavar='BROWSER[+KEYRING][:PROFILE][::CONTAINER]',
982ee69a 1450 help=(
825d3ce3 1451 'The name of the browser to load cookies from. '
f59f5ef8 1452 f'Currently supported browsers are: {", ".join(sorted(SUPPORTED_BROWSERS))}. '
825d3ce3 1453 'Optionally, the KEYRING used for decrypting Chromium cookies on Linux, '
1454 'the name/path of the PROFILE to load cookies from, '
1455 'and the CONTAINER name (if Firefox) ("none" for no container) '
1456 'can be given with their respective seperators. '
1457 'By default, all containers of the most recently accessed profile are used. '
f59f5ef8 1458 f'Currently supported keyrings are: {", ".join(map(str.lower, sorted(SUPPORTED_KEYRINGS)))}'))
982ee69a
MB
1459 filesystem.add_option(
1460 '--no-cookies-from-browser',
1461 action='store_const', const=None, dest='cookiesfrombrowser',
1462 help='Do not load cookies from browser (default)')
34a741a8
PH
1463 filesystem.add_option(
1464 '--cache-dir', dest='cachedir', default=None, metavar='DIR',
304ad45a 1465 help=(
1466 'Location in the filesystem where yt-dlp can store some downloaded information '
1467 '(such as client ids and signatures) permanently. By default ${XDG_CACHE_HOME}/yt-dlp'))
34a741a8 1468 filesystem.add_option(
6623ac34 1469 '--no-cache-dir', action='store_false', dest='cachedir',
34a741a8
PH
1470 help='Disable filesystem caching')
1471 filesystem.add_option(
8450c15c
PH
1472 '--rm-cache-dir',
1473 action='store_true', dest='rm_cachedir',
34a741a8
PH
1474 help='Delete all filesystem cache files')
1475
b31fdeed 1476 thumbnail = optparse.OptionGroup(parser, 'Thumbnail Options')
cfb56d1a
PH
1477 thumbnail.add_option(
1478 '--write-thumbnail',
acc0d6a4 1479 action='callback', dest='writethumbnail', default=False,
1480 # Should override --no-write-thumbnail, but not --write-all-thumbnail
1481 callback=lambda option, _, __, parser: setattr(
1482 parser.values, option.dest, getattr(parser.values, option.dest) or True),
17941321 1483 help='Write thumbnail image to disk')
6623ac34 1484 thumbnail.add_option(
1485 '--no-write-thumbnail',
1486 action='store_false', dest='writethumbnail',
1487 help='Do not write thumbnail image to disk (default)')
ec82d85a
PH
1488 thumbnail.add_option(
1489 '--write-all-thumbnails',
acc0d6a4 1490 action='store_const', dest='writethumbnail', const='all',
17941321 1491 help='Write all thumbnail image formats to disk')
cfb56d1a
PH
1492 thumbnail.add_option(
1493 '--list-thumbnails',
1494 action='store_true', dest='list_thumbnails', default=False,
b7b04c78 1495 help='List available thumbnails of each video. Simulate unless --no-simulate is used')
cfb56d1a 1496
732044af 1497 link = optparse.OptionGroup(parser, 'Internet Shortcut Options')
1498 link.add_option(
1499 '--write-link',
1500 action='store_true', dest='writelink', default=False,
8a51f564 1501 help='Write an internet shortcut file, depending on the current platform (.url, .webloc or .desktop). The URL may be cached by the OS')
732044af 1502 link.add_option(
1503 '--write-url-link',
1504 action='store_true', dest='writeurllink', default=False,
8a51f564 1505 help='Write a .url Windows internet shortcut. The OS caches the URL based on the file path')
732044af 1506 link.add_option(
1507 '--write-webloc-link',
1508 action='store_true', dest='writewebloclink', default=False,
8a51f564 1509 help='Write a .webloc macOS internet shortcut')
732044af 1510 link.add_option(
1511 '--write-desktop-link',
1512 action='store_true', dest='writedesktoplink', default=False,
8a51f564 1513 help='Write a .desktop Linux internet shortcut')
732044af 1514
1515 postproc = optparse.OptionGroup(parser, 'Post-Processing Options')
8450c15c
PH
1516 postproc.add_option(
1517 '-x', '--extract-audio',
1518 action='store_true', dest='extractaudio', default=False,
e4172ac9 1519 help='Convert video files to audio-only files (requires ffmpeg and ffprobe)')
8450c15c
PH
1520 postproc.add_option(
1521 '--audio-format', metavar='FORMAT', dest='audioformat', default='best',
81a23040 1522 help=(
35faefee 1523 'Format to convert the audio to when -x is used. '
8dc59305 1524 f'(currently supported: best (default), {", ".join(sorted(FFmpegExtractAudioPP.SUPPORTED_EXTS))}). '
e0ab9854 1525 'You can specify multiple rules using similar syntax as --remux-video'))
8450c15c
PH
1526 postproc.add_option(
1527 '--audio-quality', metavar='QUALITY',
1528 dest='audioquality', default='5',
35faefee 1529 help=(
1530 'Specify ffmpeg audio quality to use when converting the audio with -x. '
1531 'Insert a value between 0 (best) and 10 (worst) for VBR or a specific bitrate like 128K (default %default)'))
efe87a10
FS
1532 postproc.add_option(
1533 '--remux-video',
1534 metavar='FORMAT', dest='remuxvideo', default=None,
6623ac34 1535 help=(
35faefee 1536 'Remux the video into another container if necessary '
1537 f'(currently supported: {", ".join(FFmpegVideoRemuxerPP.SUPPORTED_EXTS)}). '
1538 'If target container does not support the video/audio codec, remuxing will fail. You can specify multiple rules; '
62b58c09 1539 'e.g. "aac>m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 and anything else to mkv'))
8450c15c
PH
1540 postproc.add_option(
1541 '--recode-video',
1542 metavar='FORMAT', dest='recodevideo', default=None,
2dd5a2e3 1543 help='Re-encode the video into another format if necessary. The syntax and supported formats are the same as --remux-video')
d84f1d14 1544 postproc.add_option(
45016689 1545 '--postprocessor-args', '--ppa',
1546 metavar='NAME:ARGS', dest='postprocessor_args', default={}, type='str',
e632bce2 1547 action='callback', callback=_dict_from_options_callback,
d818eb74 1548 callback_kwargs={
9e907ebd 1549 'allowed_keys': r'\w+(?:\+\w+)?',
1550 'default_key': 'default-compat',
f9934b96 1551 'process': shlex.split,
cc0ec3e1 1552 'multiple_keys': False
dbf5416a 1553 }, help=(
1b77b347 1554 'Give these arguments to the postprocessors. '
43820c03 1555 'Specify the postprocessor/executable name and the arguments separated by a colon ":" '
8fa43c73 1556 'to give the argument to the specified postprocessor/executable. Supported PP are: '
7a340e0d
NA
1557 'Merger, ModifyChapters, SplitChapters, ExtractAudio, VideoRemuxer, VideoConvertor, '
1558 'Metadata, EmbedSubtitle, EmbedThumbnail, SubtitlesConvertor, ThumbnailsConvertor, '
1559 'FixupStretched, FixupM4a, FixupM3u8, FixupTimestamp and FixupDuration. '
1560 'The supported executables are: AtomicParsley, FFmpeg and FFprobe. '
43820c03 1561 'You can also specify "PP+EXE:ARGS" to give the arguments to the specified executable '
5b1ecbb3 1562 'only when being used by the specified postprocessor. Additionally, for ffmpeg/ffprobe, '
597c1866 1563 '"_i"/"_o" can be appended to the prefix optionally followed by a number to pass the argument '
62b58c09 1564 'before the specified input/output file, e.g. --ppa "Merger+ffmpeg_i1:-v quiet". '
5b1ecbb3 1565 'You can use this option multiple times to give different arguments to different '
1566 'postprocessors. (Alias: --ppa)'))
8450c15c
PH
1567 postproc.add_option(
1568 '-k', '--keep-video',
1569 action='store_true', dest='keepvideo', default=False,
6623ac34 1570 help='Keep the intermediate video file on disk after post-processing')
1571 postproc.add_option(
1572 '--no-keep-video',
1573 action='store_false', dest='keepvideo',
1574 help='Delete the intermediate video file after post-processing (default)')
1575 postproc.add_option(
1576 '--post-overwrites',
1577 action='store_false', dest='nopostoverwrites',
1578 help='Overwrite post-processed files (default)')
8450c15c
PH
1579 postproc.add_option(
1580 '--no-post-overwrites',
1581 action='store_true', dest='nopostoverwrites', default=False,
6623ac34 1582 help='Do not overwrite post-processed files')
8450c15c
PH
1583 postproc.add_option(
1584 '--embed-subs',
1585 action='store_true', dest='embedsubtitles', default=False,
40025ee2 1586 help='Embed subtitles in the video (only for mp4, webm and mkv videos)')
6623ac34 1587 postproc.add_option(
1588 '--no-embed-subs',
1589 action='store_false', dest='embedsubtitles',
1590 help='Do not embed subtitles (default)')
8450c15c
PH
1591 postproc.add_option(
1592 '--embed-thumbnail',
1593 action='store_true', dest='embedthumbnail', default=False,
6aecd871 1594 help='Embed thumbnail in the video as cover art')
6623ac34 1595 postproc.add_option(
1596 '--no-embed-thumbnail',
1597 action='store_false', dest='embedthumbnail',
1598 help='Do not embed thumbnail (default)')
8450c15c 1599 postproc.add_option(
7e067091 1600 '--embed-metadata', '--add-metadata',
8450c15c 1601 action='store_true', dest='addmetadata', default=False,
dac5df5a 1602 help=(
1603 'Embed metadata to the video file. Also embeds chapters/infojson if present '
1604 'unless --no-embed-chapters/--no-embed-info-json are used (Alias: --add-metadata)'))
6623ac34 1605 postproc.add_option(
7e067091 1606 '--no-embed-metadata', '--no-add-metadata',
6623ac34 1607 action='store_false', dest='addmetadata',
7a340e0d
NA
1608 help='Do not add metadata to file (default) (Alias: --no-add-metadata)')
1609 postproc.add_option(
1610 '--embed-chapters', '--add-chapters',
1611 action='store_true', dest='addchapters', default=None,
1612 help='Add chapter markers to the video file (Alias: --add-chapters)')
1613 postproc.add_option(
1614 '--no-embed-chapters', '--no-add-chapters',
1615 action='store_false', dest='addchapters',
1616 help='Do not add chapter markers (default) (Alias: --no-add-chapters)')
dac5df5a 1617 postproc.add_option(
1618 '--embed-info-json',
1619 action='store_true', dest='embed_infojson', default=None,
1620 help='Embed the infojson as an attachment to mkv/mka video files')
1621 postproc.add_option(
1622 '--no-embed-info-json',
1623 action='store_false', dest='embed_infojson',
1624 help='Do not embed the infojson as an attachment to the video file')
e7db87f7 1625 postproc.add_option(
1626 '--metadata-from-title',
1627 metavar='FORMAT', dest='metafromtitle',
5bfa4862 1628 help=optparse.SUPPRESS_HELP)
1629 postproc.add_option(
1630 '--parse-metadata',
fe74d5b5 1631 metavar='[WHEN:]FROM:TO', dest='parse_metadata', **when_prefix('pre_process'),
6623ac34 1632 help=(
fe74d5b5 1633 'Parse additional metadata like title/artist from other fields; see "MODIFYING METADATA" for details. '
1634 'Supported values of "WHEN" are the same as that of --use-postprocessor (default: pre_process)'))
e9f4ccd1 1635 postproc.add_option(
1636 '--replace-in-metadata',
fe74d5b5 1637 dest='parse_metadata', metavar='[WHEN:]FIELDS REGEX REPLACE', nargs=3, **when_prefix('pre_process'),
1638 help=(
1639 'Replace text in a metadata field using the given regex. This option can be used multiple times. '
1640 'Supported values of "WHEN" are the same as that of --use-postprocessor (default: pre_process)'))
8450c15c 1641 postproc.add_option(
6f7563be 1642 '--xattrs', '--xattr',
8450c15c 1643 action='store_true', dest='xattrs', default=False,
17941321 1644 help='Write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
3b603dbd 1645 postproc.add_option(
1646 '--concat-playlist',
1647 metavar='POLICY', dest='concat_playlist', default='multi_video',
1648 choices=('never', 'always', 'multi_video'),
1649 help=(
fc5fa964 1650 'Concatenate videos in a playlist. One of "never", "always", or '
1651 '"multi_video" (default; only when the videos form a single show). '
3b603dbd 1652 'All the video files must have same codecs and number of streams to be concatable. '
1653 'The "pl_video:" prefix can be used with "--paths" and "--output" to '
a44ca5a4 1654 'set the output filename for the concatenated files. See "OUTPUT TEMPLATE" for details'))
6271f1ca
PH
1655 postproc.add_option(
1656 '--fixup',
99594a11 1657 metavar='POLICY', dest='fixup', default=None,
f89b3e2d 1658 choices=('never', 'ignore', 'warn', 'detect_or_warn', 'force'),
6623ac34 1659 help=(
1660 'Automatically correct known faults of the file. '
1661 'One of never (do nothing), warn (only emit a warning), '
f89b3e2d 1662 'detect_or_warn (the default; fix file if we can, warn otherwise), '
f304da8a 1663 'force (try fixing even if file already exists)'))
8450c15c 1664 postproc.add_option(
6623ac34 1665 '--prefer-avconv', '--no-prefer-ffmpeg',
8450c15c 1666 action='store_false', dest='prefer_ffmpeg',
e4172ac9 1667 help=optparse.SUPPRESS_HELP)
8450c15c 1668 postproc.add_option(
6623ac34 1669 '--prefer-ffmpeg', '--no-prefer-avconv',
e4172ac9 1670 action='store_true', dest='prefer_ffmpeg', default=True,
1671 help=optparse.SUPPRESS_HELP)
73fac4e9
PH
1672 postproc.add_option(
1673 '--ffmpeg-location', '--avconv-location', metavar='PATH',
1674 dest='ffmpeg_location',
e4172ac9 1675 help='Location of the ffmpeg binary; either the path to the binary or its containing directory')
34a741a8 1676 postproc.add_option(
1e43a6f7 1677 '--exec',
119e40ef 1678 metavar='[WHEN:]CMD', dest='exec_cmd', **when_prefix('after_move'),
1679 help=(
1680 'Execute a command, optionally prefixed with when to execute it, separated by a ":". '
1681 'Supported values of "WHEN" are the same as that of --use-postprocessor (default: after_move). '
34488702 1682 'Same syntax as the output template can be used to pass any field as arguments to the command. '
ad54c913 1683 'If no fields are passed, %(filepath,_filename|)q is appended to the end of the command. '
c681cb5d 1684 'This option can be used multiple times'))
1685 postproc.add_option(
1686 '--no-exec',
1e43a6f7 1687 action='store_const', dest='exec_cmd', const={},
c681cb5d 1688 help='Remove any previously defined --exec')
1689 postproc.add_option(
1690 '--exec-before-download', metavar='CMD',
ad3dc496 1691 action='append', dest='exec_before_dl_cmd',
1e43a6f7 1692 help=optparse.SUPPRESS_HELP)
5520aa2d 1693 postproc.add_option(
c681cb5d 1694 '--no-exec-before-download',
a44ca5a4 1695 action='store_const', dest='exec_before_dl_cmd', const=None,
1e43a6f7 1696 help=optparse.SUPPRESS_HELP)
e9fade72 1697 postproc.add_option(
e167860c 1698 '--convert-subs', '--convert-sub', '--convert-subtitles',
e9fade72 1699 metavar='FORMAT', dest='convertsubtitles', default=None,
81a23040 1700 help=(
1701 'Convert the subtitles to another format (currently supported: %s) '
8dc59305 1702 '(Alias: --convert-subtitles)' % ', '.join(sorted(FFmpegSubtitlesConvertorPP.SUPPORTED_EXTS))))
8fa43c73 1703 postproc.add_option(
1704 '--convert-thumbnails',
1705 metavar='FORMAT', dest='convertthumbnails', default=None,
81a23040 1706 help=(
1707 'Convert the thumbnails to another format '
8dc59305 1708 f'(currently supported: {", ".join(sorted(FFmpegThumbnailsConvertorPP.SUPPORTED_EXTS))}). '
00bbc5f1 1709 'You can specify multiple rules using similar syntax as --remux-video'))
72755351 1710 postproc.add_option(
1711 '--split-chapters', '--split-tracks',
1712 dest='split_chapters', action='store_true', default=False,
1713 help=(
1714 'Split video into multiple files based on internal chapters. '
1715 'The "chapter:" prefix can be used with "--paths" and "--output" to '
1716 'set the output filename for the split files. See "OUTPUT TEMPLATE" for details'))
1717 postproc.add_option(
1718 '--no-split-chapters', '--no-split-tracks',
1719 dest='split_chapters', action='store_false',
1720 help='Do not split video based on chapters (default)')
7a340e0d
NA
1721 postproc.add_option(
1722 '--remove-chapters',
1723 metavar='REGEX', dest='remove_chapters', action='append',
2d9ec704 1724 help=(
1725 'Remove chapters whose title matches the given regular expression. '
5ec1b6b7 1726 'The syntax is the same as --download-sections. This option can be used multiple times'))
7a340e0d
NA
1727 postproc.add_option(
1728 '--no-remove-chapters', dest='remove_chapters', action='store_const', const=None,
1729 help='Do not remove any chapters from the file (default)')
1730 postproc.add_option(
1731 '--force-keyframes-at-cuts',
1732 action='store_true', dest='force_keyframes_at_cuts', default=False,
1733 help=(
5ec1b6b7 1734 'Force keyframes at cuts when downloading/splitting/removing sections. '
1735 'This is slow due to needing a re-encode, but the resulting video may have fewer artifacts around the cuts'))
7a340e0d
NA
1736 postproc.add_option(
1737 '--no-force-keyframes-at-cuts',
1738 action='store_false', dest='force_keyframes_at_cuts',
1739 help='Do not force keyframes around the chapters when cutting/splitting (default)')
3ae5e797 1740 _postprocessor_opts_parser = lambda key, val='': (
1741 *(item.split('=', 1) for item in (val.split(';') if val else [])),
1742 ('key', remove_end(key, 'PP')))
1743 postproc.add_option(
1744 '--use-postprocessor',
1745 metavar='NAME[:ARGS]', dest='add_postprocessors', default=[], type='str',
1746 action='callback', callback=_list_from_options_callback,
1747 callback_kwargs={
1748 'delim': None,
1749 'process': lambda val: dict(_postprocessor_opts_parser(*val.split(':', 1)))
1750 }, help=(
1751 'The (case sensitive) name of plugin postprocessors to be enabled, '
e75bb0d6 1752 'and (optionally) arguments to be passed to it, separated by a colon ":". '
3ae5e797 1753 'ARGS are a semicolon ";" delimited list of NAME=VALUE. '
1754 'The "when" argument determines when the postprocessor is invoked. '
09b49e1f 1755 'It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), '
119e40ef 1756 '"video" (after --format; before --print/--output), "before_dl" (before each video download), '
1757 '"post_process" (after each video download; default), '
09b49e1f 1758 '"after_move" (after moving video file to it\'s final locations), '
ebed8b37 1759 '"after_video" (after downloading and processing all formats of a video), '
09b49e1f 1760 'or "playlist" (at end of playlist). '
3ae5e797 1761 'This option can be used multiple times to add different postprocessors'))
34a741a8 1762
7a340e0d
NA
1763 sponsorblock = optparse.OptionGroup(parser, 'SponsorBlock Options', description=(
1764 'Make chapter entries for, or remove various segments (sponsor, introductions, etc.) '
1765 'from downloaded YouTube videos using the SponsorBlock API (https://sponsor.ajay.app)'))
1766 sponsorblock.add_option(
1767 '--sponsorblock-mark', metavar='CATS',
1768 dest='sponsorblock_mark', default=set(), action='callback', type='str',
8157a09d
NA
1769 callback=_set_from_options_callback, callback_kwargs={
1770 'allowed_values': SponsorBlockPP.CATEGORIES.keys(),
1771 'aliases': {'default': ['all']}
1772 }, help=(
7a340e0d 1773 'SponsorBlock categories to create chapters for, separated by commas. '
2dd5a2e3 1774 f'Available categories are {", ".join(SponsorBlockPP.CATEGORIES.keys())}, all and default (=all). '
1775 'You can prefix the category with a "-" to exclude it. See [1] for description of the categories. '
62b58c09 1776 'E.g. --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories'))
7a340e0d
NA
1777 sponsorblock.add_option(
1778 '--sponsorblock-remove', metavar='CATS',
1779 dest='sponsorblock_remove', default=set(), action='callback', type='str',
8157a09d 1780 callback=_set_from_options_callback, callback_kwargs={
63c547d7 1781 'allowed_values': set(SponsorBlockPP.CATEGORIES.keys()) - set(SponsorBlockPP.NON_SKIPPABLE_CATEGORIES.keys()),
8157a09d
NA
1782 # Note: From https://wiki.sponsor.ajay.app/w/Types:
1783 # The filler category is very aggressive.
1784 # It is strongly recommended to not use this in a client by default.
1785 'aliases': {'default': ['all', '-filler']}
1786 }, help=(
7a340e0d
NA
1787 'SponsorBlock categories to be removed from the video file, separated by commas. '
1788 'If a category is present in both mark and remove, remove takes precedence. '
8157a09d
NA
1789 'The syntax and available categories are the same as for --sponsorblock-mark '
1790 'except that "default" refers to "all,-filler" '
63c547d7 1791 f'and {", ".join(SponsorBlockPP.NON_SKIPPABLE_CATEGORIES.keys())} are not available'))
7a340e0d
NA
1792 sponsorblock.add_option(
1793 '--sponsorblock-chapter-title', metavar='TEMPLATE',
1794 default=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, dest='sponsorblock_chapter_title',
1795 help=(
2dd5a2e3 1796 'An output template for the title of the SponsorBlock chapters created by --sponsorblock-mark. '
1797 'The only available fields are start_time, end_time, category, categories, name, category_names. '
1798 'Defaults to "%default"'))
7a340e0d
NA
1799 sponsorblock.add_option(
1800 '--no-sponsorblock', default=False,
1801 action='store_true', dest='no_sponsorblock',
1802 help='Disable both --sponsorblock-mark and --sponsorblock-remove')
1803 sponsorblock.add_option(
1804 '--sponsorblock-api', metavar='URL',
1805 default='https://sponsor.ajay.app', dest='sponsorblock_api',
1806 help='SponsorBlock API location, defaults to %default')
1807
1808 sponsorblock.add_option(
a9e7f546 1809 '--sponskrub',
165efb82 1810 action='store_true', dest='sponskrub', default=False,
7a340e0d
NA
1811 help=optparse.SUPPRESS_HELP)
1812 sponsorblock.add_option(
a9e7f546 1813 '--no-sponskrub',
1814 action='store_false', dest='sponskrub',
7a340e0d
NA
1815 help=optparse.SUPPRESS_HELP)
1816 sponsorblock.add_option(
a9e7f546 1817 '--sponskrub-cut', default=False,
1818 action='store_true', dest='sponskrub_cut',
7a340e0d
NA
1819 help=optparse.SUPPRESS_HELP)
1820 sponsorblock.add_option(
6623ac34 1821 '--no-sponskrub-cut',
1822 action='store_false', dest='sponskrub_cut',
7a340e0d
NA
1823 help=optparse.SUPPRESS_HELP)
1824 sponsorblock.add_option(
a9e7f546 1825 '--sponskrub-force', default=False,
1826 action='store_true', dest='sponskrub_force',
7a340e0d
NA
1827 help=optparse.SUPPRESS_HELP)
1828 sponsorblock.add_option(
6623ac34 1829 '--no-sponskrub-force',
1830 action='store_true', dest='sponskrub_force',
7a340e0d
NA
1831 help=optparse.SUPPRESS_HELP)
1832 sponsorblock.add_option(
a9e7f546 1833 '--sponskrub-location', metavar='PATH',
1834 dest='sponskrub_path', default='',
7a340e0d
NA
1835 help=optparse.SUPPRESS_HELP)
1836 sponsorblock.add_option(
c76eb41b 1837 '--sponskrub-args', dest='sponskrub_args', metavar='ARGS',
1b77b347 1838 help=optparse.SUPPRESS_HELP)
a9e7f546 1839
78895bd3 1840 extractor = optparse.OptionGroup(parser, 'Extractor Options')
62bff2c1 1841 extractor.add_option(
1842 '--extractor-retries',
d6e51845 1843 dest='extractor_retries', metavar='RETRIES', default=3,
62bff2c1 1844 help='Number of retries for known extractor errors (default is %default), or "infinite"')
78895bd3 1845 extractor.add_option(
6623ac34 1846 '--allow-dynamic-mpd', '--no-ignore-dynamic-mpd',
78895bd3 1847 action='store_true', dest='dynamic_mpd', default=True,
8a51f564 1848 help='Process dynamic DASH manifests (default) (Alias: --no-ignore-dynamic-mpd)')
78895bd3 1849 extractor.add_option(
6623ac34 1850 '--ignore-dynamic-mpd', '--no-allow-dynamic-mpd',
78895bd3 1851 action='store_false', dest='dynamic_mpd',
8a51f564 1852 help='Do not process dynamic DASH manifests (Alias: --no-allow-dynamic-mpd)')
310c2ed2 1853 extractor.add_option(
1854 '--hls-split-discontinuity',
1855 dest='hls_split_discontinuity', action='store_true', default=False,
1856 help='Split HLS playlists to different formats at discontinuities such as ad breaks'
1857 )
1858 extractor.add_option(
1859 '--no-hls-split-discontinuity',
1860 dest='hls_split_discontinuity', action='store_false',
1861 help='Do not split HLS playlists to different formats at discontinuities such as ad breaks (default)')
042931a5 1862 _extractor_arg_parser = lambda key, vals='': (key.strip().lower().replace('-', '_'), [
1863 val.replace(r'\,', ',').strip() for val in re.split(r'(?<!\\),', vals)])
5d3a0e79 1864 extractor.add_option(
1865 '--extractor-args',
2fa669f7 1866 metavar='IE_KEY:ARGS', dest='extractor_args', default={}, type='str',
5d3a0e79 1867 action='callback', callback=_dict_from_options_callback,
1868 callback_kwargs={
1869 'multiple_keys': False,
1870 'process': lambda val: dict(
4bb6b02f 1871 _extractor_arg_parser(*arg.split('=', 1)) for arg in val.split(';'))
dbf5416a 1872 }, help=(
2fa669f7 1873 'Pass ARGS arguments to the IE_KEY extractor. See "EXTRACTOR ARGUMENTS" for details. '
4bb6b02f 1874 'You can use this option multiple times to give arguments for different extractors'))
e409895f 1875 extractor.add_option(
1876 '--youtube-include-dash-manifest', '--no-youtube-skip-dash-manifest',
1877 action='store_true', dest='youtube_include_dash_manifest', default=True,
5d3a0e79 1878 help=optparse.SUPPRESS_HELP)
e409895f 1879 extractor.add_option(
1880 '--youtube-skip-dash-manifest', '--no-youtube-include-dash-manifest',
1881 action='store_false', dest='youtube_include_dash_manifest',
5d3a0e79 1882 help=optparse.SUPPRESS_HELP)
e409895f 1883 extractor.add_option(
1884 '--youtube-include-hls-manifest', '--no-youtube-skip-hls-manifest',
1885 action='store_true', dest='youtube_include_hls_manifest', default=True,
5d3a0e79 1886 help=optparse.SUPPRESS_HELP)
e409895f 1887 extractor.add_option(
1888 '--youtube-skip-hls-manifest', '--no-youtube-include-hls-manifest',
1889 action='store_false', dest='youtube_include_hls_manifest',
5d3a0e79 1890 help=optparse.SUPPRESS_HELP)
78895bd3 1891
34a741a8 1892 parser.add_option_group(general)
be4a824d 1893 parser.add_option_group(network)
0aa10994 1894 parser.add_option_group(geo)
34a741a8
PH
1895 parser.add_option_group(selection)
1896 parser.add_option_group(downloader)
1897 parser.add_option_group(filesystem)
cfb56d1a 1898 parser.add_option_group(thumbnail)
732044af 1899 parser.add_option_group(link)
34a741a8
PH
1900 parser.add_option_group(verbosity)
1901 parser.add_option_group(workarounds)
1902 parser.add_option_group(video_format)
1903 parser.add_option_group(subtitles)
1904 parser.add_option_group(authentication)
1905 parser.add_option_group(postproc)
7a340e0d 1906 parser.add_option_group(sponsorblock)
78895bd3 1907 parser.add_option_group(extractor)
34a741a8 1908
06e57990 1909 return parser
7303f84a 1910
e66dca5e 1911
06e57990 1912def _hide_login_info(opts):
da4db748 1913 deprecation_warning(f'"{__name__}._hide_login_info" is deprecated and may be removed '
1914 'in a future version. Use "yt_dlp.utils.Config.hide_login_info" instead')
06e57990 1915 return Config.hide_login_info(opts)