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