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