return ''.join(opts)
- def _comma_separated_values_options_callback(option, opt_str, value, parser):
- setattr(parser.values, option.dest, value.split(','))
+ def _comma_separated_values_options_callback(option, opt_str, value, parser, prepend=True):
+ setattr(
+ parser.values, option.dest,
+ value.split(',') if not prepend
+ else value.split(',') + getattr(parser.values, option.dest))
def _dict_from_multiple_values_options_callback(
- option, opt_str, value, parser, allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None):
+ option, opt_str, value, parser,
+ allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None, multiple_keys=True):
out_dict = getattr(parser.values, option.dest)
- mobj = re.match(r'(?i)(?P<key>%s)%s(?P<val>.*)$' % (allowed_keys, delimiter), value)
+ if multiple_keys:
+ allowed_keys = r'(%s)(,(%s))*' % (allowed_keys, allowed_keys)
+ mobj = re.match(r'(?i)(?P<keys>%s)%s(?P<val>.*)$' % (allowed_keys, delimiter), value)
if mobj is not None:
- key, val = mobj.group('key').lower(), mobj.group('val')
+ keys = [k.strip() for k in mobj.group('keys').lower().split(',')]
+ val = mobj.group('val')
elif default_key is not None:
- key, val = default_key, value
+ keys, val = [default_key], value
else:
raise optparse.OptionValueError(
'wrong %s formatting; it should be %s, not "%s"' % (opt_str, option.metavar, value))
- out_dict[key] = process(val) if callable(process) else val
+ val = process(val) if callable(process) else val
+ for key in keys:
+ out_dict[key] = val
# No need to wrap help messages if we're on a wide console
columns = compat_get_terminal_size().columns
help='Update this program to latest version. Make sure that you have sufficient permissions (run with sudo if needed)')
general.add_option(
'-i', '--ignore-errors', '--no-abort-on-error',
- action='store_true', dest='ignoreerrors', default=True,
+ action='store_true', dest='ignoreerrors', default=None,
help='Continue on download errors, for example to skip unavailable videos in a playlist (default) (Alias: --no-abort-on-error)')
general.add_option(
'--abort-on-error', '--no-ignore-errors',
'--no-colors',
action='store_true', dest='no_color', default=False,
help='Do not emit color codes in output')
+ general.add_option(
+ '--compat-options',
+ metavar='OPTS', dest='compat_opts', default=[],
+ action='callback', callback=_comma_separated_values_options_callback, type='str',
+ help=(
+ 'Options that can help keep compatibility with youtube-dl and youtube-dlc '
+ 'configurations by reverting some of the changes made in yt-dlp. '
+ 'See "Differences in default behavior" for details'))
network = optparse.OptionGroup(parser, 'Network Options')
network.add_option(
help='Make all connections via IPv6',
)
- geo = optparse.OptionGroup(parser, 'Geo Restriction')
+ geo = optparse.OptionGroup(parser, 'Geo-restriction')
geo.add_option(
'--geo-verification-proxy',
dest='geo_verification_proxy', default=None, metavar='URL',
'--break-on-reject',
action='store_true', dest='break_on_reject', default=False,
help='Stop the download process when encountering a file that has been filtered out')
+ selection.add_option(
+ '--skip-playlist-after-errors', metavar='N',
+ dest='skip_playlist_after_errors', default=None, type=int,
+ help='Number of allowed failures until the rest of the playlist is skipped')
selection.add_option(
'--no-download-archive',
dest='download_archive', action="store_const", const=None,
selection.add_option(
'--include-ads',
dest='include_ads', action='store_true',
- help='Download advertisements as well (experimental)')
+ help=optparse.SUPPRESS_HELP)
selection.add_option(
'--no-include-ads',
dest='include_ads', action='store_false',
- help='Do not download advertisements (default)')
+ help=optparse.SUPPRESS_HELP)
authentication = optparse.OptionGroup(parser, 'Authentication Options')
authentication.add_option(
'--video-password',
dest='videopassword', metavar='PASSWORD',
help='Video password (vimeo, youku)')
-
- adobe_pass = optparse.OptionGroup(parser, 'Adobe Pass Options')
- adobe_pass.add_option(
+ authentication.add_option(
'--ap-mso',
dest='ap_mso', metavar='MSO',
help='Adobe Pass multiple-system operator (TV provider) identifier, use --ap-list-mso for a list of available MSOs')
- adobe_pass.add_option(
+ authentication.add_option(
'--ap-username',
dest='ap_username', metavar='USERNAME',
help='Multiple-system operator account login')
- adobe_pass.add_option(
+ authentication.add_option(
'--ap-password',
dest='ap_password', metavar='PASSWORD',
help='Multiple-system operator account password. If this option is left out, yt-dlp will ask interactively')
- adobe_pass.add_option(
+ authentication.add_option(
'--ap-list-mso',
action='store_true', dest='ap_list_mso', default=False,
help='List all supported multiple-system operators')
'see "Sorting Formats" for more details'))
video_format.add_option(
'--video-multistreams',
- action='store_true', dest='allow_multiple_video_streams', default=False,
+ action='store_true', dest='allow_multiple_video_streams', default=None,
help='Allow multiple video streams to be merged into a single file')
video_format.add_option(
'--no-video-multistreams',
help='Only one video stream is downloaded for each output file (default)')
video_format.add_option(
'--audio-multistreams',
- action='store_true', dest='allow_multiple_audio_streams', default=False,
+ action='store_true', dest='allow_multiple_audio_streams', default=None,
help='Allow multiple audio streams to be merged into a single file')
video_format.add_option(
'--no-audio-multistreams',
video_format.add_option(
'--all-formats',
action='store_const', dest='format', const='all',
- help='Download all available video formats')
+ help=optparse.SUPPRESS_HELP)
video_format.add_option(
'--prefer-free-formats',
action='store_true', dest='prefer_free_formats', default=False,
'--no-prefer-free-formats',
action='store_true', dest='prefer_free_formats', default=False,
help="Don't give any special preference to free containers (default)")
+ video_format.add_option(
+ '--check-formats',
+ action='store_true', dest='check_formats', default=False,
+ help="Check that the formats selected are actually downloadable (Experimental)")
video_format.add_option(
'-F', '--list-formats',
action='store_true', dest='listformats',
video_format.add_option(
'--list-formats-as-table',
action='store_true', dest='listformats_table', default=True,
- help='Present the output of -F in tabular form (default)')
+ help=optparse.SUPPRESS_HELP)
video_format.add_option(
'--list-formats-old', '--no-list-formats-as-table',
action='store_false', dest='listformats_table',
- help='Present the output of -F in the old form (Alias: --no-list-formats-as-table)')
+ help=optparse.SUPPRESS_HELP)
video_format.add_option(
'--merge-output-format',
action='store', dest='merge_output_format', metavar='FORMAT', default=None,
action='store_true', dest='allow_unplayable_formats', default=False,
help=(
'Allow unplayable formats to be listed and downloaded. '
- 'All video postprocessing will also be turned off'))
+ 'All video post-processing will also be turned off'))
video_format.add_option(
'--no-allow-unplayable-formats',
action='store_false', dest='allow_unplayable_formats',
subtitles.add_option(
'--all-subs',
action='store_true', dest='allsubtitles', default=False,
- help='Download all the available subtitles of the video')
+ help=optparse.SUPPRESS_HELP)
subtitles.add_option(
'--list-subs',
action='store_true', dest='listsubtitles', default=False,
'--sub-langs', '--srt-langs',
action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
default=[], callback=_comma_separated_values_options_callback,
- help='Languages of the subtitles to download (optional) separated by commas, use --list-subs for available language tags')
+ help=(
+ 'Languages of the subtitles to download (can be regex) or "all" separated by commas. (Eg: --sub-langs en.*,ja) '
+ 'You can prefix the language code with a "-" to exempt it from the requested languages. (Eg: --sub-langs all,-live_chat) '
+ 'Use --list-subs for a list of available language tags'))
downloader = optparse.OptionGroup(parser, 'Download Options')
downloader.add_option(
'-N', '--concurrent-fragments',
dest='concurrent_fragment_downloads', metavar='N', default=1, type=int,
- help='Number of fragments to download concurrently (default is %default)')
+ help='Number of fragments of a dash/hlsnative video that should be download concurrently (default is %default)')
downloader.add_option(
'-r', '--limit-rate', '--rate-limit',
dest='ratelimit', metavar='RATE',
downloader.add_option(
'--hls-prefer-native',
dest='hls_prefer_native', action='store_true', default=None,
- help='Use the native HLS downloader instead of ffmpeg')
+ help=optparse.SUPPRESS_HELP)
downloader.add_option(
'--hls-prefer-ffmpeg',
dest='hls_prefer_native', action='store_false', default=None,
- help='Use ffmpeg instead of the native HLS downloader')
+ help=optparse.SUPPRESS_HELP)
downloader.add_option(
'--hls-use-mpegts',
dest='hls_use_mpegts', action='store_true', default=None,
'Do not use the mpegts container for HLS videos. '
'This is default when not downloading live streams'))
downloader.add_option(
- '--external-downloader',
- dest='external_downloader', metavar='NAME',
+ '--downloader', '--external-downloader',
+ dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str',
+ action='callback', callback=_dict_from_multiple_values_options_callback,
+ callback_kwargs={
+ 'allowed_keys': 'http|ftp|m3u8|dash|rtsp|rtmp|mms',
+ 'default_key': 'default',
+ 'process': lambda x: x.strip()
+ },
help=(
- 'Name or path of the external downloader to use. '
- 'Currently supports %s (Recommended: aria2c)' % ', '.join(list_external_downloaders())))
+ 'Name or path of the external downloader to use (optionally) prefixed by '
+ 'the protocols (http, ftp, m3u8, dash, rstp, rtmp, mms) to use it for. '
+ 'Currently supports native, %s (Recommended: aria2c). '
+ 'You can use this option multiple times to set different downloaders for different protocols. '
+ 'For example, --downloader aria2c --downloader "dash,m3u8:native" will use '
+ 'aria2c for http/ftp downloads, and the native downloader for dash/m3u8 downloads '
+ '(Alias: --external-downloader)' % ', '.join(list_external_downloaders())))
downloader.add_option(
'--downloader-args', '--external-downloader-args',
metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str',
action='callback', callback=_dict_from_multiple_values_options_callback,
callback_kwargs={
'allowed_keys': '|'.join(list_external_downloaders()),
- 'default_key': 'default', 'process': compat_shlex_split},
+ 'default_key': 'default',
+ 'process': compat_shlex_split
+ },
help=(
'Give these arguments to the external downloader. '
'Specify the downloader name and the arguments separated by a colon ":". '
'--add-header',
metavar='FIELD:VALUE', dest='headers', default={}, type='str',
action='callback', callback=_dict_from_multiple_values_options_callback,
+ callback_kwargs={'multiple_keys': False},
help='Specify a custom HTTP header and its value, separated by a colon ":". You can use this option multiple times',
)
workarounds.add_option(
'-s', '--simulate',
action='store_true', dest='simulate', default=False,
help='Do not download the video and do not write anything to disk')
+ verbosity.add_option(
+ '--ignore-no-formats-error',
+ action='store_true', dest='ignore_no_formats_error', default=False,
+ help=(
+ 'Ignore "No video formats" error. Usefull for extracting metadata '
+ 'even if the video is not actually available for download (experimental)'))
+ verbosity.add_option(
+ '--no-ignore-no-formats-error',
+ action='store_false', dest='ignore_no_formats_error',
+ help='Throw error when no downloadable video formats are found (default)')
verbosity.add_option(
'--skip-download', '--no-download',
action='store_true', dest='skip_download', default=False,
'--force-write-archive', '--force-write-download-archive', '--force-download-archive',
action='store_true', dest='force_write_download_archive', default=False,
help=(
- 'Force download archive entries to be written as far as no errors occur,'
- 'even if -s or another simulation switch is used (Alias: --force-download-archive)'))
+ 'Force download archive entries to be written as far as no errors occur, '
+ 'even if -s or another simulation option is used (Alias: --force-download-archive)'))
verbosity.add_option(
'--newline',
action='store_true', dest='progress_with_newline', default=False,
action='store_true', dest='useid', help=optparse.SUPPRESS_HELP)
filesystem.add_option(
'-P', '--paths',
- metavar='TYPE:PATH', dest='paths', default={}, type='str',
+ metavar='TYPES:PATH', dest='paths', default={}, type='str',
action='callback', callback=_dict_from_multiple_values_options_callback,
- callback_kwargs={
- 'allowed_keys': 'home|temp|%s' % '|'.join(OUTTMPL_TYPES.keys()),
- 'process': lambda x: x.strip()},
+ callback_kwargs={'allowed_keys': 'home|temp|%s' % '|'.join(OUTTMPL_TYPES.keys())},
help=(
'The paths where the files should be downloaded. '
'Specify the type of file and the path separated by a colon ":". '
'This option is ignored if --output is an absolute path'))
filesystem.add_option(
'-o', '--output',
- metavar='[TYPE:]TEMPLATE', dest='outtmpl', default={}, type='str',
+ metavar='[TYPES:]TEMPLATE', dest='outtmpl', default={}, type='str',
action='callback', callback=_dict_from_multiple_values_options_callback,
callback_kwargs={
'allowed_keys': '|'.join(OUTTMPL_TYPES.keys()),
- 'default_key': 'default', 'process': lambda x: x.strip()},
- help='Output filename template, see "OUTPUT TEMPLATE" for details')
+ 'default_key': 'default'
+ },
+ help='Output filename template; see "OUTPUT TEMPLATE" for details')
filesystem.add_option(
'--output-na-placeholder',
dest='outtmpl_na_placeholder', metavar='TEXT', default='NA',
filesystem.add_option(
'--autonumber-start',
dest='autonumber_start', metavar='NUMBER', default=1, type=int,
- help='Specify the start value for %(autonumber)s (default is %default)')
+ help=optparse.SUPPRESS_HELP)
filesystem.add_option(
'--restrict-filenames',
action='store_true', dest='restrictfilenames', default=False,
dest='trim_file_name', default=0, type=int,
help='Limit the filename length (excluding extension) to the specified number of characters')
filesystem.add_option(
- '-A', '--auto-number',
+ '--auto-number',
action='store_true', dest='autonumber', default=False,
help=optparse.SUPPRESS_HELP)
filesystem.add_option(
- '-t', '--title',
+ '--title',
action='store_true', dest='usetitle', default=False,
help=optparse.SUPPRESS_HELP)
filesystem.add_option(
- '-l', '--literal', default=False,
+ '--literal', default=False,
action='store_true', dest='usetitle',
help=optparse.SUPPRESS_HELP)
filesystem.add_option(
action='store_false', dest='continue_dl',
help=(
'Do not resume partially downloaded fragments. '
- 'If the file is unfragmented, restart download of the entire file'))
+ 'If the file is not fragmented, restart download of the entire file'))
filesystem.add_option(
'--part',
action='store_false', dest='nopart', default=False,
help='Do not write video annotations (default)')
filesystem.add_option(
'--write-playlist-metafiles',
- action='store_true', dest='allow_playlist_files', default=True,
+ action='store_true', dest='allow_playlist_files', default=None,
help=(
'Write playlist metadata in addition to the video metadata '
'when using --write-info-json, --write-description etc. (default)'))
action='store_true', dest='rm_cachedir',
help='Delete all filesystem cache files')
- thumbnail = optparse.OptionGroup(parser, 'Thumbnail Images')
+ thumbnail = optparse.OptionGroup(parser, 'Thumbnail Options')
thumbnail.add_option(
'--write-thumbnail',
action='store_true', dest='writethumbnail', default=False,
'--postprocessor-args', '--ppa',
metavar='NAME:ARGS', dest='postprocessor_args', default={}, type='str',
action='callback', callback=_dict_from_multiple_values_options_callback,
- callback_kwargs={'default_key': 'default-compat', 'allowed_keys': r'\w+(?:\+\w+)?', 'process': compat_shlex_split},
+ callback_kwargs={
+ 'allowed_keys': r'\w+(?:\+\w+)?', 'default_key': 'default-compat',
+ 'process': compat_shlex_split,
+ 'multiple_keys': False
+ },
help=(
'Give these arguments to the postprocessors. '
'Specify the postprocessor/executable name and the arguments separated by a colon ":" '
- 'to give the argument to the specified postprocessor/executable. Supported postprocessors are: '
- 'SponSkrub, ExtractAudio, VideoRemuxer, VideoConvertor, EmbedSubtitle, Metadata, Merger, '
- 'FixupStretched, FixupM4a, FixupM3u8, SubtitlesConvertor, EmbedThumbnail and SplitChapters. '
- 'The supported executables are: SponSkrub, FFmpeg, FFprobe, and AtomicParsley. '
+ 'to give the argument to the specified postprocessor/executable. Supported PP are: '
+ 'Merger, ExtractAudio, SplitChapters, Metadata, EmbedSubtitle, EmbedThumbnail, '
+ 'SubtitlesConvertor, ThumbnailsConvertor, VideoRemuxer, VideoConvertor, '
+ 'SponSkrub, FixupStretched, FixupM4a and FixupM3u8. '
+ 'The supported executables are: AtomicParsley, FFmpeg, FFprobe, and SponSkrub. '
'You can also specify "PP+EXE:ARGS" to give the arguments to the specified executable '
'only when being used by the specified postprocessor. Additionally, for ffmpeg/ffprobe, '
'"_i"/"_o" can be appended to the prefix optionally followed by a number to pass the argument '
help=optparse.SUPPRESS_HELP)
postproc.add_option(
'--parse-metadata',
- metavar='FIELD:FORMAT', dest='metafromfield', action='append',
+ metavar='FROM:TO', dest='metafromfield', action='append',
help=(
- 'Parse additional metadata like title/artist from other fields. '
- 'Give field name to extract data from, and format of the field seperated by a ":". '
- 'Either regular expression with named capture groups or a '
- 'similar syntax to the output template can also be used. '
- 'The parsed parameters replace any existing values and can be use in output template. '
- 'This option can be used multiple times. '
- 'Example: --parse-metadata "title:%(artist)s - %(title)s" matches a title like '
- '"Coldplay - Paradise". '
- 'Example (regex): --parse-metadata "description:Artist - (?P<artist>.+?)"'))
+ 'Parse additional metadata like title/artist from other fields; '
+ 'see "MODIFYING METADATA" for details'))
postproc.add_option(
'--xattrs',
action='store_true', dest='xattrs', default=False,
postproc.add_option(
'--exec',
metavar='CMD', dest='exec_cmd',
- help='Execute a command on the file after downloading and post-processing, similar to find\'s -exec syntax. Example: --exec \'adb push {} /sdcard/Music/ && rm {}\'')
+ help=(
+ 'Execute a command on the file after downloading and post-processing. '
+ 'Similar syntax to the output template can be used to pass any field as arguments to the command. '
+ 'An additional field "filepath" that contains the final path of the downloaded file is also available. '
+ 'If no fields are passed, "%(filepath)s" is appended to the end of the command'))
postproc.add_option(
'--convert-subs', '--convert-sub', '--convert-subtitles',
metavar='FORMAT', dest='convertsubtitles', default=None,
help='Convert the subtitles to another format (currently supported: srt|ass|vtt|lrc) (Alias: --convert-subtitles)')
+ postproc.add_option(
+ '--convert-thumbnails',
+ metavar='FORMAT', dest='convertthumbnails', default=None,
+ help='Convert the thumbnails to another format (currently supported: jpg)')
postproc.add_option(
'--split-chapters', '--split-tracks',
dest='split_chapters', action='store_true', default=False,
parser.add_option_group(video_format)
parser.add_option_group(subtitles)
parser.add_option_group(authentication)
- parser.add_option_group(adobe_pass)
parser.add_option_group(postproc)
parser.add_option_group(sponskrub)
parser.add_option_group(extractor)