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