import re
import sys
-from .downloader.external import list_external_downloaders
from .compat import (
compat_expanduser,
compat_get_terminal_size,
get_executable_path,
OUTTMPL_TYPES,
preferredencoding,
- REMUX_EXTENSIONS,
write_string,
)
from .version import __version__
+from .downloader.external import list_external_downloaders
+from .postprocessor.ffmpeg import (
+ FFmpegExtractAudioPP,
+ FFmpegSubtitlesConvertorPP,
+ FFmpegThumbnailsConvertorPP,
+ FFmpegVideoRemuxerPP,
+)
+
def _hide_login_info(opts):
PRIVATE_OPTS = set(['-p', '--password', '-u', '--username', '--video-password', '--ap-password', '--ap-username'])
return ''.join(opts)
- def _comma_separated_values_options_callback(option, opt_str, value, parser):
- setattr(parser.values, option.dest, value.split(','))
+ def _list_from_options_callback(option, opt_str, value, parser, append=True, delim=','):
+ # append can be True, False or -1 (prepend)
+ current = getattr(parser.values, option.dest) if append else []
+ value = [value] if delim is None else value.split(delim)
+ setattr(
+ parser.values, option.dest,
+ current + value if append is True else value + current)
- def _dict_from_multiple_values_options_callback(
- option, opt_str, value, parser, allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None):
+ def _dict_from_options_callback(
+ 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',
help='Mark videos watched (YouTube only)')
general.add_option(
'--no-mark-watched',
- action='store_false', dest='mark_watched', default=False,
- help='Do not mark videos watched')
+ action='store_false', dest='mark_watched',
+ help='Do not mark videos watched (default)')
general.add_option(
'--no-colors',
- action='store_true', dest='no_color',
- default=False,
+ 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=_list_from_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')
help='Video format code, see "FORMAT SELECTION" for more details')
video_format.add_option(
'-S', '--format-sort', metavar='SORTORDER',
- dest='format_sort', default=[],
- action='callback', callback=_comma_separated_values_options_callback, type='str',
+ dest='format_sort', default=[], type='str', action='callback',
+ callback=_list_from_options_callback, callback_kwargs={'append': -1},
help='Sort the formats by the fields given, see "Sorting Formats" for more details')
video_format.add_option(
'--format-sort-force', '--S-force',
'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(
'--write-auto-subs', '--write-automatic-subs',
action='store_true', dest='writeautomaticsub', default=False,
- help='Write automatically generated subtitle file (YouTube only)')
+ help='Write automatically generated subtitle file (Alias: --write-automatic-subs)')
subtitles.add_option(
'--no-write-auto-subs', '--no-write-automatic-subs',
action='store_false', dest='writeautomaticsub', default=False,
- help='Do not write automatically generated subtitle file (default)')
+ help='Do not write auto-generated subtitles (default) (Alias: --no-write-automatic-subs)')
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,
action='store', dest='subtitlesformat', metavar='FORMAT', default='best',
help='Subtitle format, accepts formats preference, for example: "srt" or "ass/srt/best"')
subtitles.add_option(
- '--sub-lang', '--sub-langs', '--srt-lang',
+ '--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')
+ default=[], callback=_list_from_options_callback,
+ 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',
help='Maximum download rate in bytes per second (e.g. 50K or 4.2M)')
+ downloader.add_option(
+ '--throttled-rate',
+ dest='throttledratelimit', metavar='RATE',
+ help='Minimum download rate in bytes per second below which throttling is assumed and the video data is re-extracted (e.g. 100K)')
downloader.add_option(
'-R', '--retries',
dest='retries', metavar='RETRIES', default=10,
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_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,
+ action='callback', callback=_dict_from_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 ":". '
- 'You can use this option multiple times (Alias: --external-downloader-args)'))
+ 'You can use this option multiple times to give different arguments to different downloaders '
+ '(Alias: --external-downloader-args)'))
workarounds = optparse.OptionGroup(parser, 'Workarounds')
workarounds.add_option(
workarounds.add_option(
'--prefer-insecure', '--prefer-unsecure',
action='store_true', dest='prefer_insecure',
- help='Use an unencrypted connection to retrieve information about the video. (Currently supported only for YouTube)')
+ help='Use an unencrypted connection to retrieve information about the video (Currently supported only for YouTube)')
workarounds.add_option(
'--user-agent',
metavar='UA', dest='user_agent',
workarounds.add_option(
'--add-header',
metavar='FIELD:VALUE', dest='headers', default={}, type='str',
- action='callback', callback=_dict_from_multiple_values_options_callback,
+ action='callback', callback=_dict_from_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(
'--sleep-interval', '--min-sleep-interval', metavar='SECONDS',
dest='sleep_interval', type=float,
help=(
- 'Number of seconds to sleep before each download when used alone '
- 'or a lower bound of a range for randomized sleep before each download '
- '(minimum possible number of seconds to sleep) when used along with '
- '--max-sleep-interval'))
+ 'Number of seconds to sleep before each download. '
+ 'This is the minimum time to sleep when used along with --max-sleep-interval '
+ '(Alias: --min-sleep-interval)'))
workarounds.add_option(
'--max-sleep-interval', metavar='SECONDS',
dest='max_sleep_interval', type=float,
- help=(
- 'Upper bound of a range for randomized sleep before each download '
- '(maximum possible number of seconds to sleep). Must only be used '
- 'along with --min-sleep-interval'))
+ help='Maximum number of seconds to sleep. Can only be used along with --min-sleep-interval')
workarounds.add_option(
'--sleep-subtitles', metavar='SECONDS',
dest='sleep_interval_subtitles', default=0, type=int,
'-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,
- help='Do not download the video')
+ help='Do not download the video but write all related files (Alias: --no-download)')
+ verbosity.add_option(
+ '-O', '--print', metavar='TEMPLATE',
+ action='callback', dest='forceprint', type='str', default=[],
+ callback=_list_from_options_callback, callback_kwargs={'delim': None},
+ help=(
+ 'Simulate, quiet but print the given fields. Either a field name '
+ 'or similar formatting as the output template can be used'))
verbosity.add_option(
'-g', '--get-url',
action='store_true', dest='geturl', default=False,
- help='Simulate, quiet but print URL')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'-e', '--get-title',
action='store_true', dest='gettitle', default=False,
- help='Simulate, quiet but print title')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-id',
action='store_true', dest='getid', default=False,
- help='Simulate, quiet but print id')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-thumbnail',
action='store_true', dest='getthumbnail', default=False,
- help='Simulate, quiet but print thumbnail URL')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-description',
action='store_true', dest='getdescription', default=False,
- help='Simulate, quiet but print video description')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-duration',
action='store_true', dest='getduration', default=False,
- help='Simulate, quiet but print video length')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-filename',
action='store_true', dest='getfilename', default=False,
- help='Simulate, quiet but print output filename')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'--get-format',
action='store_true', dest='getformat', default=False,
- help='Simulate, quiet but print output format')
+ help=optparse.SUPPRESS_HELP)
verbosity.add_option(
'-j', '--dump-json',
action='store_true', dest='dumpjson', 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',
- 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()},
+ metavar='TYPES:PATH', dest='paths', default={}, type='str',
+ action='callback', callback=_dict_from_options_callback,
+ 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',
- action='callback', callback=_dict_from_multiple_values_options_callback,
+ metavar='[TYPES:]TEMPLATE', dest='outtmpl', default={}, type='str',
+ action='callback', callback=_dict_from_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)'))
filesystem.add_option(
'--no-write-playlist-metafiles',
action='store_false', dest='allow_playlist_files',
+ help='Do not write playlist metadata when using --write-info-json, --write-description etc.')
+ filesystem.add_option(
+ '--clean-infojson',
+ action='store_true', dest='clean_infojson', default=True,
help=(
- 'Do not write playlist metadata when using '
- '--write-info-json, --write-description etc.'))
+ 'Remove some private fields such as filenames from the infojson. '
+ 'Note that it could still contain some personal information (default)'))
+ filesystem.add_option(
+ '--no-clean-infojson',
+ action='store_false', dest='clean_infojson',
+ help='Write all fields to the infojson')
filesystem.add_option(
- '--get-comments',
+ '--write-comments', '--get-comments',
action='store_true', dest='getcomments', default=False,
help=(
- 'Retrieve video comments to be placed in the .info.json file. '
- 'The comments are fetched even without this option if the extraction is known to be quick'))
+ 'Retrieve video comments to be placed in the infojson. '
+ 'The comments are fetched even without this option if the extraction is known to be quick (Alias: --get-comments)'))
+ filesystem.add_option(
+ '--no-write-comments', '--no-get-comments',
+ action='store_true', dest='getcomments', default=False,
+ help='Do not retrieve video comments unless the extraction is known to be quick (Alias: --no-get-comments)')
filesystem.add_option(
'--load-info-json', '--load-info',
dest='load_info_filename', metavar='FILE',
help='Do not read/dump cookies (default)')
filesystem.add_option(
'--cache-dir', dest='cachedir', default=None, metavar='DIR',
- help='Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl . At the moment, only YouTube player files (for videos with obfuscated signatures) are cached, but that may change')
+ 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/youtube-dl or ~/.cache/youtube-dl')
filesystem.add_option(
'--no-cache-dir', action='store_false', dest='cachedir',
help='Disable filesystem caching')
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,
help='Convert video files to audio-only files (requires ffmpeg and ffprobe)')
postproc.add_option(
'--audio-format', metavar='FORMAT', dest='audioformat', default='best',
- help='Specify audio format: "best", "aac", "flac", "mp3", "m4a", "opus", "vorbis", or "wav"; "%default" by default; No effect without -x')
+ help=(
+ 'Specify audio format to convert the audio to when -x is used. Currently supported formats are: '
+ 'best (default) or one of %s' % '|'.join(FFmpegExtractAudioPP.SUPPORTED_EXTS)))
postproc.add_option(
'--audio-quality', metavar='QUALITY',
dest='audioquality', default='5',
help=(
'Remux the video into another container if necessary (currently supported: %s). '
'If target container does not support the video/audio codec, remuxing will fail. '
- 'You can specify multiple rules; eg. "aac>m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 '
- 'and anything else to mkv.' % '|'.join(REMUX_EXTENSIONS)))
+ 'You can specify multiple rules; Eg. "aac>m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 '
+ 'and anything else to mkv.' % '|'.join(FFmpegVideoRemuxerPP.SUPPORTED_EXTS)))
postproc.add_option(
'--recode-video',
metavar='FORMAT', dest='recodevideo', default=None,
help=(
'Re-encode the video into another format if re-encoding is necessary. '
- 'The supported formats are the same as --remux-video'))
+ 'The syntax and supported formats are the same as --remux-video'))
postproc.add_option(
'--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},
+ action='callback', callback=_dict_from_options_callback,
+ 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 and EmbedThumbnail. '
- '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, FixupM3u8, FixupTimestamp and FixupDuration. '
+ '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, '
- 'a number can be appended to the exe name seperated by "_i" to pass the argument '
- 'before the specified input file. Eg: --ppa "Merger+ffmpeg_i1:-v quiet". '
+ '"_i"/"_o" can be appended to the prefix optionally followed by a number to pass the argument '
+ 'before the specified input/output file. Eg: --ppa "Merger+ffmpeg_i1:-v quiet". '
'You can use this option multiple times to give different arguments to different '
'postprocessors. (Alias: --ppa)'))
postproc.add_option(
postproc.add_option(
'--embed-thumbnail',
action='store_true', dest='embedthumbnail', default=False,
- help='Embed thumbnail in the audio as cover art')
+ help='Embed thumbnail in the video as cover art')
postproc.add_option(
'--no-embed-thumbnail',
action='store_false', dest='embedthumbnail',
help='Do not embed thumbnail (default)')
postproc.add_option(
- '--add-metadata',
+ '--embed-metadata', '--add-metadata',
action='store_true', dest='addmetadata', default=False,
- help='Write metadata to the video file')
+ help='Embed metadata including chapter markers (if supported by the format) to the video file (Alias: --add-metadata)')
postproc.add_option(
- '--no-add-metadata',
+ '--no-embed-metadata', '--no-add-metadata',
action='store_false', dest='addmetadata',
- help='Do not write metadata (default)')
+ help='Do not write metadata (default) (Alias: --no-add-metadata)')
postproc.add_option(
'--metadata-from-title',
metavar='FORMAT', dest='metafromtitle',
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(
'--fixup',
metavar='POLICY', dest='fixup', default=None,
+ choices=('never', 'ignore', 'warn', 'detect_or_warn', 'force'),
help=(
'Automatically correct known faults of the file. '
'One of never (do nothing), warn (only emit a warning), '
- 'detect_or_warn (the default; fix file if we can, warn otherwise)'))
+ 'detect_or_warn (the default; fix file if we can, warn otherwise), '
+ 'force (try fixing even if file already exists'))
postproc.add_option(
'--prefer-avconv', '--no-prefer-ffmpeg',
action='store_false', dest='prefer_ffmpeg',
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-subtitles',
+ '--convert-subs', '--convert-sub', '--convert-subtitles',
metavar='FORMAT', dest='convertsubtitles', default=None,
- help='Convert the subtitles to other format (currently supported: srt|ass|vtt|lrc)')
+ help=(
+ 'Convert the subtitles to another format (currently supported: %s) '
+ '(Alias: --convert-subtitles)' % '|'.join(FFmpegSubtitlesConvertorPP.SUPPORTED_EXTS)))
+ postproc.add_option(
+ '--convert-thumbnails',
+ metavar='FORMAT', dest='convertthumbnails', default=None,
+ help=(
+ 'Convert the thumbnails to another format '
+ '(currently supported: %s) ' % '|'.join(FFmpegThumbnailsConvertorPP.SUPPORTED_EXTS)))
postproc.add_option(
'--split-chapters', '--split-tracks',
dest='split_chapters', action='store_true', default=False,
'--no-hls-split-discontinuity',
dest='hls_split_discontinuity', action='store_false',
help='Do not split HLS playlists to different formats at discontinuities such as ad breaks (default)')
+ extractor.add_option(
+ '--extractor-args',
+ metavar='KEY:ARGS', dest='extractor_args', default={}, type='str',
+ action='callback', callback=_dict_from_options_callback,
+ callback_kwargs={
+ 'multiple_keys': False,
+ 'process': lambda val: dict(
+ (lambda x: (x[0], x[1].split(',')))(arg.split('=', 1) + ['', '']) for arg in val.split(';'))
+ },
+ help=(
+ 'Pass these arguments to the extractor. See "EXTRACTOR ARGUMENTS" for details. '
+ 'You can use this option multiple times to give different arguments to different extractors'))
extractor.add_option(
'--youtube-include-dash-manifest', '--no-youtube-skip-dash-manifest',
action='store_true', dest='youtube_include_dash_manifest', default=True,
- help='Download the DASH manifests and related data on YouTube videos (default) (Alias: --no-youtube-skip-dash-manifest)')
+ help=optparse.SUPPRESS_HELP)
extractor.add_option(
'--youtube-skip-dash-manifest', '--no-youtube-include-dash-manifest',
action='store_false', dest='youtube_include_dash_manifest',
- help='Do not download the DASH manifests and related data on YouTube videos (Alias: --no-youtube-include-dash-manifest)')
+ help=optparse.SUPPRESS_HELP)
extractor.add_option(
'--youtube-include-hls-manifest', '--no-youtube-skip-hls-manifest',
action='store_true', dest='youtube_include_hls_manifest', default=True,
- help='Download the HLS manifests and related data on YouTube videos (default) (Alias: --no-youtube-skip-hls-manifest)')
+ help=optparse.SUPPRESS_HELP)
extractor.add_option(
'--youtube-skip-hls-manifest', '--no-youtube-include-hls-manifest',
action='store_false', dest='youtube_include_hls_manifest',
- help='Do not download the HLS manifests and related data on YouTube videos (Alias: --no-youtube-include-hls-manifest)')
+ help=optparse.SUPPRESS_HELP)
parser.add_option_group(general)
parser.add_option_group(network)
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)