From 7a5c1cfe93924351387b44919b3c0b2f66c4b883 Mon Sep 17 00:00:00 2001 From: Pccode66 <49125134+Pccode66@users.noreply.github.com> Date: Wed, 24 Feb 2021 15:45:56 -0300 Subject: Completely change project name to yt-dlp (#85) * All modules and binary names are changed * All documentation references changed * yt-dlp no longer loads youtube-dlc config files * All URLs changed to point to organization account Co-authored-by: Pccode66 Co-authored-by: pukkandan --- yt_dlp/options.py | 1338 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1338 insertions(+) create mode 100644 yt_dlp/options.py (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py new file mode 100644 index 000000000..00bc02c2d --- /dev/null +++ b/yt_dlp/options.py @@ -0,0 +1,1338 @@ +from __future__ import unicode_literals + +import os.path +import optparse +import re +import sys + +from .downloader.external import list_external_downloaders +from .compat import ( + compat_expanduser, + compat_get_terminal_size, + compat_getenv, + compat_kwargs, + compat_shlex_split, +) +from .utils import ( + expand_path, + get_executable_path, + OUTTMPL_TYPES, + preferredencoding, + REMUX_EXTENSIONS, + write_string, +) +from .version import __version__ + + +def _hide_login_info(opts): + PRIVATE_OPTS = set(['-p', '--password', '-u', '--username', '--video-password', '--ap-password', '--ap-username']) + eqre = re.compile('^(?P' + ('|'.join(re.escape(po) for po in PRIVATE_OPTS)) + ')=.+$') + + def _scrub_eq(o): + m = eqre.match(o) + if m: + return m.group('key') + '=PRIVATE' + else: + return o + + opts = list(map(_scrub_eq, opts)) + for idx, opt in enumerate(opts): + if opt in PRIVATE_OPTS and idx + 1 < len(opts): + opts[idx + 1] = 'PRIVATE' + return opts + + +def parseOpts(overrideArguments=None): + def _readOptions(filename_bytes, default=[]): + try: + optionf = open(filename_bytes) + except IOError: + return default # silently skip if file is not present + try: + # FIXME: https://github.com/ytdl-org/youtube-dl/commit/dfe5fa49aed02cf36ba9f743b11b0903554b5e56 + contents = optionf.read() + if sys.version_info < (3,): + contents = contents.decode(preferredencoding()) + res = compat_shlex_split(contents, comments=True) + finally: + optionf.close() + return res + + def _readUserConf(package_name, default=[]): + # .config + xdg_config_home = compat_getenv('XDG_CONFIG_HOME') or compat_expanduser('~/.config') + userConfFile = os.path.join(xdg_config_home, package_name, 'config') + if not os.path.isfile(userConfFile): + userConfFile = os.path.join(xdg_config_home, '%s.conf' % package_name) + userConf = _readOptions(userConfFile, default=None) + if userConf is not None: + return userConf, userConfFile + + # appdata + appdata_dir = compat_getenv('appdata') + if appdata_dir: + userConfFile = os.path.join(appdata_dir, package_name, 'config') + userConf = _readOptions(userConfFile, default=None) + if userConf is None: + userConfFile += '.txt' + userConf = _readOptions(userConfFile, default=None) + if userConf is not None: + return userConf, userConfFile + + # home + userConfFile = os.path.join(compat_expanduser('~'), '%s.conf' % package_name) + userConf = _readOptions(userConfFile, default=None) + if userConf is None: + userConfFile += '.txt' + userConf = _readOptions(userConfFile, default=None) + if userConf is not None: + return userConf, userConfFile + + return default, None + + def _format_option_string(option): + ''' ('-o', '--option') -> -o, --format METAVAR''' + + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, ', ') + + if option.takes_value(): + opts.append(' %s' % option.metavar) + + return ''.join(opts) + + def _comma_separated_values_options_callback(option, opt_str, value, parser): + setattr(parser.values, option.dest, value.split(',')) + + def _dict_from_multiple_values_options_callback( + option, opt_str, value, parser, allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None): + + out_dict = getattr(parser.values, option.dest) + mobj = re.match(r'(?i)(?P%s)%s(?P.*)$' % (allowed_keys, delimiter), value) + if mobj is not None: + key, val = mobj.group('key').lower(), mobj.group('val') + elif default_key is not None: + key, 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 + + # No need to wrap help messages if we're on a wide console + columns = compat_get_terminal_size().columns + max_width = columns if columns else 80 + max_help_position = 80 + + fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position) + fmt.format_option_strings = _format_option_string + + kw = { + 'version': __version__, + 'formatter': fmt, + 'usage': '%prog [OPTIONS] URL [URL...]', + 'conflict_handler': 'resolve', + } + + parser = optparse.OptionParser(**compat_kwargs(kw)) + + general = optparse.OptionGroup(parser, 'General Options') + general.add_option( + '-h', '--help', + action='help', + help='Print this help text and exit') + general.add_option( + '--version', + action='version', + help='Print program version and exit') + general.add_option( + '-U', '--update', + action='store_true', dest='update_self', + 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, + 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', + action='store_false', dest='ignoreerrors', + help='Abort downloading of further videos if an error occurs (Alias: --no-ignore-errors)') + general.add_option( + '--dump-user-agent', + action='store_true', dest='dump_user_agent', default=False, + help='Display the current browser identification') + general.add_option( + '--list-extractors', + action='store_true', dest='list_extractors', default=False, + help='List all supported extractors') + general.add_option( + '--extractor-descriptions', + action='store_true', dest='list_extractor_descriptions', default=False, + help='Output descriptions of all supported extractors') + general.add_option( + '--force-generic-extractor', + action='store_true', dest='force_generic_extractor', default=False, + help='Force extraction to use the generic extractor') + general.add_option( + '--default-search', + dest='default_search', metavar='PREFIX', + help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let youtube-dl guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching') + general.add_option( + '--ignore-config', '--no-config', + action='store_true', + help=( + 'Disable loading any configuration files except the one provided by --config-location. ' + 'When given inside a configuration file, no further configuration files are loaded. ' + 'Additionally, (for backward compatibility) if this option is found inside the ' + 'system configuration file, the user configuration is not loaded')) + general.add_option( + '--config-location', + dest='config_location', metavar='PATH', + help='Location of the main configuration file; either the path to the config or its containing directory') + general.add_option( + '--flat-playlist', + action='store_const', dest='extract_flat', const='in_playlist', default=False, + help='Do not extract the videos of a playlist, only list them') + general.add_option( + '--flat-videos', + action='store_true', dest='extract_flat', + # help='Do not resolve the video urls') + # doesn't work + help=optparse.SUPPRESS_HELP) + general.add_option( + '--no-flat-playlist', + action='store_false', dest='extract_flat', + help='Extract the videos of a playlist') + general.add_option( + '--mark-watched', + action='store_true', dest='mark_watched', default=False, + 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') + general.add_option( + '--no-colors', + action='store_true', dest='no_color', + default=False, + help='Do not emit color codes in output') + + network = optparse.OptionGroup(parser, 'Network Options') + network.add_option( + '--proxy', dest='proxy', + default=None, metavar='URL', + help=( + 'Use the specified HTTP/HTTPS/SOCKS proxy. To enable ' + 'SOCKS proxy, specify a proper scheme. For example ' + 'socks5://127.0.0.1:1080/. Pass in an empty string (--proxy "") ' + 'for direct connection')) + network.add_option( + '--socket-timeout', + dest='socket_timeout', type=float, default=None, metavar='SECONDS', + help='Time to wait before giving up, in seconds') + network.add_option( + '--source-address', + metavar='IP', dest='source_address', default=None, + help='Client-side IP address to bind to', + ) + network.add_option( + '-4', '--force-ipv4', + action='store_const', const='0.0.0.0', dest='source_address', + help='Make all connections via IPv4', + ) + network.add_option( + '-6', '--force-ipv6', + action='store_const', const='::', dest='source_address', + help='Make all connections via IPv6', + ) + + geo = optparse.OptionGroup(parser, 'Geo Restriction') + geo.add_option( + '--geo-verification-proxy', + dest='geo_verification_proxy', default=None, metavar='URL', + help=( + 'Use this proxy to verify the IP address for some geo-restricted sites. ' + 'The default proxy specified by --proxy (or none, if the option is not present) is used for the actual downloading')) + geo.add_option( + '--cn-verification-proxy', + dest='cn_verification_proxy', default=None, metavar='URL', + help=optparse.SUPPRESS_HELP) + geo.add_option( + '--geo-bypass', + action='store_true', dest='geo_bypass', default=True, + help='Bypass geographic restriction via faking X-Forwarded-For HTTP header') + geo.add_option( + '--no-geo-bypass', + action='store_false', dest='geo_bypass', default=True, + help='Do not bypass geographic restriction via faking X-Forwarded-For HTTP header') + geo.add_option( + '--geo-bypass-country', metavar='CODE', + dest='geo_bypass_country', default=None, + help='Force bypass geographic restriction with explicitly provided two-letter ISO 3166-2 country code') + geo.add_option( + '--geo-bypass-ip-block', metavar='IP_BLOCK', + dest='geo_bypass_ip_block', default=None, + help='Force bypass geographic restriction with explicitly provided IP block in CIDR notation') + + selection = optparse.OptionGroup(parser, 'Video Selection') + selection.add_option( + '--playlist-start', + dest='playliststart', metavar='NUMBER', default=1, type=int, + help='Playlist video to start at (default is %default)') + selection.add_option( + '--playlist-end', + dest='playlistend', metavar='NUMBER', default=None, type=int, + help='Playlist video to end at (default is last)') + selection.add_option( + '--playlist-items', + dest='playlist_items', metavar='ITEM_SPEC', default=None, + help='Playlist video items to download. Specify indices of the videos in the playlist separated by commas like: "--playlist-items 1,2,5,8" if you want to download videos indexed 1, 2, 5, 8 in the playlist. You can specify range: "--playlist-items 1-3,7,10-13", it will download the videos at index 1, 2, 3, 7, 10, 11, 12 and 13') + selection.add_option( + '--match-title', + dest='matchtitle', metavar='REGEX', + help='Download only matching titles (regex or caseless sub-string)') + selection.add_option( + '--reject-title', + dest='rejecttitle', metavar='REGEX', + help='Skip download for matching titles (regex or caseless sub-string)') + selection.add_option( + '--max-downloads', + dest='max_downloads', metavar='NUMBER', type=int, default=None, + help='Abort after downloading NUMBER files') + selection.add_option( + '--min-filesize', + metavar='SIZE', dest='min_filesize', default=None, + help='Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)') + selection.add_option( + '--max-filesize', + metavar='SIZE', dest='max_filesize', default=None, + help='Do not download any videos larger than SIZE (e.g. 50k or 44.6m)') + selection.add_option( + '--date', + metavar='DATE', dest='date', default=None, + help=( + 'Download only videos uploaded in this date. ' + 'The date can be "YYYYMMDD" or in the format ' + '"(now|today)[+-][0-9](day|week|month|year)(s)?"')) + selection.add_option( + '--datebefore', + metavar='DATE', dest='datebefore', default=None, + help=( + 'Download only videos uploaded on or before this date. ' + 'The date formats accepted is the same as --date')) + selection.add_option( + '--dateafter', + metavar='DATE', dest='dateafter', default=None, + help=( + 'Download only videos uploaded on or after this date. ' + 'The date formats accepted is the same as --date')) + selection.add_option( + '--min-views', + metavar='COUNT', dest='min_views', default=None, type=int, + help='Do not download any videos with less than COUNT views') + selection.add_option( + '--max-views', + metavar='COUNT', dest='max_views', default=None, type=int, + help='Do not download any videos with more than COUNT views') + selection.add_option( + '--match-filter', + metavar='FILTER', dest='match_filter', default=None, + help=( + 'Generic video filter. ' + 'Specify any key (see "OUTPUT TEMPLATE" for a list of available keys) to ' + 'match if the key is present, ' + '!key to check if the key is not present, ' + 'key>NUMBER (like "comment_count > 12", also works with ' + '>=, <, <=, !=, =) to compare against a number, ' + 'key = \'LITERAL\' (like "uploader = \'Mike Smith\'", also works with !=) ' + 'to match against a string literal ' + 'and & to require multiple matches. ' + 'Values which are not known are excluded unless you ' + 'put a question mark (?) after the operator. ' + 'For example, to only match videos that have been liked more than ' + '100 times and disliked less than 50 times (or the dislike ' + 'functionality is not available at the given service), but who ' + 'also have a description, use --match-filter ' + '"like_count > 100 & dislike_count m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 ' + 'and anything else to mkv.' % '|'.join(REMUX_EXTENSIONS))) + 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')) + 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}, + 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. ' + '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". ' + 'You can use this option multiple times to give different arguments to different ' + 'postprocessors. (Alias: --ppa)')) + postproc.add_option( + '-k', '--keep-video', + action='store_true', dest='keepvideo', default=False, + help='Keep the intermediate video file on disk after post-processing') + postproc.add_option( + '--no-keep-video', + action='store_false', dest='keepvideo', + help='Delete the intermediate video file after post-processing (default)') + postproc.add_option( + '--post-overwrites', + action='store_false', dest='nopostoverwrites', + help='Overwrite post-processed files (default)') + postproc.add_option( + '--no-post-overwrites', + action='store_true', dest='nopostoverwrites', default=False, + help='Do not overwrite post-processed files') + postproc.add_option( + '--embed-subs', + action='store_true', dest='embedsubtitles', default=False, + help='Embed subtitles in the video (only for mp4, webm and mkv videos)') + postproc.add_option( + '--no-embed-subs', + action='store_false', dest='embedsubtitles', + help='Do not embed subtitles (default)') + postproc.add_option( + '--embed-thumbnail', + action='store_true', dest='embedthumbnail', default=False, + help='Embed thumbnail in the audio 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', + action='store_true', dest='addmetadata', default=False, + help='Write metadata to the video file') + postproc.add_option( + '--no-add-metadata', + action='store_false', dest='addmetadata', + help='Do not write metadata (default)') + 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', + 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.+?)"')) + postproc.add_option( + '--xattrs', + action='store_true', dest='xattrs', default=False, + help='Write metadata to the video file\'s xattrs (using dublin core and xdg standards)') + postproc.add_option( + '--fixup', + metavar='POLICY', dest='fixup', default='detect_or_warn', + 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)')) + postproc.add_option( + '--prefer-avconv', '--no-prefer-ffmpeg', + action='store_false', dest='prefer_ffmpeg', + help=optparse.SUPPRESS_HELP) + postproc.add_option( + '--prefer-ffmpeg', '--no-prefer-avconv', + action='store_true', dest='prefer_ffmpeg', default=True, + help=optparse.SUPPRESS_HELP) + postproc.add_option( + '--ffmpeg-location', '--avconv-location', metavar='PATH', + dest='ffmpeg_location', + help='Location of the ffmpeg binary; either the path to the binary or its containing directory') + 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 {}\'') + postproc.add_option( + '--convert-subs', '--convert-subtitles', + metavar='FORMAT', dest='convertsubtitles', default=None, + help='Convert the subtitles to other format (currently supported: srt|ass|vtt|lrc)') + + sponskrub = optparse.OptionGroup(parser, 'SponSkrub (SponsorBlock) Options', description=( + 'SponSkrub (https://github.com/yt-dlp/SponSkrub) is a utility to mark/remove sponsor segments ' + 'from downloaded YouTube videos using SponsorBlock API (https://sponsor.ajay.app)')) + sponskrub.add_option( + '--sponskrub', + action='store_true', dest='sponskrub', default=None, + help=( + 'Use sponskrub to mark sponsored sections. ' + 'This is enabled by default if the sponskrub binary exists (Youtube only)')) + sponskrub.add_option( + '--no-sponskrub', + action='store_false', dest='sponskrub', + help='Do not use sponskrub') + sponskrub.add_option( + '--sponskrub-cut', default=False, + action='store_true', dest='sponskrub_cut', + help='Cut out the sponsor sections instead of simply marking them') + sponskrub.add_option( + '--no-sponskrub-cut', + action='store_false', dest='sponskrub_cut', + help='Simply mark the sponsor sections, not cut them out (default)') + sponskrub.add_option( + '--sponskrub-force', default=False, + action='store_true', dest='sponskrub_force', + help='Run sponskrub even if the video was already downloaded') + sponskrub.add_option( + '--no-sponskrub-force', + action='store_true', dest='sponskrub_force', + help='Do not cut out the sponsor sections if the video was already downloaded (default)') + sponskrub.add_option( + '--sponskrub-location', metavar='PATH', + dest='sponskrub_path', default='', + help='Location of the sponskrub binary; either the path to the binary or its containing directory') + sponskrub.add_option( + '--sponskrub-args', dest='sponskrub_args', metavar='ARGS', + help=optparse.SUPPRESS_HELP) + + extractor = optparse.OptionGroup(parser, 'Extractor Options') + extractor.add_option( + '--allow-dynamic-mpd', '--no-ignore-dynamic-mpd', + action='store_true', dest='dynamic_mpd', default=True, + help='Process dynamic DASH manifests (default) (Alias: --no-ignore-dynamic-mpd)') + extractor.add_option( + '--ignore-dynamic-mpd', '--no-allow-dynamic-mpd', + action='store_false', dest='dynamic_mpd', + help='Do not process dynamic DASH manifests (Alias: --no-allow-dynamic-mpd)') + extractor.add_option( + '--hls-split-discontinuity', + dest='hls_split_discontinuity', action='store_true', default=False, + help='Split HLS playlists to different formats at discontinuities such as ad breaks' + ) + extractor.add_option( + '--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( + '--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)') + 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)') + 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)') + 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)') + + parser.add_option_group(general) + parser.add_option_group(network) + parser.add_option_group(geo) + parser.add_option_group(selection) + parser.add_option_group(downloader) + parser.add_option_group(filesystem) + parser.add_option_group(thumbnail) + parser.add_option_group(link) + parser.add_option_group(verbosity) + parser.add_option_group(workarounds) + 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) + + if overrideArguments is not None: + opts, args = parser.parse_args(overrideArguments) + if opts.verbose: + write_string('[debug] Override config: ' + repr(overrideArguments) + '\n') + else: + def compat_conf(conf): + if sys.version_info < (3,): + return [a.decode(preferredencoding(), 'replace') for a in conf] + return conf + + configs = { + 'command-line': compat_conf(sys.argv[1:]), + 'custom': [], 'home': [], 'portable': [], 'user': [], 'system': []} + paths = {'command-line': False} + opts, args = parser.parse_args(configs['command-line']) + + def get_configs(): + if '--config-location' in configs['command-line']: + location = compat_expanduser(opts.config_location) + if os.path.isdir(location): + location = os.path.join(location, 'yt-dlp.conf') + if not os.path.exists(location): + parser.error('config-location %s does not exist.' % location) + configs['custom'] = _readOptions(location, default=None) + if configs['custom'] is None: + configs['custom'] = [] + else: + paths['custom'] = location + if '--ignore-config' in configs['command-line']: + return + if '--ignore-config' in configs['custom']: + return + + def read_options(path, user=False): + # Multiple package names can be given here + # Eg: ('yt-dlp', 'youtube-dlc', 'youtube-dl') will look for + # the configuration file of any of these three packages + for package in ('yt-dlp',): + if user: + config, current_path = _readUserConf(package, default=None) + else: + current_path = os.path.join(path, '%s.conf' % package) + config = _readOptions(current_path, default=None) + if config is not None: + return config, current_path + return [], None + + configs['portable'], paths['portable'] = read_options(get_executable_path()) + if '--ignore-config' in configs['portable']: + return + + def get_home_path(): + opts = parser.parse_args(configs['portable'] + configs['custom'] + configs['command-line'])[0] + return expand_path(opts.paths.get('home', '')).strip() + + configs['home'], paths['home'] = read_options(get_home_path()) + if '--ignore-config' in configs['home']: + return + + configs['system'], paths['system'] = read_options('/etc') + if '--ignore-config' in configs['system']: + return + + configs['user'], paths['user'] = read_options('', True) + if '--ignore-config' in configs['user']: + configs['system'], paths['system'] = [], None + + get_configs() + argv = configs['system'] + configs['user'] + configs['home'] + configs['portable'] + configs['custom'] + configs['command-line'] + opts, args = parser.parse_args(argv) + if opts.verbose: + for label in ('System', 'User', 'Portable', 'Home', 'Custom', 'Command-line'): + key = label.lower() + if paths.get(key) is None: + continue + if paths[key]: + write_string('[debug] %s config file: %s\n' % (label, paths[key])) + write_string('[debug] %s config: %s\n' % (label, repr(_hide_login_info(configs[key])))) + + return parser, opts, args -- cgit v1.2.3 From 0744a815b734dcc80eeb93b1392ae6d06500f214 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 25 Feb 2021 01:16:57 +0530 Subject: [documentation] Changes left behind from #85 and #107 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 00bc02c2d..c47f6ea50 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -708,7 +708,7 @@ def parseOpts(overrideArguments=None): dest='sleep_interval_subtitles', default=0, type=int, help='Enforce sleep interval on subtitles as well') - verbosity = optparse.OptionGroup(parser, 'Verbosity / Simulation Options') + verbosity = optparse.OptionGroup(parser, 'Verbosity and Simulation Options') verbosity.add_option( '-q', '--quiet', action='store_true', dest='quiet', default=False, -- cgit v1.2.3 From 9bd2020476c325df351c8e706d4b55894f916089 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 26 Feb 2021 21:51:31 +0530 Subject: [hls] Enable `--hls-use-mpegts` by default when downloading live-streams * Also added option `--no-hls-use-mpegts` to disable this Related: #96 --- yt_dlp/options.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c47f6ea50..88f74ff36 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -634,10 +634,18 @@ def parseOpts(overrideArguments=None): help='Use ffmpeg instead of the native HLS downloader') downloader.add_option( '--hls-use-mpegts', - dest='hls_use_mpegts', action='store_true', + dest='hls_use_mpegts', action='store_true', default=None, help=( - 'Use the mpegts container for HLS videos, allowing to play the ' - 'video while downloading (some players may not be able to play it)')) + 'Use the mpegts container for HLS videos; ' + 'allowing some players to play the video while downloading, ' + 'and reducing the chance of file corruption if download is interrupted. ' + 'This is enabled by default for live streams')) + downloader.add_option( + '--no-hls-use-mpegts', + dest='hls_use_mpegts', action='store_false', + help=( + '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', -- cgit v1.2.3 From 7f7de7f94dfeacb0eb78cb9487dfcaf5707da381 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 27 Feb 2021 16:52:27 +0530 Subject: Allow specifying path in `--external-downloader` --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 88f74ff36..5f200fb8f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -650,8 +650,8 @@ def parseOpts(overrideArguments=None): '--external-downloader', dest='external_downloader', metavar='NAME', help=( - 'Use the specified external downloader. ' - 'Currently supports %s' % ', '.join(list_external_downloaders()))) + 'Name or path of the external downloader to use. ' + 'Currently supports %s (Recommended: aria2c)' % ', '.join(list_external_downloaders()))) downloader.add_option( '--downloader-args', '--external-downloader-args', metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str', -- cgit v1.2.3 From 1cf376f55a3d9335eb161c07c439ca143d86924e Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 27 Feb 2021 18:11:23 +0530 Subject: Add option `--sleep-requests` to sleep b/w requests (Closes #106) * Also fix documentation of `sleep_interval_subtitles` Related issues: https://github.com/blackjack4494/yt-dlc/issues/158 https://github.com/blackjack4494/youtube-dlc/issues/195 https://github.com/ytdl-org/youtube-dl/pull/28270 https://github.com/ytdl-org/youtube-dl/pull/28144 https://github.com/ytdl-org/youtube-dl/issues/27767 https://github.com/ytdl-org/youtube-dl/issues/23638 https://github.com/ytdl-org/youtube-dl/issues/26287 https://github.com/ytdl-org/youtube-dl/issues/26319 --- yt_dlp/options.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 5f200fb8f..ae11e6b8b 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -696,6 +696,10 @@ def parseOpts(overrideArguments=None): '--bidi-workaround', dest='bidi_workaround', action='store_true', help='Work around terminals that lack bidirectional text support. Requires bidiv or fribidi executable in PATH') + workarounds.add_option( + '--sleep-requests', metavar='SECONDS', + dest='sleep_interval_requests', type=float, + help='Number of seconds to sleep between requests during data extraction') workarounds.add_option( '--sleep-interval', '--min-sleep-interval', metavar='SECONDS', dest='sleep_interval', type=float, @@ -714,7 +718,7 @@ def parseOpts(overrideArguments=None): workarounds.add_option( '--sleep-subtitles', metavar='SECONDS', dest='sleep_interval_subtitles', default=0, type=int, - help='Enforce sleep interval on subtitles as well') + help='Number of seconds to sleep before each subtitle download') verbosity = optparse.OptionGroup(parser, 'Verbosity and Simulation Options') verbosity.add_option( -- cgit v1.2.3 From 277d6ff5f2bd4f142429def30d01df264eb7c922 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 28 Feb 2021 20:26:08 +0530 Subject: Extract comments only when needed #95 (Closes #94) --- yt_dlp/options.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index ae11e6b8b..269499022 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -347,7 +347,7 @@ def parseOpts(overrideArguments=None): 'Specify any key (see "OUTPUT TEMPLATE" for a list of available keys) to ' 'match if the key is present, ' '!key to check if the key is not present, ' - 'key>NUMBER (like "comment_count > 12", also works with ' + 'key>NUMBER (like "view_count > 12", also works with ' '>=, <, <=, !=, =) to compare against a number, ' 'key = \'LITERAL\' (like "uploader = \'Mike Smith\'", also works with !=) ' 'to match against a string literal ' @@ -985,7 +985,9 @@ def parseOpts(overrideArguments=None): filesystem.add_option( '--get-comments', action='store_true', dest='getcomments', default=False, - help='Retrieve video comments to be placed in the .info.json file') + 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')) filesystem.add_option( '--load-info-json', '--load-info', dest='load_info_filename', metavar='FILE', -- cgit v1.2.3 From f0884c8b3f171f8794a011fd1cb5d53d1185efab Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 28 Feb 2021 20:55:32 +0530 Subject: Cleanup some code (see desc) * `--get-comments` doesn't imply `--write-info-json` if `-J`, `-j` or `--print-json` are used * Don't pass `config_location` to `YoutubeDL` (it is unused) * [bilibiliaudio] Recognize the file as audio-only * Update gitignore * Fix typos --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 269499022..59c08fb18 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -369,7 +369,7 @@ def parseOpts(overrideArguments=None): help='Download only the video, if the URL refers to a video and a playlist') selection.add_option( '--yes-playlist', - action='store_false', dest='noplaylist', default=False, + action='store_false', dest='noplaylist', help='Download the playlist, if the URL refers to a video and a playlist') selection.add_option( '--age-limit', @@ -1143,7 +1143,7 @@ def parseOpts(overrideArguments=None): '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' + '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". ' -- cgit v1.2.3 From 62bff2c170a8f12d937d62a2ca74586c5e0eff1f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 1 Mar 2021 05:18:37 +0530 Subject: Add option `--extractor-retries` to retry on known extractor errors * Currently only used by youtube Fixes https://github.com/ytdl-org/youtube-dl/issues/28194 Possibly also fixes: https://github.com/ytdl-org/youtube-dl/issues/28289 (can not confirm since the issue isn't reliably reproducible) --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 59c08fb18..866c50cb9 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1218,6 +1218,10 @@ def parseOpts(overrideArguments=None): help=optparse.SUPPRESS_HELP) extractor = optparse.OptionGroup(parser, 'Extractor Options') + extractor.add_option( + '--extractor-retries', + dest='extractor_retries', metavar='RETRIES', default=10, + help='Number of retries for known extractor errors (default is %default), or "infinite"') extractor.add_option( '--allow-dynamic-mpd', '--no-ignore-dynamic-mpd', action='store_true', dest='dynamic_mpd', default=True, -- cgit v1.2.3 From d6e51845b7beb0a94ee4e5e780e22ec4649dc672 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Wed, 3 Mar 2021 03:03:04 +0530 Subject: Reduce default of `--extractor-retries` to 3 so that even those not using sleep won't get 429'd on youtube --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 866c50cb9..2d7961f0f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1220,7 +1220,7 @@ def parseOpts(overrideArguments=None): extractor = optparse.OptionGroup(parser, 'Extractor Options') extractor.add_option( '--extractor-retries', - dest='extractor_retries', metavar='RETRIES', default=10, + dest='extractor_retries', metavar='RETRIES', default=3, help='Number of retries for known extractor errors (default is %default), or "infinite"') extractor.add_option( '--allow-dynamic-mpd', '--no-ignore-dynamic-mpd', -- cgit v1.2.3 From 99594a11ce6eba9bb7d8f6455a368040b86f5ffa Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 7 Mar 2021 12:32:59 +0530 Subject: Remove "fixup is ignored" warning when fixup wasn't passed by user Closes #151 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 2d7961f0f..adef0e0a8 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1154,7 +1154,7 @@ def parseOpts(overrideArguments=None): help='Write metadata to the video file\'s xattrs (using dublin core and xdg standards)') postproc.add_option( '--fixup', - metavar='POLICY', dest='fixup', default='detect_or_warn', + metavar='POLICY', dest='fixup', default=None, help=( 'Automatically correct known faults of the file. ' 'One of never (do nothing), warn (only emit a warning), ' -- cgit v1.2.3 From 4cf1e5d2f9a145de9749e90a1d244350c82ef610 Mon Sep 17 00:00:00 2001 From: shirt <2660574+shirt-dev@users.noreply.github.com> Date: Fri, 12 Mar 2021 23:46:58 -0500 Subject: Native concurrent downloading of fragments (#166) * Option `--concurrent-fragments` (`-N`) to set the number of threads Related: #165 Known issues: * When receiving Ctrl+C, the process will exit only after finishing the currently downloading fragments * The download progress shows the speed of only one thread Authored by shirt-dev --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index adef0e0a8..1e995b490 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -558,6 +558,10 @@ def parseOpts(overrideArguments=None): help='Languages of the subtitles to download (optional) separated by commas, use --list-subs for 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)') downloader.add_option( '-r', '--limit-rate', '--rate-limit', dest='ratelimit', metavar='RATE', -- cgit v1.2.3 From 7275535116d6b10c1e6df54c50ee872635f3c37e Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 15 Mar 2021 04:32:13 +0530 Subject: Split video by chapters (#158) * New options `--split-chapters` and `--no-split-chapters` * The output/path of the split files can be given using the key `chapter` * Additional keys `section_title`, `section_number`, `section_start`, `section_end` are available in the output template * Alias `--split-tracks` for parity with animelover/youtube-dl * `--sponskrub-cut` and `--split-chapter` cannot work together Closes: https://github.com/blackjack4494/yt-dlc/issues/277 https://github.com/ytdl-org/youtube-dl/issues/28438 https://github.com/ytdl-org/youtube-dl/issues/12907 https://github.com/ytdl-org/youtube-dl/issues/6480 https://github.com/ytdl-org/youtube-dl/pull/25005 Rewritten from the implementation by: femaref and Wattux https://github.com/Wattux/youtube-dl/tree/split-at-timestamps https://github.com/ytdl-org/youtube-dl/pull/25005 https://github.com/femaref/youtube-dl/tree/split-track --- yt_dlp/options.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 1e995b490..99b7db184 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1183,6 +1183,17 @@ def parseOpts(overrideArguments=None): '--convert-subs', '--convert-subtitles', metavar='FORMAT', dest='convertsubtitles', default=None, help='Convert the subtitles to other format (currently supported: srt|ass|vtt|lrc)') + postproc.add_option( + '--split-chapters', '--split-tracks', + dest='split_chapters', action='store_true', default=False, + help=( + 'Split video into multiple files based on internal chapters. ' + 'The "chapter:" prefix can be used with "--paths" and "--output" to ' + 'set the output filename for the split files. See "OUTPUT TEMPLATE" for details')) + postproc.add_option( + '--no-split-chapters', '--no-split-tracks', + dest='split_chapters', action='store_false', + help='Do not split video based on chapters (default)') sponskrub = optparse.OptionGroup(parser, 'SponSkrub (SponsorBlock) Options', description=( 'SponSkrub (https://github.com/yt-dlp/SponSkrub) is a utility to mark/remove sponsor segments ' -- cgit v1.2.3 From 597c18665e352f5ed482f2cf1de4226f5a0eeb88 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 15 Mar 2021 05:30:18 +0530 Subject: Release 2021.03.15 --- yt_dlp/options.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 99b7db184..e7bf9d564 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -214,12 +214,11 @@ def parseOpts(overrideArguments=None): 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') network = optparse.OptionGroup(parser, 'Network Options') @@ -1091,8 +1090,8 @@ def parseOpts(overrideArguments=None): 'The supported executables are: SponSkrub, FFmpeg, FFprobe, and AtomicParsley. ' '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( -- cgit v1.2.3 From 75d43ca08004e711fb37694f7208af35615118d5 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 18 Mar 2021 20:57:20 +0530 Subject: Option to keep private keys in the infojson Options: --clean-infojson, --no-clean-infojson Related: https://github.com/yt-dlp/yt-dlp/issues/42#issuecomment-800778391 --- yt_dlp/options.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index e7bf9d564..5c1908bfe 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -985,6 +985,16 @@ def parseOpts(overrideArguments=None): 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=( + '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', action='store_true', dest='getcomments', default=False, -- cgit v1.2.3 From e167860ce71bae6e46b77b47d5958c9c26d5543f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 18 Mar 2021 21:04:09 +0530 Subject: [documentation] Add deprecated options and aliases in readme --- yt_dlp/options.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 5c1908bfe..28bbd27d7 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -533,11 +533,11 @@ def parseOpts(overrideArguments=None): 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, @@ -551,7 +551,7 @@ def parseOpts(overrideArguments=None): 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') @@ -679,7 +679,7 @@ def parseOpts(overrideArguments=None): 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', @@ -707,17 +707,13 @@ def parseOpts(overrideArguments=None): '--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, @@ -739,7 +735,7 @@ def parseOpts(overrideArguments=None): 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( '-g', '--get-url', action='store_true', dest='geturl', default=False, @@ -982,9 +978,7 @@ def parseOpts(overrideArguments=None): 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.')) + 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, @@ -1189,9 +1183,9 @@ def parseOpts(overrideArguments=None): 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 {}\'') 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: srt|ass|vtt|lrc) (Alias: --convert-subtitles)') postproc.add_option( '--split-chapters', '--split-tracks', dest='split_chapters', action='store_true', default=False, -- cgit v1.2.3 From dd18a58cb1166b911c3b10e0e365bc8e01a1625b Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 20 Mar 2021 09:16:42 +0530 Subject: [documentation] Add `SplitChapters` to `--ppa` --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 28bbd27d7..49a275252 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1090,7 +1090,7 @@ def parseOpts(overrideArguments=None): '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. ' + 'FixupStretched, FixupM4a, FixupM3u8, SubtitlesConvertor, EmbedThumbnail and SplitChapters. ' 'The supported executables are: SponSkrub, FFmpeg, FFprobe, and AtomicParsley. ' '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, ' -- cgit v1.2.3 From 143db31d48802e26e975a94ab27263df381c9381 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 25 Mar 2021 03:32:15 +0530 Subject: Parse metadata from multiple fields Closes #196 --- yt_dlp/options.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 49a275252..95ef27e26 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1147,13 +1147,18 @@ def parseOpts(overrideArguments=None): metavar='FIELD:FORMAT', 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 ":". ' + 'Give a template or field name to extract data from and the ' + 'format to interpret it as, 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. ' + 'similar syntax to the output template can be used for the FORMAT. ' + 'Similarly, the syntax for output template can be used for FIELD ' + 'to parse the data from multiple fields. ' + 'The parsed parameters replace any existing values and can be used in output templates. ' 'This option can be used multiple times. ' 'Example: --parse-metadata "title:%(artist)s - %(title)s" matches a title like ' '"Coldplay - Paradise". ' + 'Example: --parse-metadata "%(series)s %(episode_number)s:%(title)s" ' + 'sets the title using series and episode number. ' 'Example (regex): --parse-metadata "description:Artist - (?P.+?)"')) postproc.add_option( '--xattrs', -- cgit v1.2.3 From b050d210dfd6f1a9d0e56820c81aa0eec924e2eb Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 1 Apr 2021 14:16:10 +0530 Subject: Fix some typos and linter --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 95ef27e26..2047ac28e 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1148,7 +1148,7 @@ def parseOpts(overrideArguments=None): help=( 'Parse additional metadata like title/artist from other fields. ' 'Give a template or field name to extract data from and the ' - 'format to interpret it as, seperated by a ":". ' + 'format to interpret it as, separated by a ":". ' 'Either regular expression with named capture groups or a ' 'similar syntax to the output template can be used for the FORMAT. ' 'Similarly, the syntax for output template can be used for FIELD ' -- cgit v1.2.3 From 73cd218f5a0e73a21c81a7faef123c8d12e1da77 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 3 Apr 2021 14:03:25 +0530 Subject: [documentation] Improve `--parse-metadata` documentation --- yt_dlp/options.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 2047ac28e..1057cb643 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -862,7 +862,7 @@ def parseOpts(overrideArguments=None): 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') + help='Output filename template; see "OUTPUT TEMPLATE" for details') filesystem.add_option( '--output-na-placeholder', dest='outtmpl_na_placeholder', metavar='TEXT', default='NA', @@ -1144,22 +1144,10 @@ def parseOpts(overrideArguments=None): 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 a template or field name to extract data from and the ' - 'format to interpret it as, separated by a ":". ' - 'Either regular expression with named capture groups or a ' - 'similar syntax to the output template can be used for the FORMAT. ' - 'Similarly, the syntax for output template can be used for FIELD ' - 'to parse the data from multiple fields. ' - 'The parsed parameters replace any existing values and can be used in output templates. ' - 'This option can be used multiple times. ' - 'Example: --parse-metadata "title:%(artist)s - %(title)s" matches a title like ' - '"Coldplay - Paradise". ' - 'Example: --parse-metadata "%(series)s %(episode_number)s:%(title)s" ' - 'sets the title using series and episode number. ' - 'Example (regex): --parse-metadata "description:Artist - (?P.+?)"')) + '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, -- cgit v1.2.3 From d818eb747361117ec86a5c4fe217d5d6956f36d3 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 10 Apr 2021 20:30:38 +0530 Subject: Improve argument parsing for `-P`, `-o`, `-S` * `-P "subtitle,thumbnail:PATH"` is now possible. Similarly for `-o` * `-S "fps,br" -S "res,codec"` is now interpreted as `-S res,codec,fps,br`. Previously, `-S fps,br` was ignored in this case. --- yt_dlp/options.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 1057cb643..6b4736e97 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -107,22 +107,31 @@ def parseOpts(overrideArguments=None): 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%s)%s(?P.*)$' % (allowed_keys, delimiter), value) + if multiple_keys: + allowed_keys = r'(%s)(,(%s))*' % (allowed_keys, allowed_keys) + mobj = re.match(r'(?i)(?P%s)%s(?P.*)$' % (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 @@ -693,6 +702,7 @@ def parseOpts(overrideArguments=None): '--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( @@ -842,7 +852,7 @@ def parseOpts(overrideArguments=None): 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()), @@ -857,7 +867,7 @@ def parseOpts(overrideArguments=None): '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()), @@ -1084,7 +1094,9 @@ def parseOpts(overrideArguments=None): '--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 ":" ' -- cgit v1.2.3 From 52a8a1e1b93dbc88f0018d4842f1e90ba96e095f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 10 Apr 2021 20:38:33 +0530 Subject: Option to choose different downloader for different protocols * Renamed `--external-downloader-args` to `--downloader-args` * Added `native` as an option for the downloader * Use similar syntax to `--downloader-args` etc. Eg: `--downloader dash:native --downloader aria2c` * Deprecated `--hls-prefer-native` and `--hls-prefer-ffmpeg` since the same can now be done with `--downloader "m3u8:native"` and `m3u8:ffmpeg` respectively * Split `frag_urls` protocol into `m3u8_frag_urls` and `dash_frag_urls` * Standardize shortening of protocol names with `downloader.shorten_protocol_name` --- yt_dlp/options.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 6b4736e97..7f36777d9 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -639,11 +639,11 @@ def parseOpts(overrideArguments=None): 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, @@ -659,11 +659,20 @@ def parseOpts(overrideArguments=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', -- cgit v1.2.3 From d9aa233295ac4b679d408fd1ca8f85b3f30ddd9c Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 10 Apr 2021 20:52:54 +0530 Subject: Deprecate more options * `--all-formats` = `-f all` * `--include-ads` is not implemented --- yt_dlp/options.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 7f36777d9..ace353042 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -402,11 +402,11 @@ def parseOpts(overrideArguments=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( @@ -489,7 +489,7 @@ def parseOpts(overrideArguments=None): 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, -- cgit v1.2.3 From 9de3ea31269c396dabf5b26f92fa65bc99038ede Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 11 Apr 2021 05:39:55 +0530 Subject: Pass any field to `--exec` using similar syntax to output template Related: https://github.com/ytdl-org/youtube-dl/issues/28642 --- yt_dlp/options.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index ace353042..c4cb57e2f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1195,7 +1195,11 @@ def parseOpts(overrideArguments=None): 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, -- cgit v1.2.3 From 8fa43c73d83619722c7e30d70247eaa9b7f52810 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 11 Apr 2021 03:48:52 +0530 Subject: Add option `--convert-thumbnails` Closes: https://github.com/yt-dlp/yt-dlp/issues/99 https://github.com/yt-dlp/yt-dlp/issues/102 --- yt_dlp/options.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c4cb57e2f..574af0a54 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1109,10 +1109,11 @@ def parseOpts(overrideArguments=None): 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 ' @@ -1204,6 +1205,10 @@ def parseOpts(overrideArguments=None): '--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, -- cgit v1.2.3 From b31fdeedfd77af7c2274bcaf9d8bb3f84ffc6128 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 11 Apr 2021 05:52:55 +0530 Subject: [documentation] Improvements --- yt_dlp/options.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 574af0a54..cced9fb89 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -259,7 +259,7 @@ def parseOpts(overrideArguments=None): 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', @@ -429,21 +429,19 @@ def parseOpts(overrideArguments=None): '--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') @@ -569,7 +567,7 @@ def parseOpts(overrideArguments=None): 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', @@ -1037,7 +1035,7 @@ def parseOpts(overrideArguments=None): 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, @@ -1310,7 +1308,6 @@ def parseOpts(overrideArguments=None): 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) -- cgit v1.2.3 From b7da73eb19e00e4eab43ec7de129e9aa12f6d5d3 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 17 Apr 2021 05:39:58 +0530 Subject: Add option `--ignore-no-formats-error` * Ignores the "no video format" and similar errors * Experimental - Some extractors may still throw these errors --- yt_dlp/options.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index cced9fb89..fef1e4b15 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -749,6 +749,16 @@ def parseOpts(overrideArguments=None): '-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, -- cgit v1.2.3 From c32b0aab8a1ac1498ad474559cb097d4927d8324 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 20 Apr 2021 02:47:09 +0530 Subject: Improve --sub-langs (see desc) * Treat `--sub-langs` entries as regex * `all` can be used to refer to all the subtitles * the language code can be prefixed with `-` to exclude it * Deprecates `--all-subs` Closes #253 --- yt_dlp/options.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index fef1e4b15..a16604b73 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -548,7 +548,7 @@ def parseOpts(overrideArguments=None): 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, @@ -561,7 +561,10 @@ def parseOpts(overrideArguments=None): '--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( -- cgit v1.2.3 From 26e2805c3f11066c79ed29cf78511eae7fdc7a7b Mon Sep 17 00:00:00 2001 From: pukkandan Date: Wed, 21 Apr 2021 11:30:43 +0530 Subject: Add option `--skip-playlist-after-errors` Allows to skip the rest of a playlist after a given number of errors are encountered --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index a16604b73..c21c453ed 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -395,6 +395,10 @@ def parseOpts(overrideArguments=None): '--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, -- cgit v1.2.3 From a439a3a45ca884956cacc104680e0a32aa3faba5 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 15 Apr 2021 18:01:16 +0530 Subject: Improve output template (see desc) * Objects can be traversed like `%(field.key1.key2)s` * A number can be added to the field as `%(field+n)s` * Deprecates `--autonumber-start` --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c21c453ed..60ae6c7fe 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -908,7 +908,7 @@ def parseOpts(overrideArguments=None): 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, -- cgit v1.2.3 From e58c22a0f62757cbe5b5713f27badfb7a742f327 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 22 Apr 2021 16:34:02 +0530 Subject: [documentation] Fix typos --- yt_dlp/options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 60ae6c7fe..d99aeba44 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -526,7 +526,7 @@ def parseOpts(overrideArguments=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', @@ -820,8 +820,8 @@ def parseOpts(overrideArguments=None): '--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, @@ -962,7 +962,7 @@ def parseOpts(overrideArguments=None): 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, -- cgit v1.2.3 From cc0ec3e16119df54ff69fc26d45f2bfa954814c2 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 1 May 2021 21:29:42 +0530 Subject: Do not strip out whitespaces in `-o` and `-P` Related: https://github.com/yt-dlp/yt-dlp/issues/276#issuecomment-827361652 --- yt_dlp/options.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index d99aeba44..a3fd9d122 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -669,7 +669,9 @@ def parseOpts(overrideArguments=None): 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()}, + 'default_key': 'default', + 'process': lambda x: x.strip() + }, help=( '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. ' @@ -684,7 +686,9 @@ def parseOpts(overrideArguments=None): 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 ":". ' @@ -878,9 +882,7 @@ def parseOpts(overrideArguments=None): '-P', '--paths', 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 ":". ' @@ -895,7 +897,8 @@ def parseOpts(overrideArguments=None): 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()}, + 'default_key': 'default' + }, help='Output filename template; see "OUTPUT TEMPLATE" for details') filesystem.add_option( '--output-na-placeholder', @@ -1120,7 +1123,9 @@ def parseOpts(overrideArguments=None): action='callback', callback=_dict_from_multiple_values_options_callback, callback_kwargs={ 'allowed_keys': r'\w+(?:\+\w+)?', 'default_key': 'default-compat', - 'process': compat_shlex_split, 'multiple_keys': False}, + '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 ":" ' -- cgit v1.2.3 From e8e738406a01f2a2ca07ef348b453a49d19d1614 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 4 May 2021 21:24:00 +0530 Subject: Add experimental option `--check-formats` to test the URLs before format selection --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index a3fd9d122..7505e8c78 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -502,6 +502,10 @@ def parseOpts(overrideArguments=None): '--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', -- cgit v1.2.3 From 486fb1797547bc83995d1b1c1bd98ffc39ae8deb Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 8 May 2021 20:51:43 +0530 Subject: Remove `-l`, `-t`, `-A` completely and disable `--auto-number`, `--title`, `--literal`, `--id` --- yt_dlp/options.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 7505e8c78..3c103f6da 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -937,15 +937,15 @@ def parseOpts(overrideArguments=None): 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( -- cgit v1.2.3 From 53ed7066ab711ca9a167174de0b61eeed2d04fa4 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 11 May 2021 13:30:48 +0530 Subject: Option `--compat-options` to revert some of yt-dlp's changes * Deprecates `--list-formats-as-table`, `--list-formats-old` --- yt_dlp/options.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 3c103f6da..49c3f7d63 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -165,7 +165,7 @@ def parseOpts(overrideArguments=None): 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', @@ -229,6 +229,14 @@ def parseOpts(overrideArguments=None): '--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( @@ -474,7 +482,7 @@ def parseOpts(overrideArguments=None): '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', @@ -482,7 +490,7 @@ def parseOpts(overrideArguments=None): 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', @@ -513,11 +521,11 @@ def parseOpts(overrideArguments=None): 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, @@ -1012,7 +1020,7 @@ def parseOpts(overrideArguments=None): 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)')) -- cgit v1.2.3 From e632bce2e4745b3e60b1c8b4b5dde2dee9b743a6 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 13 May 2021 17:51:22 +0530 Subject: [options] Refactor callbacks --- yt_dlp/options.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 49c3f7d63..0f2b77287 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -107,13 +107,15 @@ def parseOpts(overrideArguments=None): return ''.join(opts) - def _comma_separated_values_options_callback(option, opt_str, value, parser, prepend=True): + 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, - value.split(',') if not prepend - else value.split(',') + getattr(parser.values, option.dest)) + current + value if append is True else value + current) - def _dict_from_multiple_values_options_callback( + def _dict_from_options_callback( option, opt_str, value, parser, allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None, multiple_keys=True): @@ -232,7 +234,7 @@ def parseOpts(overrideArguments=None): general.add_option( '--compat-options', metavar='OPTS', dest='compat_opts', default=[], - action='callback', callback=_comma_separated_values_options_callback, type='str', + 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. ' @@ -465,8 +467,8 @@ def parseOpts(overrideArguments=None): 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', @@ -576,7 +578,7 @@ def parseOpts(overrideArguments=None): subtitles.add_option( '--sub-langs', '--srt-langs', action='callback', dest='subtitleslangs', metavar='LANGS', type='str', - default=[], callback=_comma_separated_values_options_callback, + 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) ' @@ -678,7 +680,7 @@ def parseOpts(overrideArguments=None): downloader.add_option( '--downloader', '--external-downloader', dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str', - action='callback', callback=_dict_from_multiple_values_options_callback, + action='callback', callback=_dict_from_options_callback, callback_kwargs={ 'allowed_keys': 'http|ftp|m3u8|dash|rtsp|rtmp|mms', 'default_key': 'default', @@ -695,7 +697,7 @@ def parseOpts(overrideArguments=None): 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', @@ -731,7 +733,7 @@ def parseOpts(overrideArguments=None): 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', ) @@ -893,7 +895,7 @@ def parseOpts(overrideArguments=None): filesystem.add_option( '-P', '--paths', metavar='TYPES:PATH', dest='paths', default={}, type='str', - action='callback', callback=_dict_from_multiple_values_options_callback, + 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. ' @@ -906,7 +908,7 @@ def parseOpts(overrideArguments=None): filesystem.add_option( '-o', '--output', metavar='[TYPES:]TEMPLATE', dest='outtmpl', default={}, type='str', - action='callback', callback=_dict_from_multiple_values_options_callback, + action='callback', callback=_dict_from_options_callback, callback_kwargs={ 'allowed_keys': '|'.join(OUTTMPL_TYPES.keys()), 'default_key': 'default' @@ -1132,7 +1134,7 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--postprocessor-args', '--ppa', metavar='NAME:ARGS', dest='postprocessor_args', default={}, type='str', - action='callback', callback=_dict_from_multiple_values_options_callback, + action='callback', callback=_dict_from_options_callback, callback_kwargs={ 'allowed_keys': r'\w+(?:\+\w+)?', 'default_key': 'default-compat', 'process': compat_shlex_split, -- cgit v1.2.3 From 53c18592d39b253bfff1f32ccd5821d8b73ce173 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 14 May 2021 13:14:38 +0530 Subject: Add option `--print` Deprecates: `--get-description`, `--get-duration`, `--get-filename`, `--get-format`, `--get-id`, `--get-thumbnail`, `--get-title`, `--get-url` Closes #295 --- yt_dlp/options.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 0f2b77287..26e54f1f6 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -788,38 +788,45 @@ def parseOpts(overrideArguments=None): '--skip-download', '--no-download', action='store_true', dest='skip_download', default=False, help='Do not download the video but write all related files (Alias: --no-download)') + verbosity.add_option( + '-O', '--print', metavar='TEMPLATE', + action='callback', dest='print', 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, -- cgit v1.2.3 From d2a1fad9689cf866309c9de9c5b06adb73a8a943 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 13 May 2021 17:09:43 +0530 Subject: [compat] Fix py2 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 26e54f1f6..b99d5d202 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -790,7 +790,7 @@ def parseOpts(overrideArguments=None): help='Do not download the video but write all related files (Alias: --no-download)') verbosity.add_option( '-O', '--print', metavar='TEMPLATE', - action='callback', dest='print', type='str', default=[], + 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 ' -- cgit v1.2.3 From 2305e2e5c91e46f921cf4221033a0804c78876f8 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 20 May 2021 15:40:35 +0530 Subject: [options] Alias `--write-comments`, `--no-write-comments` Closes: #264 --- yt_dlp/options.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index b99d5d202..695e08594 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1048,11 +1048,15 @@ def parseOpts(overrideArguments=None): 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', -- cgit v1.2.3 From a927acb1ecf7cef80c24eca604b73d9b5e45b732 Mon Sep 17 00:00:00 2001 From: louie-github <30176969+louie-github@users.noreply.github.com> Date: Sat, 22 May 2021 02:09:48 +0800 Subject: [ThumbnailsConvertor] Support conversion to `png` and make it the default (#333) PNG, being a lossless format, should be a better default here compared to JPG since we won't be compressing to a lossy format and losing some of the original image data PNG is also supported for embedding in all the formats similar to JPEG Authored by: louie-github --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 695e08594..c982dbb84 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1253,7 +1253,7 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--convert-thumbnails', metavar='FORMAT', dest='convertthumbnails', default=None, - help='Convert the thumbnails to another format (currently supported: jpg)') + help='Convert the thumbnails to another format (currently supported: jpg, png)') postproc.add_option( '--split-chapters', '--split-tracks', dest='split_chapters', action='store_true', default=False, -- cgit v1.2.3 From 857f63136d4f46b18353f8e50b07ff1394b79695 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 22 May 2021 13:08:12 +0530 Subject: [videoconvertor] Generalize with remuxer and allow conditional recoding --- yt_dlp/options.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c982dbb84..812bee572 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1141,7 +1141,8 @@ def parseOpts(overrideArguments=None): 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')) + 'You can specify multiple rules similar to --remux-video. ' + 'The supported formats are also the same as --remux-video')) postproc.add_option( '--postprocessor-args', '--ppa', metavar='NAME:ARGS', dest='postprocessor_args', default={}, type='str', -- cgit v1.2.3 From 81a23040ebf330a87a7eb842aa76884d5fc6e504 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 22 May 2021 13:54:12 +0530 Subject: [cleanup] Refactor ffmpeg convertors --- yt_dlp/options.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 812bee572..c72a7d5d0 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -5,7 +5,6 @@ import optparse import re import sys -from .downloader.external import list_external_downloaders from .compat import ( compat_expanduser, compat_get_terminal_size, @@ -18,11 +17,18 @@ from .utils import ( 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']) @@ -1123,7 +1129,9 @@ def parseOpts(overrideArguments=None): 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', @@ -1134,15 +1142,14 @@ def parseOpts(overrideArguments=None): 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. ' - 'You can specify multiple rules similar to --remux-video. ' - 'The supported formats are also 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', @@ -1250,11 +1257,15 @@ def parseOpts(overrideArguments=None): 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)') + 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: jpg, png)') + 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, -- cgit v1.2.3 From 3b1fe47d840325903cce8f53bbe4d1fd1e31071b Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 8 Jun 2021 20:13:41 +0530 Subject: Release 2021.06.08 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c72a7d5d0..4d17356da 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1077,7 +1077,7 @@ def parseOpts(overrideArguments=None): 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') -- cgit v1.2.3 From 8ba87148802843c6502f7ffc48e574a2eb0049d2 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 11 Jun 2021 17:37:02 +0530 Subject: [EmbedThumbnail] Fix for already downloaded thumbnail --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 4d17356da..eb137ac47 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1200,7 +1200,7 @@ def parseOpts(overrideArguments=None): 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/audio as cover art') postproc.add_option( '--no-embed-thumbnail', action='store_false', dest='embedthumbnail', -- cgit v1.2.3 From fd7cfb6444272678b9bada28ed3dfa68535dc85e Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 20 Jun 2021 03:49:23 +0530 Subject: [cleanup] Refactor fixup --- yt_dlp/options.py | 1 + 1 file changed, 1 insertion(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index eb137ac47..0d1960d9f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1230,6 +1230,7 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--fixup', metavar='POLICY', dest='fixup', default=None, + choices=('never', 'ignore', 'warn', 'detect_or_warn'), help=( 'Automatically correct known faults of the file. ' 'One of never (do nothing), warn (only emit a warning), ' -- cgit v1.2.3 From f89b3e2d7ab7a6e28fc1d9975aa4e998b165c090 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 20 Jun 2021 04:15:19 +0530 Subject: Skip fixup of existing files and add `--fixup force` to force it --- yt_dlp/options.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 0d1960d9f..b26d43d2a 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1230,11 +1230,12 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--fixup', metavar='POLICY', dest='fixup', default=None, - choices=('never', 'ignore', 'warn', 'detect_or_warn'), + 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', -- cgit v1.2.3 From 7e067091e87fafbd7ac2d8b4e170c8cba7ec7ace Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 20 Jun 2021 03:54:37 +0530 Subject: [options] Rename `--add-metadata` to `--embed-metadata` and clarify that it embeds chapter markers --- yt_dlp/options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index b26d43d2a..20211a764 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1206,13 +1206,13 @@ def parseOpts(overrideArguments=None): 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', -- cgit v1.2.3 From e36d50c5dd35973c090f87df05d4e94963e8036c Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 21 Jun 2021 22:53:17 +0530 Subject: [websockets] Add `WebSocketFragmentFD` (#399) Necessary for #392 Co-authored by: nao20010128nao, pukkandan --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 20211a764..535178627 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1165,7 +1165,7 @@ def parseOpts(overrideArguments=None): '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. ' + '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, ' -- cgit v1.2.3 From 51d9739f8031fb37d8e25b0e9f1abea561e3d2e3 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Wed, 23 Jun 2021 04:41:09 +0530 Subject: Add option `--throttled-rate` below which video data is re-extracted Currently only for HTTP downloads Closes #430, workaround for https://github.com/ytdl-org/youtube-dl/issues/29326 --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 535178627..bd817fed7 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -599,6 +599,10 @@ def parseOpts(overrideArguments=None): '-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, -- cgit v1.2.3 From 6aecd87106a50c76352e34c84cdf5fe63571cd1f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Wed, 23 Jun 2021 07:06:12 +0530 Subject: Release 2021.06.23 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index bd817fed7..4ad5223fa 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1204,7 +1204,7 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--embed-thumbnail', action='store_true', dest='embedthumbnail', default=False, - help='Embed thumbnail in the video/audio as cover art') + help='Embed thumbnail in the video as cover art') postproc.add_option( '--no-embed-thumbnail', action='store_false', dest='embedthumbnail', -- cgit v1.2.3 From 5d3a0e794b50a7f2524bdf37a886e0f436eb2f14 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 25 Jun 2021 19:35:41 +0530 Subject: Add `--extractor-args` to pass extractor-specific arguments --- yt_dlp/options.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 4ad5223fa..5caf4cb53 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -716,7 +716,8 @@ def parseOpts(overrideArguments=None): 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( @@ -1343,22 +1344,34 @@ def parseOpts(overrideArguments=None): '--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) -- cgit v1.2.3 From 4bb6b02f93e633dbba7bb722c167bf3b725cd7ce Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 8 Jul 2021 21:03:13 +0530 Subject: Improve `extractor_args` parsing --- yt_dlp/options.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 5caf4cb53..64bc380e1 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -137,7 +137,11 @@ def parseOpts(overrideArguments=None): else: raise optparse.OptionValueError( 'wrong %s formatting; it should be %s, not "%s"' % (opt_str, option.metavar, value)) - val = process(val) if callable(process) else val + try: + val = process(val) if process else val + except Exception as err: + raise optparse.OptionValueError( + 'wrong %s formatting; %s' % (opt_str, err)) for key in keys: out_dict[key] = val @@ -1344,6 +1348,7 @@ def parseOpts(overrideArguments=None): '--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_arg_parser = lambda key, vals='': (key.strip().lower(), [val.strip() for val in vals.split(',')]) extractor.add_option( '--extractor-args', metavar='KEY:ARGS', dest='extractor_args', default={}, type='str', @@ -1351,11 +1356,11 @@ def parseOpts(overrideArguments=None): callback_kwargs={ 'multiple_keys': False, 'process': lambda val: dict( - (lambda x: (x[0], x[1].split(',')))(arg.split('=', 1) + ['', '']) for arg in val.split(';')) + _extractor_arg_parser(*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')) + 'You can use this option multiple times to give arguments for different extractors')) extractor.add_option( '--youtube-include-dash-manifest', '--no-youtube-skip-dash-manifest', action='store_true', dest='youtube_include_dash_manifest', default=True, -- cgit v1.2.3 From 5520aa2dc9119a091b96944d373e33251a3b9ba7 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 19 Jul 2021 23:26:22 +0530 Subject: Add option `--exec-before-download` Closes #530 --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 64bc380e1..2a42712b6 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1265,6 +1265,10 @@ def parseOpts(overrideArguments=None): '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( + '--exec-before-download', + metavar='CMD', dest='exec_before_dl_cmd', + help='Execute a command before the actual download. The syntax is the same as --exec') postproc.add_option( '--convert-subs', '--convert-sub', '--convert-subtitles', metavar='FORMAT', dest='convertsubtitles', default=None, -- cgit v1.2.3 From 0ba692acc8feffd46b6e1085fb4a2849b685945c Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 15 Jul 2021 22:49:59 +0530 Subject: [youtube] Extract more thumbnails * The thumbnail URLs are hard-coded and their actual existence is tested lazily * Added option `--no-check-formats` to not test them Closes #340, Related: #402, #337, https://github.com/ytdl-org/youtube-dl/issues/29049 --- yt_dlp/options.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 2a42712b6..f9201bf01 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -524,8 +524,12 @@ def parseOpts(overrideArguments=None): 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)") + action='store_true', dest='check_formats', default=None, + help='Check that the formats selected are actually downloadable') + video_format.add_option( + '--no-check-formats', + action='store_false', dest='check_formats', + help='Do not check that the formats selected are actually downloadable') video_format.add_option( '-F', '--list-formats', action='store_true', dest='listformats', -- cgit v1.2.3 From 982ee69a742347efe91acb12df1f14ba5c7f65dd Mon Sep 17 00:00:00 2001 From: Matt Broadway Date: Wed, 21 Jul 2021 21:32:49 +0100 Subject: Add option `--cookies-from-browser` to load cookies from a browser (#488) * also adds `--no-cookies-from-browser` Original PR: https://github.com/ytdl-org/youtube-dl/pull/29201 Authored by: mbway --- yt_dlp/options.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index f9201bf01..5c3ac0dcd 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -19,6 +19,7 @@ from .utils import ( preferredencoding, write_string, ) +from .cookies import SUPPORTED_BROWSERS from .version import __version__ from .downloader.external import list_external_downloaders @@ -148,7 +149,10 @@ def parseOpts(overrideArguments=None): # No need to wrap help messages if we're on a wide console columns = compat_get_terminal_size().columns max_width = columns if columns else 80 - max_help_position = 80 + # 47% is chosen because that is how README.md is currently formatted + # and moving help text even further to the right is undesirable. + # This can be reduced in the future to get a prettier output + max_help_position = int(0.47 * max_width) fmt = optparse.IndentedHelpFormatter(width=max_width, max_help_position=max_help_position) fmt.format_option_strings = _format_option_string @@ -1087,7 +1091,21 @@ def parseOpts(overrideArguments=None): filesystem.add_option( '--no-cookies', action='store_const', const=None, dest='cookiefile', metavar='FILE', - help='Do not read/dump cookies (default)') + help='Do not read/dump cookies from/to file (default)') + filesystem.add_option( + '--cookies-from-browser', + dest='cookiesfrombrowser', metavar='BROWSER[:PROFILE]', + help=( + 'Load cookies from a user profile of the given web browser. ' + 'Currently supported browsers are: {}. ' + 'You can specify the user profile name or directory using ' + '"BROWSER:PROFILE_NAME" or "BROWSER:PROFILE_PATH". ' + 'If no profile is given, the most recently accessed one is used'.format( + '|'.join(sorted(SUPPORTED_BROWSERS))))) + filesystem.add_option( + '--no-cookies-from-browser', + action='store_const', const=None, dest='cookiesfrombrowser', + help='Do not load cookies from browser (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 (such as client ids and signatures) permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl') -- cgit v1.2.3 From 7d1eb38af154db77341b28b14776b23172a234e0 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 29 Jul 2021 08:26:17 +0530 Subject: Add format types `j`, `l`, `q` for outtmpl Closes #345 --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 5c3ac0dcd..9b71427d1 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1286,11 +1286,11 @@ def parseOpts(overrideArguments=None): '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')) + 'If no fields are passed, %(filepath)q is appended to the end of the command')) postproc.add_option( '--exec-before-download', metavar='CMD', dest='exec_before_dl_cmd', - help='Execute a command before the actual download. The syntax is the same as --exec') + help='Execute a command before the actual download. The syntax is the same as --exec but "filepath" is not available') postproc.add_option( '--convert-subs', '--convert-sub', '--convert-subtitles', metavar='FORMAT', dest='convertsubtitles', default=None, -- cgit v1.2.3 From e4f0275711cd4917bfe819356533926cd369a621 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 31 Jul 2021 11:38:39 +0530 Subject: Add compat-option `no-clean-infojson` --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 9b71427d1..955f610e6 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1062,7 +1062,7 @@ def parseOpts(overrideArguments=None): 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, + action='store_true', dest='clean_infojson', default=None, help=( 'Remove some private fields such as filenames from the infojson. ' 'Note that it could still contain some personal information (default)')) -- cgit v1.2.3 From d74a58a186603670f0f8acbc07a54f6381ca267f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 31 Jul 2021 19:00:32 +0530 Subject: Set `home:` as the default key for `-P` --- yt_dlp/options.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 955f610e6..e21030c28 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -924,14 +924,16 @@ def parseOpts(overrideArguments=None): action='store_true', dest='useid', help=optparse.SUPPRESS_HELP) filesystem.add_option( '-P', '--paths', - metavar='TYPES:PATH', dest='paths', default={}, type='str', + 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=( + callback_kwargs={ + 'allowed_keys': 'home|temp|%s' % '|'.join(OUTTMPL_TYPES.keys()), + 'default_key': 'home' + }, help=( 'The paths where the files should be downloaded. ' 'Specify the type of file and the path separated by a colon ":". ' 'All the same types as --output are supported. ' - 'Additionally, you can also provide "home" and "temp" paths. ' + 'Additionally, you can also provide "home" (default) and "temp" paths. ' 'All intermediary files are first downloaded to the temp path and ' 'then the final files are moved over to the home path after download is finished. ' 'This option is ignored if --output is an absolute path')) -- cgit v1.2.3 From dbf5416a20b8a4ff301ef6c641f516fa20a546cb Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 31 Jul 2021 16:21:01 +0530 Subject: [cleanup] Refactor some code --- yt_dlp/options.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index e21030c28..85dadc7d9 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -706,9 +706,8 @@ def parseOpts(overrideArguments=None): callback_kwargs={ 'allowed_keys': 'http|ftp|m3u8|dash|rtsp|rtmp|mms', 'default_key': 'default', - 'process': lambda x: x.strip() - }, - help=( + 'process': str.strip + }, help=( '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). ' @@ -724,8 +723,7 @@ def parseOpts(overrideArguments=None): 'allowed_keys': '|'.join(list_external_downloaders()), 'default_key': 'default', 'process': compat_shlex_split - }, - help=( + }, 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 to give different arguments to different downloaders ' @@ -944,8 +942,7 @@ def parseOpts(overrideArguments=None): callback_kwargs={ 'allowed_keys': '|'.join(OUTTMPL_TYPES.keys()), 'default_key': 'default' - }, - help='Output filename template; see "OUTPUT TEMPLATE" for details') + }, help='Output filename template; see "OUTPUT TEMPLATE" for details') filesystem.add_option( '--output-na-placeholder', dest='outtmpl_na_placeholder', metavar='TEXT', default='NA', @@ -1191,8 +1188,7 @@ def parseOpts(overrideArguments=None): 'allowed_keys': r'\w+(?:\+\w+)?', 'default_key': 'default-compat', 'process': compat_shlex_split, 'multiple_keys': False - }, - help=( + }, 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 PP are: ' @@ -1385,8 +1381,7 @@ def parseOpts(overrideArguments=None): 'multiple_keys': False, 'process': lambda val: dict( _extractor_arg_parser(*arg.split('=', 1)) for arg in val.split(';')) - }, - help=( + }, help=( 'Pass these arguments to the extractor. See "EXTRACTOR ARGUMENTS" for details. ' 'You can use this option multiple times to give arguments for different extractors')) extractor.add_option( -- cgit v1.2.3 From 77b87f0519719c4264f400f5627da86c12f48bca Mon Sep 17 00:00:00 2001 From: Max Teegen <870074+max-te@users.noreply.github.com> Date: Sun, 13 Jun 2021 16:25:19 +0200 Subject: Add all format filtering operators also to `--match-filter` PR: https://github.com/ytdl-org/youtube-dl/pull/27361 Authored by: max-te --- yt_dlp/options.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 85dadc7d9..fba231382 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -375,22 +375,16 @@ def parseOpts(overrideArguments=None): '--match-filter', metavar='FILTER', dest='match_filter', default=None, help=( - 'Generic video filter. ' - 'Specify any key (see "OUTPUT TEMPLATE" for a list of available keys) to ' - 'match if the key is present, ' - '!key to check if the key is not present, ' - 'key>NUMBER (like "view_count > 12", also works with ' - '>=, <, <=, !=, =) to compare against a number, ' - 'key = \'LITERAL\' (like "uploader = \'Mike Smith\'", also works with !=) ' - 'to match against a string literal ' - 'and & to require multiple matches. ' - 'Values which are not known are excluded unless you ' - 'put a question mark (?) after the operator. ' - 'For example, to only match videos that have been liked more than ' - '100 times and disliked less than 50 times (or the dislike ' - 'functionality is not available at the given service), but who ' - 'also have a description, use --match-filter ' - '"like_count > 100 & dislike_count 100 & dislike_count Date: Thu, 5 Aug 2021 03:01:23 +0530 Subject: Add regex to `--match-filter` This does not fully deprecate `--match-title`/`--reject-title` since `--match-filter` is only checked after the extraction is complete, while `--match-title` can often be checked from the flat playlist. Fixes: https://github.com/ytdl-org/youtube-dl/issues/9092, https://github.com/ytdl-org/youtube-dl/issues/23035 --- yt_dlp/options.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index fba231382..b5ddbeaff 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -378,13 +378,14 @@ def parseOpts(overrideArguments=None): 'Generic video filter. Any field (see "OUTPUT TEMPLATE") can be compared with a ' 'number or a string using the operators defined in "Filtering formats". ' 'You can also simply specify a field to match if the field is present ' - 'and "!field" to check if the field is not present. ' - 'Multiple filters can be checked using "&". ' - 'For example, to only match videos that are not live, ' - 'has a like count more than 100, a dislike count less than 50 ' - '(or the dislike field is not available), and also has a description ' - 'that contains "python", use --match-filter "!is_live & ' - 'like_count>100 & dislike_count?100 & description~=\'(?i)\bcats \& dogs\b\'" ' + 'matches only videos that are not live, has a like count more than 100 ' + '(or the like field is not available), and also has a description ' + 'that contains the phrase "cats & dogs" (ignoring case)')) selection.add_option( '--no-match-filter', metavar='FILTER', dest='match_filter', action='store_const', const=None, -- cgit v1.2.3 From 57015a4a3f15b23c152ffd2d72ed9ef520664ee5 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 7 Aug 2021 11:32:15 +0530 Subject: [youtube] extractor-arg to show live dash formats If replay is enabled, these formats can be used to download the last 4 hours --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index b5ddbeaff..e70471282 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1367,7 +1367,7 @@ def parseOpts(overrideArguments=None): '--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_arg_parser = lambda key, vals='': (key.strip().lower(), [val.strip() for val in vals.split(',')]) + _extractor_arg_parser = lambda key, vals='': (key.strip().lower().replace('-', '_'), [val.strip() for val in vals.split(',')]) extractor.add_option( '--extractor-args', metavar='KEY:ARGS', dest='extractor_args', default={}, type='str', -- cgit v1.2.3 From b7b04c782eec0945d54aff5ebe9cade413a10377 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 7 Aug 2021 05:31:51 +0530 Subject: Add option `--no-simulate` to not simulate even when `--print` or `--list...` are used * Deprecates `--print-json` * Some listings like `--list-extractors` are handled by `yt_dlp` and so are not affected by this. These have been documented as such Addresses: https://github.com/ytdl-org/youtube-dl/issues/29675, https://github.com/ytdl-org/youtube-dl/issues/29580#issuecomment-882046305 --- yt_dlp/options.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index e70471282..55c2b9aa3 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -190,15 +190,15 @@ def parseOpts(overrideArguments=None): general.add_option( '--dump-user-agent', action='store_true', dest='dump_user_agent', default=False, - help='Display the current browser identification') + help='Display the current browser identification and exit') general.add_option( '--list-extractors', action='store_true', dest='list_extractors', default=False, - help='List all supported extractors') + help='List all supported extractors and exit') general.add_option( '--extractor-descriptions', action='store_true', dest='list_extractor_descriptions', default=False, - help='Output descriptions of all supported extractors') + help='Output descriptions of all supported extractors and exit') general.add_option( '--force-generic-extractor', action='store_true', dest='force_generic_extractor', default=False, @@ -532,7 +532,7 @@ def parseOpts(overrideArguments=None): video_format.add_option( '-F', '--list-formats', action='store_true', dest='listformats', - help='List all available formats of requested videos') + help='List available formats of each video. Simulate unless --no-simulate is used') video_format.add_option( '--list-formats-as-table', action='store_true', dest='listformats_table', default=True, @@ -583,7 +583,7 @@ def parseOpts(overrideArguments=None): subtitles.add_option( '--list-subs', action='store_true', dest='listsubtitles', default=False, - help='List all available subtitles for the video') + help='List available subtitles of each video. Simulate unless --no-simulate is used') subtitles.add_option( '--sub-format', action='store', dest='subtitlesformat', metavar='FORMAT', default='best', @@ -788,8 +788,12 @@ def parseOpts(overrideArguments=None): help='Ignore warnings') verbosity.add_option( '-s', '--simulate', - action='store_true', dest='simulate', default=False, + action='store_true', dest='simulate', default=None, help='Do not download the video and do not write anything to disk') + verbosity.add_option( + '--no-simulate', + action='store_false', dest='simulate', + help='Download the video even if printing/listing options are used') verbosity.add_option( '--ignore-no-formats-error', action='store_true', dest='ignore_no_formats_error', default=False, @@ -809,8 +813,8 @@ def parseOpts(overrideArguments=None): 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')) + 'Quiet, but print the given fields for each video. Simulate unless --no-simulate is used. ' + 'Either a field name or same syntax as the output template can be used')) verbosity.add_option( '-g', '--get-url', action='store_true', dest='geturl', default=False, @@ -846,17 +850,17 @@ def parseOpts(overrideArguments=None): verbosity.add_option( '-j', '--dump-json', action='store_true', dest='dumpjson', default=False, - help='Simulate, quiet but print JSON information. See "OUTPUT TEMPLATE" for a description of available keys') + help='Quiet, but print JSON information for each video. Simulate unless --no-simulate is used. See "OUTPUT TEMPLATE" for a description of available keys') verbosity.add_option( '-J', '--dump-single-json', action='store_true', dest='dump_single_json', default=False, help=( - 'Simulate, quiet but print JSON information for each command-line argument. ' - 'If the URL refers to a playlist, dump the whole playlist information in a single line')) + 'Quiet, but print JSON information for each url or infojson passed. Simulate unless --no-simulate is used. ' + 'If the URL refers to a playlist, the whole playlist information is dumped in a single line')) verbosity.add_option( '--print-json', action='store_true', dest='print_json', default=False, - help='Be quiet and print the video information as JSON (video is still being downloaded)') + help=optparse.SUPPRESS_HELP) verbosity.add_option( '--force-write-archive', '--force-write-download-archive', '--force-download-archive', action='store_true', dest='force_write_download_archive', default=False, @@ -1127,7 +1131,7 @@ def parseOpts(overrideArguments=None): thumbnail.add_option( '--list-thumbnails', action='store_true', dest='list_thumbnails', default=False, - help='Simulate and list all available thumbnail formats') + help='List available thumbnails of each video. Simulate unless --no-simulate is used') link = optparse.OptionGroup(parser, 'Internet Shortcut Options') link.add_option( -- cgit v1.2.3 From c681cb5d931b61a4370c56c8da82f01f3983f000 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 7 Aug 2021 13:30:55 +0530 Subject: Allow multiple `--exec` and `--exec-before-download` --- yt_dlp/options.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 55c2b9aa3..38c99bbcb 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1277,17 +1277,31 @@ def parseOpts(overrideArguments=None): dest='ffmpeg_location', help='Location of the ffmpeg binary; either the path to the binary or its containing directory') postproc.add_option( - '--exec', - metavar='CMD', dest='exec_cmd', + '--exec', metavar='CMD', + action='callback', dest='exec_cmd', default=[], type='str', + callback=_list_from_options_callback, callback_kwargs={'delim': None}, 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)q is appended to the end of the command')) + 'If no fields are passed, %(filepath)q is appended to the end of the command. ' + 'This option can be used multiple times')) + postproc.add_option( + '--no-exec', + action='store_const', dest='exec_cmd', const=[], + help='Remove any previously defined --exec') + postproc.add_option( + '--exec-before-download', metavar='CMD', + action='callback', dest='exec_before_dl_cmd', default=[], type='str', + callback=_list_from_options_callback, callback_kwargs={'delim': None}, + help=( + 'Execute a command before the actual download. ' + 'The syntax is the same as --exec but "filepath" is not available. ' + 'This option can be used multiple times')) postproc.add_option( - '--exec-before-download', - metavar='CMD', dest='exec_before_dl_cmd', - help='Execute a command before the actual download. The syntax is the same as --exec but "filepath" is not available') + '--no-exec-before-download', + action='store_const', dest='exec_before_dl_cmd', const=[], + help='Remove any previously defined --exec-before-download') postproc.add_option( '--convert-subs', '--convert-sub', '--convert-subtitles', metavar='FORMAT', dest='convertsubtitles', default=None, -- cgit v1.2.3 From 34488702053d995aba6a0dea9995e6a8858402dd Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 7 Aug 2021 14:19:17 +0530 Subject: [docs] Fix some mistakes and improve doc --- yt_dlp/options.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 38c99bbcb..aef2f8143 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -190,7 +190,7 @@ def parseOpts(overrideArguments=None): general.add_option( '--dump-user-agent', action='store_true', dest='dump_user_agent', default=False, - help='Display the current browser identification and exit') + help='Display the current user-agent and exit') general.add_option( '--list-extractors', action='store_true', dest='list_extractors', default=False, @@ -223,12 +223,6 @@ def parseOpts(overrideArguments=None): '--flat-playlist', action='store_const', dest='extract_flat', const='in_playlist', default=False, help='Do not extract the videos of a playlist, only list them') - general.add_option( - '--flat-videos', - action='store_true', dest='extract_flat', - # help='Do not resolve the video urls') - # doesn't work - help=optparse.SUPPRESS_HELP) general.add_option( '--no-flat-playlist', action='store_false', dest='extract_flat', @@ -781,7 +775,7 @@ def parseOpts(overrideArguments=None): verbosity.add_option( '-q', '--quiet', action='store_true', dest='quiet', default=False, - help='Activate quiet mode') + help='Activate quiet mode. If used with --verbose, print the log to stderr') verbosity.add_option( '--no-warnings', dest='no_warnings', action='store_true', default=False, @@ -799,7 +793,7 @@ def parseOpts(overrideArguments=None): 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)')) + 'even if the videos are not actually available for download (experimental)')) verbosity.add_option( '--no-ignore-no-formats-error', action='store_false', dest='ignore_no_formats_error', @@ -1282,7 +1276,7 @@ def parseOpts(overrideArguments=None): callback=_list_from_options_callback, callback_kwargs={'delim': None}, 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. ' + 'Same syntax as 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)q is appended to the end of the command. ' 'This option can be used multiple times')) -- cgit v1.2.3 From e9f4ccd19eb92621970b518fb5984b8aef52bdc8 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 10 Aug 2021 01:22:55 +0530 Subject: Add option `--replace-in-metadata` --- yt_dlp/options.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index aef2f8143..f8cfdeb12 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1241,10 +1241,14 @@ def parseOpts(overrideArguments=None): help=optparse.SUPPRESS_HELP) postproc.add_option( '--parse-metadata', - metavar='FROM:TO', dest='metafromfield', action='append', + metavar='FROM:TO', dest='parse_metadata', action='append', help=( 'Parse additional metadata like title/artist from other fields; ' 'see "MODIFYING METADATA" for details')) + postproc.add_option( + '--replace-in-metadata', + dest='parse_metadata', metavar='FIELDS REGEX REPLACE', action='append', nargs=3, + help='Replace text in a metadata field using the given regex. This option can be used multiple times') postproc.add_option( '--xattrs', action='store_true', dest='xattrs', default=False, -- cgit v1.2.3 From ad3dc496bbf2e2a574a16244ddde0740778e5daf Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 9 Aug 2021 17:40:24 +0530 Subject: Misc fixes - See desc * Remove unnecessary uses of _list_from_options_callback * Fix download tests - Bug from 6e84b21559f586ee4d6affb61688d5c6a0c21221 * Rename ExecAfterDownloadPP to ExecPP and refactor its tests * Ensure _write_ytdl_file closes file handle on error - Potential fix for #517 --- yt_dlp/options.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index f8cfdeb12..f2d5deb68 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -23,7 +23,7 @@ from .cookies import SUPPORTED_BROWSERS from .version import __version__ from .downloader.external import list_external_downloaders -from .postprocessor.ffmpeg import ( +from .postprocessor import ( FFmpegExtractAudioPP, FFmpegSubtitlesConvertorPP, FFmpegThumbnailsConvertorPP, @@ -803,9 +803,8 @@ def parseOpts(overrideArguments=None): action='store_true', dest='skip_download', default=False, 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}, + '-O', '--print', + metavar='TEMPLATE', action='append', dest='forceprint', help=( 'Quiet, but print the given fields for each video. Simulate unless --no-simulate is used. ' 'Either a field name or same syntax as the output template can be used')) @@ -1276,8 +1275,7 @@ def parseOpts(overrideArguments=None): help='Location of the ffmpeg binary; either the path to the binary or its containing directory') postproc.add_option( '--exec', metavar='CMD', - action='callback', dest='exec_cmd', default=[], type='str', - callback=_list_from_options_callback, callback_kwargs={'delim': None}, + action='append', dest='exec_cmd', help=( 'Execute a command on the file after downloading and post-processing. ' 'Same syntax as the output template can be used to pass any field as arguments to the command. ' @@ -1290,8 +1288,7 @@ def parseOpts(overrideArguments=None): help='Remove any previously defined --exec') postproc.add_option( '--exec-before-download', metavar='CMD', - action='callback', dest='exec_before_dl_cmd', default=[], type='str', - callback=_list_from_options_callback, callback_kwargs={'delim': None}, + action='append', dest='exec_before_dl_cmd', help=( 'Execute a command before the actual download. ' 'The syntax is the same as --exec but "filepath" is not available. ' -- cgit v1.2.3 From 31654882e9c2018a23b4b8de89038e62c1f15e59 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 15 Aug 2021 00:24:53 +0530 Subject: [options] Add `_set_from_options_callback` --- yt_dlp/options.py | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index f2d5deb68..1499991a1 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -122,6 +122,30 @@ def parseOpts(overrideArguments=None): parser.values, option.dest, current + value if append is True else value + current) + def _set_from_options_callback( + option, opt_str, value, parser, + delim=',', allowed_values=None, process=str.lower, aliases={}): + current = getattr(parser.values, option.dest) + values = [process(value)] if delim is None else process(value).split(delim)[::-1] + while values: + actual_val = val = values.pop() + if val == 'all': + current.update(allowed_values) + elif val == '-all': + current = set() + elif val in aliases: + values.extend(aliases[val]) + else: + if val[0] == '-': + val = val[1:] + current.discard(val) + else: + current.update([val]) + if allowed_values is not None and val not in allowed_values: + raise optparse.OptionValueError(f'wrong {option.metavar} for {opt_str}: {actual_val}') + + setattr(parser.values, option.dest, current) + def _dict_from_options_callback( option, opt_str, value, parser, allowed_keys=r'[\w-]+', delimiter=':', default_key=None, process=None, multiple_keys=True): @@ -241,10 +265,21 @@ def parseOpts(overrideArguments=None): 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 ' + metavar='OPTS', dest='compat_opts', default=set(), type='str', + action='callback', callback=_set_from_options_callback, + callback_kwargs={ + 'allowed_values': { + 'filename', 'format-sort', 'abort-on-error', 'format-spec', 'no-playlist-metafiles', + 'multistreams', 'no-live-chat', 'playlist-index', 'list-formats', 'no-direct-merge', + 'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-attach-info-json', + 'embed-thumbnail-atomicparsley', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', + }, + 'aliases': { + 'youtube-dl': ['-multistreams', 'all'], + 'youtube-dlc': ['-no-youtube-channel-redirect', '-no-live-chat', 'all'], + } + }, help=( + 'Options that can help keep compatibility with youtube-dl or youtube-dlc ' 'configurations by reverting some of the changes made in yt-dlp. ' 'See "Differences in default behavior" for details')) -- cgit v1.2.3 From 8f18aca8717bb0dd49054555af8d386e5eda3a88 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sun, 15 Aug 2021 13:42:23 +0530 Subject: Let `--match-filter` reject entries early Makes redundant: `--match-title`, `--reject-title`, `--min-views`, `--max-views` --- yt_dlp/options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 1499991a1..ef821eb11 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -356,11 +356,11 @@ def parseOpts(overrideArguments=None): selection.add_option( '--match-title', dest='matchtitle', metavar='REGEX', - help='Download only matching titles (regex or caseless sub-string)') + help=optparse.SUPPRESS_HELP) selection.add_option( '--reject-title', dest='rejecttitle', metavar='REGEX', - help='Skip download for matching titles (regex or caseless sub-string)') + help=optparse.SUPPRESS_HELP) selection.add_option( '--max-downloads', dest='max_downloads', metavar='NUMBER', type=int, default=None, @@ -395,11 +395,11 @@ def parseOpts(overrideArguments=None): selection.add_option( '--min-views', metavar='COUNT', dest='min_views', default=None, type=int, - help='Do not download any videos with less than COUNT views') + help=optparse.SUPPRESS_HELP) selection.add_option( '--max-views', metavar='COUNT', dest='max_views', default=None, type=int, - help='Do not download any videos with more than COUNT views') + help=optparse.SUPPRESS_HELP) selection.add_option( '--match-filter', metavar='FILTER', dest='match_filter', default=None, -- cgit v1.2.3 From 88acdbc2698169e22cdbf358e44765150434c69e Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 23 Aug 2021 01:38:38 +0530 Subject: [extractor] Better error message for DRM (#729) Closes #636 --- yt_dlp/options.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index ef821eb11..56ab001be 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -580,13 +580,11 @@ def parseOpts(overrideArguments=None): video_format.add_option( '--allow-unplayable-formats', action='store_true', dest='allow_unplayable_formats', default=False, - help=( - 'Allow unplayable formats to be listed and downloaded. ' - 'All video post-processing will also be turned off')) + help=optparse.SUPPRESS_HELP) video_format.add_option( '--no-allow-unplayable-formats', action='store_false', dest='allow_unplayable_formats', - help='Do not allow unplayable formats to be listed or downloaded (default)') + help=optparse.SUPPRESS_HELP) subtitles = optparse.OptionGroup(parser, 'Subtitle Options') subtitles.add_option( -- cgit v1.2.3 From 330690a214e5a9b6bebcfe9f7e46ebd8ffe77f03 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 24 Aug 2021 03:15:44 +0530 Subject: [downloader/ffmpeg] Allow passing custom arguments before -i Closes #686 --- yt_dlp/options.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 56ab001be..6bad37d19 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -742,12 +742,13 @@ def parseOpts(overrideArguments=None): metavar='NAME:ARGS', dest='external_downloader_args', default={}, type='str', action='callback', callback=_dict_from_options_callback, callback_kwargs={ - 'allowed_keys': '|'.join(list_external_downloaders()), + 'allowed_keys': r'ffmpeg_[io]\d*|%s' % '|'.join(list_external_downloaders()), '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 ":". ' + 'For ffmpeg, arguments can be passed to different positions using the same syntax as --postprocessor-args. ' 'You can use this option multiple times to give different arguments to different downloaders ' '(Alias: --external-downloader-args)')) -- cgit v1.2.3 From 0bb1bc1b107b9c3d68ea0c887bd09cad75d7714d Mon Sep 17 00:00:00 2001 From: coletdjnz Date: Tue, 24 Aug 2021 15:52:40 +1200 Subject: [youtube] Remove annotations and deprecate `--write-annotations` (#765) Closes #692 Authored by: coletdjnz --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 6bad37d19..86aad3393 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1070,11 +1070,11 @@ def parseOpts(overrideArguments=None): filesystem.add_option( '--write-annotations', action='store_true', dest='writeannotations', default=False, - help='Write video annotations to a .annotations.xml file') + help=optparse.SUPPRESS_HELP) filesystem.add_option( '--no-write-annotations', action='store_false', dest='writeannotations', - help='Do not write video annotations (default)') + help=optparse.SUPPRESS_HELP) filesystem.add_option( '--write-playlist-metafiles', action='store_true', dest='allow_playlist_files', default=None, -- cgit v1.2.3 From 1c36c1f3205e514717b974355f84b7fc823194d8 Mon Sep 17 00:00:00 2001 From: CeruleanSky Date: Wed, 25 Aug 2021 07:49:05 -0400 Subject: Fix `--no-prefer-free-formats` (#787) Authored by: CeruleanSky --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 86aad3393..c26d498a5 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -548,7 +548,7 @@ def parseOpts(overrideArguments=None): 'Use with "-S ext" to strictly prefer free containers irrespective of quality')) video_format.add_option( '--no-prefer-free-formats', - action='store_true', dest='prefer_free_formats', default=False, + action='store_false', dest='prefer_free_formats', default=False, help="Don't give any special preference to free containers (default)") video_format.add_option( '--check-formats', -- cgit v1.2.3 From 2e7781a93c702fffacf0076ccd498d79e03258d4 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 28 Aug 2021 02:20:18 +0530 Subject: [docs] Fix some typos Closes #677, #774 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c26d498a5..0f8ce8ce8 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -411,7 +411,7 @@ def parseOpts(overrideArguments=None): 'Python style regular expression matching can be done using "~=", ' 'and multiple filters can be checked with "&". ' 'Use a "\\" to escape "&" or quotes if needed. Eg: --match-filter ' - r'"!is_live & like_count>?100 & description~=\'(?i)\bcats \& dogs\b\'" ' + '"!is_live & like_count>?100 & description~=\'(?i)\\bcats \\& dogs\\b\'" ' 'matches only videos that are not live, has a like count more than 100 ' '(or the like field is not available), and also has a description ' 'that contains the phrase "cats & dogs" (ignoring case)')) -- cgit v1.2.3 From 7a340e0df352bf97da7a7fd238f7d705afbd9c6a Mon Sep 17 00:00:00 2001 From: Nil Admirari <50202386+nihil-admirari@users.noreply.github.com> Date: Wed, 1 Sep 2021 20:55:16 +0000 Subject: Native SponsorBlock implementation and related improvements (#360) SponsorBlock options: * The fetched sponsor sections are written to infojson * `--sponsorblock-remove` removes specified chapters from file * `--sponsorblock-mark` marks the specified sponsor sections as chapters * `--sponsorblock-chapter-title` to specify sponsor chapter template * `--sponsorblock-api` to use a different API Related improvements: * Split `--embed-chapters` from `--embed-metadata` * Add `--remove-chapters` to remove arbitrary chapters * Add `--force-keyframes-at-cuts` for more accurate cuts when removing and splitting chapters Deprecates all `--sponskrub` options Authored by: nihil-admirari, pukkandan --- yt_dlp/options.py | 113 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 27 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 0f8ce8ce8..483cce8d8 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -28,7 +28,9 @@ from .postprocessor import ( FFmpegSubtitlesConvertorPP, FFmpegThumbnailsConvertorPP, FFmpegVideoRemuxerPP, + SponsorBlockPP, ) +from .postprocessor.modify_chapters import DEFAULT_SPONSORBLOCK_CHAPTER_TITLE def _hide_login_info(opts): @@ -1218,10 +1220,10 @@ def parseOpts(overrideArguments=None): '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 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. ' + 'Merger, ModifyChapters, SplitChapters, ExtractAudio, VideoRemuxer, VideoConvertor, ' + 'Metadata, EmbedSubtitle, EmbedThumbnail, SubtitlesConvertor, ThumbnailsConvertor, ' + 'FixupStretched, FixupM4a, FixupM3u8, FixupTimestamp and FixupDuration. ' + 'The supported executables are: AtomicParsley, FFmpeg and FFprobe. ' '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 ' @@ -1263,11 +1265,19 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--embed-metadata', '--add-metadata', action='store_true', dest='addmetadata', default=False, - help='Embed metadata including chapter markers (if supported by the format) to the video file (Alias: --add-metadata)') + help='Embed metadata to the video file. Also adds chapters to file unless --no-add-chapters is used (Alias: --add-metadata)') postproc.add_option( '--no-embed-metadata', '--no-add-metadata', action='store_false', dest='addmetadata', - help='Do not write metadata (default) (Alias: --no-add-metadata)') + help='Do not add metadata to file (default) (Alias: --no-add-metadata)') + postproc.add_option( + '--embed-chapters', '--add-chapters', + action='store_true', dest='addchapters', default=None, + help='Add chapter markers to the video file (Alias: --add-chapters)') + postproc.add_option( + '--no-embed-chapters', '--no-add-chapters', + action='store_false', dest='addchapters', + help='Do not add chapter markers (default) (Alias: --no-add-chapters)') postproc.add_option( '--metadata-from-title', metavar='FORMAT', dest='metafromtitle', @@ -1354,41 +1364,90 @@ def parseOpts(overrideArguments=None): '--no-split-chapters', '--no-split-tracks', dest='split_chapters', action='store_false', help='Do not split video based on chapters (default)') + postproc.add_option( + '--remove-chapters', + metavar='REGEX', dest='remove_chapters', action='append', + help='Remove chapters whose title matches the given regular expression. This option can be used multiple times') + postproc.add_option( + '--no-remove-chapters', dest='remove_chapters', action='store_const', const=None, + help='Do not remove any chapters from the file (default)') + postproc.add_option( + '--force-keyframes-at-cuts', + action='store_true', dest='force_keyframes_at_cuts', default=False, + help=( + 'Force keyframes around the chapters before removing/splitting them. ' + 'Requires a reencode and thus is very slow, but the resulting video ' + 'may have fewer artifacts around the cuts')) + postproc.add_option( + '--no-force-keyframes-at-cuts', + action='store_false', dest='force_keyframes_at_cuts', + help='Do not force keyframes around the chapters when cutting/splitting (default)') - sponskrub = optparse.OptionGroup(parser, 'SponSkrub (SponsorBlock) Options', description=( - 'SponSkrub (https://github.com/yt-dlp/SponSkrub) is a utility to mark/remove sponsor segments ' - 'from downloaded YouTube videos using SponsorBlock API (https://sponsor.ajay.app)')) - sponskrub.add_option( + sponsorblock = optparse.OptionGroup(parser, 'SponsorBlock Options', description=( + 'Make chapter entries for, or remove various segments (sponsor, introductions, etc.) ' + 'from downloaded YouTube videos using the SponsorBlock API (https://sponsor.ajay.app)')) + sponsorblock.add_option( + '--sponsorblock-mark', metavar='CATS', + dest='sponsorblock_mark', default=set(), action='callback', type='str', + callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, + help=( + 'SponsorBlock categories to create chapters for, separated by commas. ' + 'Available categories are all, %s. You can prefix the category with a "-" to exempt it. ' + 'See https://wiki.sponsor.ajay.app/index.php/Segment_Categories for description of the categories. ' + 'Eg: --sponsorblock-query all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys()))) + sponsorblock.add_option( + '--sponsorblock-remove', metavar='CATS', + dest='sponsorblock_remove', default=set(), action='callback', type='str', + callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, + help=( + 'SponsorBlock categories to be removed from the video file, separated by commas. ' + 'If a category is present in both mark and remove, remove takes precedence. ' + 'The syntax and available categories are the same as for --sponsorblock-mark')) + sponsorblock.add_option( + '--sponsorblock-chapter-title', metavar='TEMPLATE', + default=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, dest='sponsorblock_chapter_title', + help=( + 'The title template for SponsorBlock chapters created by --sponsorblock-mark. ' + 'The same syntax as the output template is used, but the only available fields are ' + 'start_time, end_time, category, categories, name, category_names. Defaults to "%default"')) + sponsorblock.add_option( + '--no-sponsorblock', default=False, + action='store_true', dest='no_sponsorblock', + help='Disable both --sponsorblock-mark and --sponsorblock-remove') + sponsorblock.add_option( + '--sponsorblock-api', metavar='URL', + default='https://sponsor.ajay.app', dest='sponsorblock_api', + help='SponsorBlock API location, defaults to %default') + + sponsorblock.add_option( '--sponskrub', action='store_true', dest='sponskrub', default=None, - help=( - 'Use sponskrub to mark sponsored sections. ' - 'This is enabled by default if the sponskrub binary exists (Youtube only)')) - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--no-sponskrub', action='store_false', dest='sponskrub', - help='Do not use sponskrub') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--sponskrub-cut', default=False, action='store_true', dest='sponskrub_cut', - help='Cut out the sponsor sections instead of simply marking them') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--no-sponskrub-cut', action='store_false', dest='sponskrub_cut', - help='Simply mark the sponsor sections, not cut them out (default)') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--sponskrub-force', default=False, action='store_true', dest='sponskrub_force', - help='Run sponskrub even if the video was already downloaded') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--no-sponskrub-force', action='store_true', dest='sponskrub_force', - help='Do not cut out the sponsor sections if the video was already downloaded (default)') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--sponskrub-location', metavar='PATH', dest='sponskrub_path', default='', - help='Location of the sponskrub binary; either the path to the binary or its containing directory') - sponskrub.add_option( + help=optparse.SUPPRESS_HELP) + sponsorblock.add_option( '--sponskrub-args', dest='sponskrub_args', metavar='ARGS', help=optparse.SUPPRESS_HELP) @@ -1457,7 +1516,7 @@ def parseOpts(overrideArguments=None): parser.add_option_group(subtitles) parser.add_option_group(authentication) parser.add_option_group(postproc) - parser.add_option_group(sponskrub) + parser.add_option_group(sponsorblock) parser.add_option_group(extractor) if overrideArguments is not None: -- cgit v1.2.3 From 9ee4f0bb5b82fab44185b762d482bf9e96acd55a Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 2 Sep 2021 04:39:47 +0530 Subject: Release 2021.09.02 --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 483cce8d8..2086e1265 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -232,7 +232,7 @@ def parseOpts(overrideArguments=None): general.add_option( '--default-search', dest='default_search', metavar='PREFIX', - help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple". Use the value "auto" to let youtube-dl guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching') + help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for the search term "large apple". Use the value "auto" to let yt-dlp guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching') general.add_option( '--ignore-config', '--no-config', action='store_true', @@ -1135,7 +1135,7 @@ def parseOpts(overrideArguments=None): help='Do not load cookies from browser (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 (such as client ids and signatures) permanently. By default $XDG_CACHE_HOME/youtube-dl or ~/.cache/youtube-dl') + 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') filesystem.add_option( '--no-cache-dir', action='store_false', dest='cachedir', help='Disable filesystem caching') -- cgit v1.2.3 From dd594deb2a0449dd8b145ef0552235f66ee3d454 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 4 Sep 2021 01:18:56 +0530 Subject: Fix `--no-get-comments` Closes #882 --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 2086e1265..505160cec 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1105,7 +1105,7 @@ def parseOpts(overrideArguments=None): '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, + action='store_false', dest='getcomments', 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', -- cgit v1.2.3 From 165efb823b3a8a6a6788cfe23e6b93dfbe150568 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 4 Sep 2021 01:37:41 +0530 Subject: [ModifyChapters] fixes (See desc) * [docs] Fix typo * Do not enable `sponskrub` by default * Fix `--force-keyframes-at-cuts` * Don't embed subtitles if the video has been cut. Previously, running `--remove-chapters` with `--embed-subs` multiple times caused repeated cuts and out-of-sync subtitles * Store `_real_duration` to prevent running ffprobe multiple times --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 505160cec..c2d7a74ff 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1394,7 +1394,7 @@ def parseOpts(overrideArguments=None): 'SponsorBlock categories to create chapters for, separated by commas. ' 'Available categories are all, %s. You can prefix the category with a "-" to exempt it. ' 'See https://wiki.sponsor.ajay.app/index.php/Segment_Categories for description of the categories. ' - 'Eg: --sponsorblock-query all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys()))) + 'Eg: --sponsorblock-mark all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys()))) sponsorblock.add_option( '--sponsorblock-remove', metavar='CATS', dest='sponsorblock_remove', default=set(), action='callback', type='str', @@ -1421,7 +1421,7 @@ def parseOpts(overrideArguments=None): sponsorblock.add_option( '--sponskrub', - action='store_true', dest='sponskrub', default=None, + action='store_true', dest='sponskrub', default=False, help=optparse.SUPPRESS_HELP) sponsorblock.add_option( '--no-sponskrub', -- cgit v1.2.3 From ca46b941349c0b5ab183320182fc61af28c70c45 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 11 Sep 2021 17:49:03 +0530 Subject: [cookies] Make browser names case insensitive --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index c2d7a74ff..7cabc35ae 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1128,7 +1128,7 @@ def parseOpts(overrideArguments=None): 'You can specify the user profile name or directory using ' '"BROWSER:PROFILE_NAME" or "BROWSER:PROFILE_PATH". ' 'If no profile is given, the most recently accessed one is used'.format( - '|'.join(sorted(SUPPORTED_BROWSERS))))) + ', '.join(sorted(SUPPORTED_BROWSERS))))) filesystem.add_option( '--no-cookies-from-browser', action='store_const', const=None, dest='cookiesfrombrowser', -- cgit v1.2.3 From d21bba78533ca53dac179e4a4f1cfaa9ba241b2f Mon Sep 17 00:00:00 2001 From: pukkandan Date: Tue, 14 Sep 2021 12:03:26 +0530 Subject: [options] Strip spaces in list-like switches --- yt_dlp/options.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 7cabc35ae..2ff0fbfc1 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -116,19 +116,19 @@ def parseOpts(overrideArguments=None): return ''.join(opts) - def _list_from_options_callback(option, opt_str, value, parser, append=True, delim=','): + def _list_from_options_callback(option, opt_str, value, parser, append=True, delim=',', process=str.strip): # 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) + value = [process(value)] if delim is None else list(map(process, value.split(delim))) setattr( parser.values, option.dest, current + value if append is True else value + current) def _set_from_options_callback( - option, opt_str, value, parser, - delim=',', allowed_values=None, process=str.lower, aliases={}): + option, opt_str, value, parser, delim=',', allowed_values=None, aliases={}, + process=lambda x: x.lower().strip()): current = getattr(parser.values, option.dest) - values = [process(value)] if delim is None else process(value).split(delim)[::-1] + values = [process(value)] if delim is None else list(map(process, value.split(delim)[::-1])) while values: actual_val = val = values.pop() if val == 'all': @@ -275,8 +275,7 @@ def parseOpts(overrideArguments=None): 'multistreams', 'no-live-chat', 'playlist-index', 'list-formats', 'no-direct-merge', 'no-youtube-channel-redirect', 'no-youtube-unavailable-videos', 'no-attach-info-json', 'embed-thumbnail-atomicparsley', 'seperate-video-versions', 'no-clean-infojson', 'no-keep-subs', - }, - 'aliases': { + }, 'aliases': { 'youtube-dl': ['-multistreams', 'all'], 'youtube-dlc': ['-no-youtube-channel-redirect', '-no-live-chat', 'all'], } -- cgit v1.2.3 From 0001fcb586c3ab297cd48c77ddd6f5d40546dac4 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 16 Sep 2021 00:51:40 +0530 Subject: Add option `--netrc-location` Closes #792, #963 --- yt_dlp/options.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 2ff0fbfc1..099b151c6 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -478,6 +478,10 @@ def parseOpts(overrideArguments=None): '-n', '--netrc', action='store_true', dest='usenetrc', default=False, help='Use .netrc authentication data') + authentication.add_option( + '--netrc-location', + dest='netrc_location', metavar='PATH', + help='Location of .netrc authentication data; either the path or its containing directory. Defaults to ~/.netrc') authentication.add_option( '--video-password', dest='videopassword', metavar='PASSWORD', -- cgit v1.2.3 From 7303f84abeeb283b15806f7ef47bfe694f55b99c Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 13 Sep 2021 08:22:11 +0530 Subject: [options] Fix `--no-config` and refactor reading of config files Closes #912, #914 --- yt_dlp/options.py | 79 ++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 45 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 099b151c6..74c810471 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -235,7 +235,7 @@ def parseOpts(overrideArguments=None): help='Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for the search term "large apple". Use the value "auto" to let yt-dlp guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching') general.add_option( '--ignore-config', '--no-config', - action='store_true', + action='store_true', dest='ignoreconfig', help=( 'Disable loading any configuration files except the one provided by --config-location. ' 'When given inside a configuration file, no further configuration files are loaded. ' @@ -1536,57 +1536,47 @@ def parseOpts(overrideArguments=None): 'command-line': compat_conf(sys.argv[1:]), 'custom': [], 'home': [], 'portable': [], 'user': [], 'system': []} paths = {'command-line': False} - opts, args = parser.parse_args(configs['command-line']) + + def read_options(name, path, user=False): + ''' loads config files and returns ignoreconfig ''' + # Multiple package names can be given here + # Eg: ('yt-dlp', 'youtube-dlc', 'youtube-dl') will look for + # the configuration file of any of these three packages + for package in ('yt-dlp',): + if user: + config, current_path = _readUserConf(package, default=None) + else: + current_path = os.path.join(path, '%s.conf' % package) + config = _readOptions(current_path, default=None) + if config is not None: + configs[name], paths[name] = config, current_path + return parser.parse_args(config)[0].ignoreconfig + return False def get_configs(): - if '--config-location' in configs['command-line']: + opts, _ = parser.parse_args(configs['command-line']) + if opts.config_location is not None: location = compat_expanduser(opts.config_location) if os.path.isdir(location): location = os.path.join(location, 'yt-dlp.conf') if not os.path.exists(location): parser.error('config-location %s does not exist.' % location) - configs['custom'] = _readOptions(location, default=None) - if configs['custom'] is None: - configs['custom'] = [] - else: - paths['custom'] = location - if '--ignore-config' in configs['command-line']: + config = _readOptions(location, default=None) + if config: + configs['custom'], paths['config'] = config, location + + if opts.ignoreconfig: return - if '--ignore-config' in configs['custom']: + if parser.parse_args(configs['custom'])[0].ignoreconfig: return - - def read_options(path, user=False): - # Multiple package names can be given here - # Eg: ('yt-dlp', 'youtube-dlc', 'youtube-dl') will look for - # the configuration file of any of these three packages - for package in ('yt-dlp',): - if user: - config, current_path = _readUserConf(package, default=None) - else: - current_path = os.path.join(path, '%s.conf' % package) - config = _readOptions(current_path, default=None) - if config is not None: - return config, current_path - return [], None - - configs['portable'], paths['portable'] = read_options(get_executable_path()) - if '--ignore-config' in configs['portable']: + if read_options('portable', get_executable_path()): return - - def get_home_path(): - opts = parser.parse_args(configs['portable'] + configs['custom'] + configs['command-line'])[0] - return expand_path(opts.paths.get('home', '')).strip() - - configs['home'], paths['home'] = read_options(get_home_path()) - if '--ignore-config' in configs['home']: + opts, _ = parser.parse_args(configs['portable'] + configs['custom'] + configs['command-line']) + if read_options('home', expand_path(opts.paths.get('home', '')).strip()): return - - configs['system'], paths['system'] = read_options('/etc') - if '--ignore-config' in configs['system']: + if read_options('system', '/etc'): return - - configs['user'], paths['user'] = read_options('', True) - if '--ignore-config' in configs['user']: + if read_options('user', None, user=True): configs['system'], paths['system'] = [], None get_configs() @@ -1595,10 +1585,9 @@ def parseOpts(overrideArguments=None): if opts.verbose: for label in ('System', 'User', 'Portable', 'Home', 'Custom', 'Command-line'): key = label.lower() - if paths.get(key) is None: - continue - if paths[key]: - write_string('[debug] %s config file: %s\n' % (label, paths[key])) - write_string('[debug] %s config: %s\n' % (label, repr(_hide_login_info(configs[key])))) + if paths.get(key): + write_string(f'[debug] {label} config file: {paths[key]}\n') + if paths.get(key) is not None: + write_string(f'[debug] {label} config: {_hide_login_info(configs[key])!r}\n') return parser, opts, args -- cgit v1.2.3 From 1f8471e22cdb5181aa19b0c63523ad96891ea2dd Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 24 Sep 2021 05:10:33 +0530 Subject: Ignore empty entries in `_list_from_options_callback` --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 74c810471..80b3df74f 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -119,7 +119,7 @@ def parseOpts(overrideArguments=None): def _list_from_options_callback(option, opt_str, value, parser, append=True, delim=',', process=str.strip): # append can be True, False or -1 (prepend) current = getattr(parser.values, option.dest) if append else [] - value = [process(value)] if delim is None else list(map(process, value.split(delim))) + value = list(filter(None, [process(value)] if delim is None else map(process, value.split(delim)))) setattr( parser.values, option.dest, current + value if append is True else value + current) -- cgit v1.2.3 From b19404591a8ad4d0c7e962931ea809221e3f0b8e Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 24 Sep 2021 05:51:54 +0530 Subject: Separate the options `--ignore-errors` and `--no-abort-on-error` In youtube-dl, `-i` ignores both download and post-processing error, and treats the download as successful even if the post-processor fails. yt-dlp used to skip the entire video on either error and there was no option to ignore the post-processing errors like youtube-dl does. By splitting the option into two, now either just the download errors (--no-abort-on-error, default on CLI) or all errors (--ignore-errors) can be ignored as per the users' needs Closes #893 --- yt_dlp/options.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 80b3df74f..57e25a518 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -206,9 +206,13 @@ def parseOpts(overrideArguments=None): action='store_true', dest='update_self', 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=None, - help='Continue on download errors, for example to skip unavailable videos in a playlist (default) (Alias: --no-abort-on-error)') + '-i', '--ignore-errors', + action='store_true', dest='ignoreerrors', + help='Ignore download and postprocessing errors. The download will be considered successfull even if the postprocessing fails') + general.add_option( + '--no-abort-on-error', + action='store_const', dest='ignoreerrors', const='only_download', + help='Continue with next video on download errors; e.g. to skip unavailable videos in a playlist (default)') general.add_option( '--abort-on-error', '--no-ignore-errors', action='store_false', dest='ignoreerrors', -- cgit v1.2.3 From 3ae5e7977439193519c0ea62eba3aa3111c5571b Mon Sep 17 00:00:00 2001 From: pukkandan Date: Thu, 30 Sep 2021 02:23:33 +0530 Subject: [postprocessor] Add plugin support Adds option `--use-postprocessor` to enable them --- yt_dlp/options.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 57e25a518..daf4c0041 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -17,6 +17,7 @@ from .utils import ( get_executable_path, OUTTMPL_TYPES, preferredencoding, + remove_end, write_string, ) from .cookies import SUPPORTED_BROWSERS @@ -1389,6 +1390,25 @@ def parseOpts(overrideArguments=None): '--no-force-keyframes-at-cuts', action='store_false', dest='force_keyframes_at_cuts', help='Do not force keyframes around the chapters when cutting/splitting (default)') + _postprocessor_opts_parser = lambda key, val='': ( + *(item.split('=', 1) for item in (val.split(';') if val else [])), + ('key', remove_end(key, 'PP'))) + postproc.add_option( + '--use-postprocessor', + metavar='NAME[:ARGS]', dest='add_postprocessors', default=[], type='str', + action='callback', callback=_list_from_options_callback, + callback_kwargs={ + 'delim': None, + 'process': lambda val: dict(_postprocessor_opts_parser(*val.split(':', 1))) + }, help=( + 'The (case sensitive) name of plugin postprocessors to be enabled, ' + 'and (optionally) arguments to be passed to it, seperated by a colon ":". ' + 'ARGS are a semicolon ";" delimited list of NAME=VALUE. ' + 'The "when" argument determines when the postprocessor is invoked. ' + 'It can be one of "pre_process" (after extraction), ' + '"before_dl" (before video download), "post_process" (after video download; default) ' + 'or "after_move" (after moving file to their final locations). ' + 'This option can be used multiple times to add different postprocessors')) sponsorblock = optparse.OptionGroup(parser, 'SponsorBlock Options', description=( 'Make chapter entries for, or remove various segments (sponsor, introductions, etc.) ' -- cgit v1.2.3 From e6f21b3d925ea708955c60c400a31fc2e0e36ac0 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Fri, 17 Sep 2021 23:53:55 +0530 Subject: [docs,cleanup] Some minor refactoring and improve docs --- yt_dlp/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index daf4c0041..be43f37ee 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -261,7 +261,7 @@ def parseOpts(overrideArguments=None): general.add_option( '--mark-watched', action='store_true', dest='mark_watched', default=False, - help='Mark videos watched (YouTube only)') + help='Mark videos watched (even with --simulate). Currently only supported for YouTube') general.add_option( '--no-mark-watched', action='store_false', dest='mark_watched', @@ -768,7 +768,7 @@ def parseOpts(overrideArguments=None): dest='encoding', metavar='ENCODING', help='Force the specified encoding (experimental)') workarounds.add_option( - '--no-check-certificate', + '--no-check-certificates', action='store_true', dest='no_check_certificate', default=False, help='Suppress HTTPS certificate validation') workarounds.add_option( -- cgit v1.2.3 From 819e05319baff2d896df026f1ef905e1f21be942 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 9 Oct 2021 00:41:59 +0530 Subject: Improved progress reporting (See desc) (#1125) * Separate `--console-title` and `--no-progress` * Add option `--progress` to show progress-bar even in quiet mode * Fix and refactor `minicurses` * Use `minicurses` for all progress reporting * Standardize use of terminal sequences and enable color support for windows 10 * Add option `--progress-template` to customize progress-bar and console-title * Add postprocessor hooks and progress reporting Closes: #906, #901, #1085, #1170 --- yt_dlp/options.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index be43f37ee..4652e8c58 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -910,12 +910,30 @@ def parseOpts(overrideArguments=None): help='Output progress bar as new lines') verbosity.add_option( '--no-progress', - action='store_true', dest='noprogress', default=False, + action='store_true', dest='noprogress', default=None, help='Do not print progress bar') + verbosity.add_option( + '--progress', + action='store_false', dest='noprogress', + help='Show progress bar, even if in quiet mode') verbosity.add_option( '--console-title', action='store_true', dest='consoletitle', default=False, help='Display progress in console titlebar') + verbosity.add_option( + '--progress-template', + metavar='[TYPES:]TEMPLATE', dest='progress_template', default={}, type='str', + action='callback', callback=_dict_from_options_callback, + callback_kwargs={ + 'allowed_keys': '(download|postprocess)(-title)?', + 'default_key': 'download' + }, help=( + 'Template for progress outputs, optionally prefixed with one of "download:" (default), ' + '"download-title:" (the console title), "postprocess:", or "postprocess-title:". ' + 'The video\'s fields are accessible under the "info" key and ' + 'the progress attributes are accessible under "progress" key. Eg: ' + # TODO: Document the fields inside "progress" + '--console-title --progress-template "download-title:%(info.id)s-%(progress.eta)s"')) verbosity.add_option( '-v', '--verbose', action='store_true', dest='verbose', default=False, -- cgit v1.2.3 From b5ae35ee6d3f913898770b8c74ee5f5e5cc33560 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Sat, 9 Oct 2021 05:53:15 +0530 Subject: [cleanup] Misc cleanup --- yt_dlp/options.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 4652e8c58..f45c548f2 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -971,9 +971,6 @@ def parseOpts(overrideArguments=None): dest='batchfile', metavar='FILE', help="File containing URLs to download ('-' for stdin), one URL per line. " "Lines starting with '#', ';' or ']' are considered as comments and ignored") - filesystem.add_option( - '--id', default=False, - action='store_true', dest='useid', help=optparse.SUPPRESS_HELP) filesystem.add_option( '-P', '--paths', metavar='[TYPES:]PATH', dest='paths', default={}, type='str', @@ -1029,18 +1026,6 @@ def parseOpts(overrideArguments=None): '--trim-filenames', '--trim-file-names', metavar='LENGTH', dest='trim_file_name', default=0, type=int, help='Limit the filename length (excluding extension) to the specified number of characters') - filesystem.add_option( - '--auto-number', - action='store_true', dest='autonumber', default=False, - help=optparse.SUPPRESS_HELP) - filesystem.add_option( - '--title', - action='store_true', dest='usetitle', default=False, - help=optparse.SUPPRESS_HELP) - filesystem.add_option( - '--literal', default=False, - action='store_true', dest='usetitle', - help=optparse.SUPPRESS_HELP) filesystem.add_option( '-w', '--no-overwrites', action='store_false', dest='overwrites', default=None, @@ -1625,7 +1610,7 @@ def parseOpts(overrideArguments=None): argv = configs['system'] + configs['user'] + configs['home'] + configs['portable'] + configs['custom'] + configs['command-line'] opts, args = parser.parse_args(argv) if opts.verbose: - for label in ('System', 'User', 'Portable', 'Home', 'Custom', 'Command-line'): + for label in ('Command-line', 'Custom', 'Portable', 'Home', 'User', 'System'): key = label.lower() if paths.get(key): write_string(f'[debug] {label} config file: {paths[key]}\n') -- cgit v1.2.3 From 7b38649845c1516e4ab4e29b6bb84b2302269663 Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 11 Oct 2021 20:21:04 +0530 Subject: Fix verbose head not showing custom configs --- yt_dlp/options.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index f45c548f2..d2dc7687b 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1590,7 +1590,7 @@ def parseOpts(overrideArguments=None): parser.error('config-location %s does not exist.' % location) config = _readOptions(location, default=None) if config: - configs['custom'], paths['config'] = config, location + configs['custom'], paths['custom'] = config, location if opts.ignoreconfig: return -- cgit v1.2.3 From 2d9ec70423121dbf280475769690f19b0034ee8b Mon Sep 17 00:00:00 2001 From: pukkandan Date: Mon, 18 Oct 2021 16:03:05 +0530 Subject: [ModifyChapters] Allow removing sections by timestamp Eg: --remove-chapters "*10:15-15:00". The `*` prefix is used so as to avoid any conflicts with other valid regex --- yt_dlp/options.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'yt_dlp/options.py') diff --git a/yt_dlp/options.py b/yt_dlp/options.py index d2dc7687b..1c99e7e7c 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1378,7 +1378,11 @@ def parseOpts(overrideArguments=None): postproc.add_option( '--remove-chapters', metavar='REGEX', dest='remove_chapters', action='append', - help='Remove chapters whose title matches the given regular expression. This option can be used multiple times') + help=( + 'Remove chapters whose title matches the given regular expression. ' + 'Time ranges prefixed by a "*" can also be used in place of chapters to remove the specified range. ' + 'Eg: --remove-chapters "*10:15-15:00" --remove-chapters "intro". ' + 'This option can be used multiple times')) postproc.add_option( '--no-remove-chapters', dest='remove_chapters', action='store_const', const=None, help='Do not remove any chapters from the file (default)') -- cgit v1.2.3