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