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