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