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