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