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