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