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