mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-03-05 05:39:42 +00:00
[cleanup] Misc (#11216)
- Add Python 3.13 to CI, finalize 3.13 support - Remove Python 3.8 from CI in preparation for removing 3.8 support - Document that PyPy3.8 and PyPy3.9 are no longer supported - Usual documentation fixes and code cleanup Closes #8248, Closes #11146, Closes #11149, Closes #11211 Authored by: Grub4K, grqz, DTrombett, KarboniteKream, bashonly, mikkovedru, seproDev Co-authored-by: N/Ame <173015200+grqz@users.noreply.github.com> Co-authored-by: DTrombett <d@trombett.org> Co-authored-by: =?UTF-8?q?Klemen=20Ko=C5=A1ir?= <klemen.kosir@kream.io> Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com> Co-authored-by: Mikko Vedru <mikko.vedru@gmail.com> Co-authored-by: sepro <sepro@sepr0.com>
This commit is contained in:
@@ -154,7 +154,6 @@ from .utils import (
|
||||
try_get,
|
||||
url_basename,
|
||||
variadic,
|
||||
version_tuple,
|
||||
windows_enable_vt_mode,
|
||||
write_json_file,
|
||||
write_string,
|
||||
@@ -251,7 +250,7 @@ class YoutubeDL:
|
||||
format_sort_force: Force the given format_sort. see "Sorting Formats"
|
||||
for more details.
|
||||
prefer_free_formats: Whether to prefer video formats with free containers
|
||||
over non-free ones of same quality.
|
||||
over non-free ones of the same quality.
|
||||
allow_multiple_video_streams: Allow multiple video streams to be merged
|
||||
into a single file
|
||||
allow_multiple_audio_streams: Allow multiple audio streams to be merged
|
||||
@@ -285,7 +284,7 @@ class YoutubeDL:
|
||||
rejecttitle: Reject downloads for matching titles.
|
||||
logger: Log messages to a logging.Logger instance.
|
||||
logtostderr: Print everything to stderr instead of stdout.
|
||||
consoletitle: Display progress in console window's titlebar.
|
||||
consoletitle: Display progress in the console window's titlebar.
|
||||
writedescription: Write the video description to a .description file
|
||||
writeinfojson: Write the video description to a .info.json file
|
||||
clean_infojson: Remove internal metadata from the infojson
|
||||
@@ -513,7 +512,7 @@ class YoutubeDL:
|
||||
The following options are used by the extractors:
|
||||
extractor_retries: Number of times to retry for known errors (default: 3)
|
||||
dynamic_mpd: Whether to process dynamic DASH manifests (default: True)
|
||||
hls_split_discontinuity: Split HLS playlists to different formats at
|
||||
hls_split_discontinuity: Split HLS playlists into different formats at
|
||||
discontinuities such as ad breaks (default: False)
|
||||
extractor_args: A dictionary of arguments to be passed to the extractors.
|
||||
See "EXTRACTOR ARGUMENTS" for details.
|
||||
@@ -553,7 +552,7 @@ class YoutubeDL:
|
||||
include_ads: - Doesn't work
|
||||
Download ads as well
|
||||
call_home: - Not implemented
|
||||
Boolean, true iff we are allowed to contact the
|
||||
Boolean, true if we are allowed to contact the
|
||||
yt-dlp servers for debugging.
|
||||
post_hooks: - Register a custom postprocessor
|
||||
A list of functions that get called as the final step
|
||||
@@ -4089,17 +4088,6 @@ class YoutubeDL:
|
||||
if plugin_dirs:
|
||||
write_debug(f'Plugin directories: {plugin_dirs}')
|
||||
|
||||
# Not implemented
|
||||
if False and self.params.get('call_home'):
|
||||
ipaddr = self.urlopen('https://yt-dl.org/ip').read().decode()
|
||||
write_debug(f'Public IP address: {ipaddr}')
|
||||
latest_version = self.urlopen(
|
||||
'https://yt-dl.org/latest/version').read().decode()
|
||||
if version_tuple(latest_version) > version_tuple(__version__):
|
||||
self.report_warning(
|
||||
f'You are using an outdated version (newest version: {latest_version})! '
|
||||
'See https://yt-dl.org/update if you need help updating.')
|
||||
|
||||
@functools.cached_property
|
||||
def proxies(self):
|
||||
"""Global proxy configuration"""
|
||||
|
||||
@@ -333,7 +333,7 @@ class InfoExtractor:
|
||||
like_count: Number of positive ratings of the video
|
||||
dislike_count: Number of negative ratings of the video
|
||||
repost_count: Number of reposts of the video
|
||||
average_rating: Average rating give by users, the scale used depends on the webpage
|
||||
average_rating: Average rating given by users, the scale used depends on the webpage
|
||||
comment_count: Number of comments on the video
|
||||
comments: A list of comments, each with one or more of the following
|
||||
properties (all but one of text or html optional):
|
||||
@@ -520,7 +520,7 @@ class InfoExtractor:
|
||||
or _extract_from_webpage as necessary. While these are normally classmethods,
|
||||
_extract_from_webpage is allowed to be an instance method.
|
||||
|
||||
_extract_from_webpage may raise self.StopExtraction() to stop further
|
||||
_extract_from_webpage may raise self.StopExtraction to stop further
|
||||
processing of the webpage and obtain exclusive rights to it. This is useful
|
||||
when the extractor cannot reliably be matched using just the URL,
|
||||
e.g. invidious/peertube instances
|
||||
|
||||
@@ -371,7 +371,7 @@ class NexxIE(InfoExtractor):
|
||||
# not all videos work via arc, e.g. nexx:741:1269984
|
||||
if not video:
|
||||
# Reverse engineered from JS code (see getDeviceID function)
|
||||
device_id = f'{random.randint(1, 4)}:{int(time.time())}:{random.randint(1e4, 99999)}{random.randint(1, 9)}'
|
||||
device_id = f'{random.randint(1, 4)}:{int(time.time())}:{random.randint(10000, 99999)}{random.randint(1, 9)}'
|
||||
|
||||
result = self._call_api(domain_id, 'session/init', video_id, data={
|
||||
'nxp_devh': device_id,
|
||||
|
||||
@@ -236,7 +236,7 @@ class TubeTuGrazSeriesIE(TubeTuGrazBaseIE):
|
||||
},
|
||||
},
|
||||
],
|
||||
'min_playlist_count': 4,
|
||||
'playlist_mincount': 4,
|
||||
}]
|
||||
|
||||
def _real_extract(self, url):
|
||||
|
||||
@@ -73,7 +73,7 @@ class UstreamIE(InfoExtractor):
|
||||
def num_to_hex(n):
|
||||
return hex(n)[2:]
|
||||
|
||||
rnd = random.randrange
|
||||
rnd = lambda x: random.randrange(int(x))
|
||||
|
||||
if not extra_note:
|
||||
extra_note = ''
|
||||
|
||||
@@ -8,7 +8,8 @@ from ..utils import (
|
||||
int_or_none,
|
||||
parse_duration,
|
||||
qualities,
|
||||
try_get,
|
||||
remove_start,
|
||||
strip_or_none,
|
||||
)
|
||||
|
||||
|
||||
@@ -108,7 +109,7 @@ class VeohIE(InfoExtractor):
|
||||
|
||||
categories = metadata.get('categoryPath')
|
||||
if not categories:
|
||||
category = try_get(video, lambda x: x['category'].strip().removeprefix('category_'))
|
||||
category = remove_start(strip_or_none(video.get('category')), 'category_')
|
||||
categories = [category] if category else None
|
||||
tags = video.get('tags')
|
||||
|
||||
|
||||
@@ -7792,9 +7792,9 @@ class YoutubeTruncatedURLIE(YoutubeBaseInfoExtractor):
|
||||
raise ExtractorError(
|
||||
'Did you forget to quote the URL? Remember that & is a meta '
|
||||
'character in most shells, so you want to put the URL in quotes, '
|
||||
'like youtube-dl '
|
||||
'like yt-dlp '
|
||||
'"https://www.youtube.com/watch?feature=foo&v=BaW_jenozKc" '
|
||||
' or simply youtube-dl BaW_jenozKc .',
|
||||
' or simply yt-dlp BaW_jenozKc .',
|
||||
expected=True)
|
||||
|
||||
|
||||
|
||||
@@ -631,13 +631,13 @@ def create_parser():
|
||||
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'))
|
||||
'The date formats accepted are 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'))
|
||||
'The date formats accepted are the same as --date'))
|
||||
selection.add_option(
|
||||
'--min-views',
|
||||
metavar='COUNT', dest='min_views', default=None, type=int,
|
||||
@@ -833,7 +833,7 @@ def create_parser():
|
||||
'--prefer-free-formats',
|
||||
action='store_true', dest='prefer_free_formats', default=False,
|
||||
help=(
|
||||
'Prefer video formats with free containers over non-free ones of same quality. '
|
||||
'Prefer video formats with free containers over non-free ones of the same quality. '
|
||||
'Use with "-S ext" to strictly prefer free containers irrespective of quality'))
|
||||
video_format.add_option(
|
||||
'--no-prefer-free-formats',
|
||||
@@ -907,13 +907,14 @@ def create_parser():
|
||||
subtitles.add_option(
|
||||
'--sub-format',
|
||||
action='store', dest='subtitlesformat', metavar='FORMAT', default='best',
|
||||
help='Subtitle format; accepts formats preference, e.g. "srt" or "ass/srt/best"')
|
||||
help='Subtitle format; accepts formats preference separated by "/", e.g. "srt" or "ass/srt/best"')
|
||||
subtitles.add_option(
|
||||
'--sub-langs', '--srt-langs',
|
||||
action='callback', dest='subtitleslangs', metavar='LANGS', type='str',
|
||||
default=[], callback=_list_from_options_callback,
|
||||
help=(
|
||||
'Languages of the subtitles to download (can be regex) or "all" separated by commas, e.g. --sub-langs "en.*,ja". '
|
||||
'Languages of the subtitles to download (can be regex) or "all" separated by commas, e.g. --sub-langs "en.*,ja" '
|
||||
'(where "en.*" is a regex pattern that matches "en" followed by 0 or more of any character). '
|
||||
'You can prefix the language code with a "-" to exclude it from the requested languages, e.g. --sub-langs all,-live_chat. '
|
||||
'Use --list-subs for a list of available language tags'))
|
||||
|
||||
@@ -1182,7 +1183,7 @@ def create_parser():
|
||||
'--print-to-file',
|
||||
metavar='[WHEN:]TEMPLATE FILE', dest='print_to_file', nargs=2, **when_prefix('video'),
|
||||
help=(
|
||||
'Append given template to the file. The values of WHEN and TEMPLATE are same as that of --print. '
|
||||
'Append given template to the file. The values of WHEN and TEMPLATE are the same as that of --print. '
|
||||
'FILE uses the same syntax as the output template. This option can be used multiple times'))
|
||||
verbosity.add_option(
|
||||
'-g', '--get-url',
|
||||
@@ -1226,7 +1227,7 @@ def create_parser():
|
||||
'-J', '--dump-single-json',
|
||||
action='store_true', dest='dump_single_json', default=False,
|
||||
help=(
|
||||
'Quiet, but print JSON information for each url or infojson passed. Simulate unless --no-simulate is used. '
|
||||
'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',
|
||||
@@ -1570,7 +1571,7 @@ def create_parser():
|
||||
help=(
|
||||
'Remux the video into another container if necessary '
|
||||
f'(currently supported: {", ".join(FFmpegVideoRemuxerPP.SUPPORTED_EXTS)}). '
|
||||
'If target container does not support the video/audio codec, remuxing will fail. You can specify multiple rules; '
|
||||
'If the target container does not support the video/audio codec, remuxing will fail. You can specify multiple rules; '
|
||||
'e.g. "aac>m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 and anything else to mkv'))
|
||||
postproc.add_option(
|
||||
'--recode-video',
|
||||
@@ -1676,7 +1677,7 @@ def create_parser():
|
||||
postproc.add_option(
|
||||
'--xattrs', '--xattr',
|
||||
action='store_true', dest='xattrs', default=False,
|
||||
help='Write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
|
||||
help='Write metadata to the video file\'s xattrs (using Dublin Core and XDG standards)')
|
||||
postproc.add_option(
|
||||
'--concat-playlist',
|
||||
metavar='POLICY', dest='concat_playlist', default='multi_video',
|
||||
@@ -1684,7 +1685,7 @@ def create_parser():
|
||||
help=(
|
||||
'Concatenate videos in a playlist. One of "never", "always", or '
|
||||
'"multi_video" (default; only when the videos form a single show). '
|
||||
'All the video files must have same codecs and number of streams to be concatable. '
|
||||
'All the video files must have the same codecs and number of streams to be concatenable. '
|
||||
'The "pl_video:" prefix can be used with "--paths" and "--output" to '
|
||||
'set the output filename for the concatenated files. See "OUTPUT TEMPLATE" for details'))
|
||||
postproc.add_option(
|
||||
@@ -1694,8 +1695,8 @@ def create_parser():
|
||||
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), '
|
||||
'force (try fixing even if file already exists)'))
|
||||
'detect_or_warn (the default; fix the file if we can, warn otherwise), '
|
||||
'force (try fixing even if the file already exists)'))
|
||||
postproc.add_option(
|
||||
'--prefer-avconv', '--no-prefer-ffmpeg',
|
||||
action='store_false', dest='prefer_ffmpeg',
|
||||
@@ -1714,7 +1715,7 @@ def create_parser():
|
||||
help=(
|
||||
'Execute a command, optionally prefixed with when to execute it, separated by a ":". '
|
||||
'Supported values of "WHEN" are the same as that of --use-postprocessor (default: after_move). '
|
||||
'Same syntax as the output template can be used to pass any field as arguments to the command. '
|
||||
'The same syntax as the output template can be used to pass any field as arguments to the command. '
|
||||
'If no fields are passed, %(filepath,_filename|)q is appended to the end of the command. '
|
||||
'This option can be used multiple times'))
|
||||
postproc.add_option(
|
||||
@@ -1785,14 +1786,14 @@ def create_parser():
|
||||
'delim': None,
|
||||
'process': lambda val: dict(_postprocessor_opts_parser(*val.split(':', 1))),
|
||||
}, help=(
|
||||
'The (case sensitive) name of plugin postprocessors to be enabled, '
|
||||
'The (case-sensitive) name of plugin postprocessors to be enabled, '
|
||||
'and (optionally) arguments to be passed to it, separated 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 video extraction), "after_filter" (after video passes filter), '
|
||||
'"video" (after --format; before --print/--output), "before_dl" (before each video download), '
|
||||
'"post_process" (after each video download; default), '
|
||||
'"after_move" (after moving video file to its final locations), '
|
||||
'"after_move" (after moving the video file to its final location), '
|
||||
'"after_video" (after downloading and processing all formats of a video), '
|
||||
'or "playlist" (at end of playlist). '
|
||||
'This option can be used multiple times to add different postprocessors'))
|
||||
@@ -1809,7 +1810,7 @@ def create_parser():
|
||||
}, help=(
|
||||
'SponsorBlock categories to create chapters for, separated by commas. '
|
||||
f'Available categories are {", ".join(SponsorBlockPP.CATEGORIES.keys())}, all and default (=all). '
|
||||
'You can prefix the category with a "-" to exclude it. See [1] for description of the categories. '
|
||||
'You can prefix the category with a "-" to exclude it. See [1] for descriptions of the categories. '
|
||||
'E.g. --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories'))
|
||||
sponsorblock.add_option(
|
||||
'--sponsorblock-remove', metavar='CATS',
|
||||
@@ -1895,7 +1896,7 @@ def create_parser():
|
||||
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)')
|
||||
help='Do not split HLS playlists into different formats at discontinuities such as ad breaks (default)')
|
||||
_extractor_arg_parser = lambda key, vals='': (key.strip().lower().replace('-', '_'), [
|
||||
val.replace(r'\,', ',').strip() for val in re.split(r'(?<!\\),', vals)])
|
||||
extractor.add_option(
|
||||
|
||||
@@ -55,7 +55,7 @@ def traverse_obj(
|
||||
The keys in the path can be one of:
|
||||
- `None`: Return the current object.
|
||||
- `set`: Requires the only item in the set to be a type or function,
|
||||
like `{type}`/`{type, type, ...}/`{func}`. If a `type`, return only
|
||||
like `{type}`/`{type, type, ...}`/`{func}`. If a `type`, return only
|
||||
values of this type. If a function, returns `func(obj)`.
|
||||
- `str`/`int`: Return `obj[key]`. For `re.Match`, return `obj.group(key)`.
|
||||
- `slice`: Branch out and return all values in `obj[key]`.
|
||||
@@ -75,7 +75,7 @@ def traverse_obj(
|
||||
|
||||
`tuple`, `list`, and `dict` all support nested paths and branches.
|
||||
|
||||
@params paths Paths which to traverse by.
|
||||
@params paths Paths by which to traverse.
|
||||
@param default Value to return if the paths do not match.
|
||||
If the last key in the path is a `dict`, it will apply to each value inside
|
||||
the dict instead, depth first. Try to avoid if using nested `dict` keys.
|
||||
|
||||
Reference in New Issue
Block a user