update yt-dlp and fix some bugs with TPE2. Fixes #3

This commit is contained in:
2026-01-31 11:10:33 +00:00
parent 4aa0c5b6d9
commit 879a318e54
6 changed files with 174 additions and 91 deletions

File diff suppressed because one or more lines are too long

View File

@@ -247,7 +247,8 @@ Python versions 3.10+ (CPython) and 3.11+ (PyPy) are supported. Other
versions and implementations may or may not work correctly. versions and implementations may or may not work correctly.
While all the other dependencies are optional, ffmpeg, ffprobe, While all the other dependencies are optional, ffmpeg, ffprobe,
yt-dlp-ejs and a JavaScript runtime are highly recommended yt-dlp-ejs and a supported JavaScript runtime/engine are highly
recommended
Strongly recommended Strongly recommended
@@ -264,11 +265,11 @@ Strongly recommended
Important: What you need is ffmpeg binary, NOT the Python package of Important: What you need is ffmpeg binary, NOT the Python package of
the same name the same name
- yt-dlp-ejs - Required for deciphering YouTube n/sig values. Licensed - yt-dlp-ejs - Required for full YouTube support. Licensed under
under Unlicense, bundles MIT and ISC components. Unlicense, bundles MIT and ISC components.
A JavaScript runtime like deno (recommended), node.js, bun, or A JavaScript runtime/engine like deno (recommended), node.js, bun,
QuickJS is also required to run yt-dlp-ejs. See the wiki. or QuickJS is also required to run yt-dlp-ejs. See the wiki.
Networking Networking
@@ -289,7 +290,7 @@ may be required for some sites that employ TLS fingerprinting.
- curl_cffi (recommended) - Python binding for curl-impersonate. - curl_cffi (recommended) - Python binding for curl-impersonate.
Provides impersonation targets for Chrome, Edge and Safari. Licensed Provides impersonation targets for Chrome, Edge and Safari. Licensed
under MIT under MIT
- Can be installed with the curl-cffi group, e.g. - Can be installed with the curl-cffi extra, e.g.
pip install "yt-dlp[default,curl-cffi]" pip install "yt-dlp[default,curl-cffi]"
- Currently included in most builds except yt-dlp (Unix zipimport - Currently included in most builds except yt-dlp (Unix zipimport
binary), yt-dlp_x86 (Windows 32-bit) and binary), yt-dlp_x86 (Windows 32-bit) and
@@ -343,7 +344,7 @@ will be built for the same CPU architecture as the Python used.
You can run the following commands: You can run the following commands:
python devscripts/install_deps.py --include-group pyinstaller python devscripts/install_deps.py --include-extra pyinstaller
python devscripts/make_lazy_extractors.py python devscripts/make_lazy_extractors.py
python -m bundle.pyinstaller python -m bundle.pyinstaller
@@ -580,7 +581,7 @@ Geo-restriction:
Video Selection: Video Selection:
-I, --playlist-items ITEM_SPEC Comma separated playlist_index of the items -I, --playlist-items ITEM_SPEC Comma-separated playlist_index of the items
to download. You can specify a range using to download. You can specify a range using
"[START]:[STOP][:STEP]". For backward "[START]:[STOP][:STEP]". For backward
compatibility, START-STOP is also supported. compatibility, START-STOP is also supported.
@@ -962,6 +963,8 @@ Video Format Options:
for more details for more details
-S, --format-sort SORTORDER Sort the formats by the fields given, see -S, --format-sort SORTORDER Sort the formats by the fields given, see
"Sorting Formats" for more details "Sorting Formats" for more details
--format-sort-reset Disregard previous user specified sort order
and reset to the default
--format-sort-force Force user specified sort order to have --format-sort-force Force user specified sort order to have
precedence over all fields, see "Sorting precedence over all fields, see "Sorting
Formats" for more details (Alias: --S-force) Formats" for more details (Alias: --S-force)
@@ -1481,7 +1484,7 @@ have some special formatting:
7. More Conversions: In addition to the normal format types 7. More Conversions: In addition to the normal format types
diouxXeEfFgGcrs, yt-dlp additionally supports converting to B = diouxXeEfFgGcrs, yt-dlp additionally supports converting to B =
Bytes, j = json (flag # for pretty-printing, + for Unicode), h = Bytes, j = json (flag # for pretty-printing, + for Unicode), h =
HTML escaping, l = a comma separated list (flag # for \n HTML escaping, l = a comma-separated list (flag # for \n
newline-separated), q = a string quoted for the terminal (flag # to newline-separated), q = a string quoted for the terminal (flag # to
split a list into different arguments), D = add Decimal suffixes split a list into different arguments), D = add Decimal suffixes
(e.g. 10M) (flag # to use 1024 as factor), and S = Sanitize as (e.g. 10M) (flag # to use 1024 as factor), and S = Sanitize as
@@ -1562,6 +1565,8 @@ The available fields are:
- comment_count (numeric): Number of comments on the video (For some - comment_count (numeric): Number of comments on the video (For some
extractors, comments are only downloaded at the end, and so this extractors, comments are only downloaded at the end, and so this
field cannot be used) field cannot be used)
- save_count (numeric): Number of times the video has been saved or
bookmarked
- age_limit (numeric): Age restriction for the video (years) - age_limit (numeric): Age restriction for the video (years)
- live_status (string): One of "not_live", "is_live", "is_upcoming", - live_status (string): One of "not_live", "is_live", "is_upcoming",
"was_live", "post_live" (was live, but VOD is not yet processed) "was_live", "post_live" (was live, but VOD is not yet processed)
@@ -2035,6 +2040,15 @@ respects. Most of the time, what you actually want is the video with the
smallest filesize instead. So it is generally better to use smallest filesize instead. So it is generally better to use
-f best -S +size,+br,+res,+fps. -f best -S +size,+br,+res,+fps.
If you use the -S/--format-sort option multiple times, each subsequent
sorting argument will be prepended to the previous one, and only the
highest priority entry of any duplicated field will be preserved. E.g.
-S proto -S res is equivalent to -S res,proto, and
-S res:720,fps -S vcodec,res:1080 is equivalent to
-S vcodec,res:1080,fps. You can use --format-sort-reset to disregard any
previously passed -S/--format-sort arguments and reset to the default
order.
Tip: You can use the -v -F to see how the formats have been sorted Tip: You can use the -v -F to see how the formats have been sorted
(worst to best). (worst to best).
@@ -2223,9 +2237,9 @@ metadata:
composer composer or composers composer composer or composers
genre genre or genres genre genre, genres, categories or tags
album album album album or series
album_artist album_artist or album_artists album_artist album_artist or album_artists
@@ -2252,6 +2266,9 @@ Modifying metadata examples
# Regex example # Regex example
$ yt-dlp --parse-metadata "description:Artist - (?P<artist>.+)" $ yt-dlp --parse-metadata "description:Artist - (?P<artist>.+)"
# Copy the episode field to the title field (with FROM and TO as single fields)
$ yt-dlp --parse-metadata "episode:title"
# Set title as "Series name S01E05" # Set title as "Series name S01E05"
$ yt-dlp --parse-metadata "%(series)s S%(season_number)02dE%(episode_number)02d:%(title)s" $ yt-dlp --parse-metadata "%(series)s S%(season_number)02dE%(episode_number)02d:%(title)s"
@@ -2295,20 +2312,20 @@ youtube
respectively respectively
- player_client: Clients to extract video data from. The currently - player_client: Clients to extract video data from. The currently
available clients are web, web_safari, web_embedded, web_music, available clients are web, web_safari, web_embedded, web_music,
web_creator, mweb, ios, android, android_sdkless, android_vr, tv, web_creator, mweb, ios, ios_downgraded, android, android_vr, tv,
tv_simply, tv_downgraded, and tv_embedded. By default, tv_simply, tv_downgraded, and tv_embedded. By default,
tv,android_sdkless,web is used. If no JavaScript runtime is android_vr,ios_downgraded,web,web_safari is used. If no JavaScript
available, then android_sdkless,web_safari,web is used. If logged-in runtime/engine is available, then android_vr,ios_downgraded is used.
cookies are passed to yt-dlp, then tv_downgraded,web_safari,web is If logged-in cookies are passed to yt-dlp, then
used for free accounts and tv_downgraded,web_creator,web is used for tv_downgraded,web,web_safari is used for free accounts and
premium accounts. The web_music client is added for tv_downgraded,web_creator,web is used for premium accounts. The
music.youtube.com URLs when logged-in cookies are used. The web_music client is added for music.youtube.com URLs when logged-in
web_embedded client is added for age-restricted videos but only cookies are used. The web_embedded client is added for
works if the video is embeddable. The tv_embedded and web_creator age-restricted videos but only works if the video is embeddable. The
clients are added for age-restricted videos if account tv_embedded and web_creator clients are added for age-restricted
age-verification is required. Some clients, such as web and videos if account age-verification is required. Some clients, such
web_music, require a po_token for their formats to be downloadable. as web and web_music, require a po_token for their formats to be
Some clients, such as web_creator, will only work with downloadable. Some clients, such as web_creator, will only work with
authentication. Not all clients support authentication via cookies. authentication. Not all clients support authentication via cookies.
You can use default for the default clients, or you can use all for You can use default for the default clients, or you can use all for
all clients (not recommended). You can prefix a client with - to all clients (not recommended). You can prefix a client with - to
@@ -2338,11 +2355,15 @@ youtube
YouTube's side) YouTube's side)
- max_comments: Limit the amount of comments to gather. - max_comments: Limit the amount of comments to gather.
Comma-separated list of integers representing Comma-separated list of integers representing
max-comments,max-parents,max-replies,max-replies-per-thread. Default max-comments,max-parents,max-replies,max-replies-per-thread,max-depth.
is all,all,all,all Default is all,all,all,all,all
- E.g. all,all,1000,10 will get a maximum of 1000 replies total, - A max-depth value of 1 will discard all replies, regardless of
with up to 10 replies per thread. 1000,all,100 will get a the max-replies or max-replies-per-thread values given
maximum of 1000 comments, with a maximum of 100 replies total - E.g. all,all,1000,10,2 will get a maximum of 1000 replies total,
with up to 10 replies per thread, and only 2 levels of depth
(i.e. top-level comments plus their immediate replies).
1000,all,100 will get a maximum of 1000 comments, with a maximum
of 100 replies total
- formats: Change the types of formats to return. dashy (convert HTTP - formats: Change the types of formats to return. dashy (convert HTTP
to DASH), duplicate (identical content but different URLs or to DASH), duplicate (identical content but different URLs or
protocol; includes dashy), incomplete (cannot be downloaded protocol; includes dashy), incomplete (cannot be downloaded
@@ -2363,7 +2384,7 @@ youtube
without cookies. Note: this may have adverse effects if used without cookies. Note: this may have adverse effects if used
improperly. If a session from a browser is wanted, you should pass improperly. If a session from a browser is wanted, you should pass
cookies instead (which contain the Visitor ID) cookies instead (which contain the Visitor ID)
- po_token: Proof of Origin (PO) Token(s) to use. Comma seperated list - po_token: Proof of Origin (PO) Token(s) to use. Comma-separated list
of PO Tokens in the format CLIENT.CONTEXT+PO_TOKEN, e.g. of PO Tokens in the format CLIENT.CONTEXT+PO_TOKEN, e.g.
youtube:po_token=web.gvs+XXX,web.player=XXX,web_safari.gvs+YYY. youtube:po_token=web.gvs+XXX,web.player=XXX,web_safari.gvs+YYY.
Context can be any of gvs (Google Video Server URLs), player Context can be any of gvs (Google Video Server URLs), player
@@ -2375,18 +2396,20 @@ youtube
requires one for the given context), never (never fetch a PO Token), requires one for the given context), never (never fetch a PO Token),
or auto (default; only fetch a PO Token if the client requires one or auto (default; only fetch a PO Token if the client requires one
for the given context) for the given context)
- playback_wait: Duration (in seconds) to wait inbetween the
extraction and download stages in order to ensure the formats are
available. The default is 6 seconds
- jsc_trace: Enable debug logging for JS Challenge fetching. Either - jsc_trace: Enable debug logging for JS Challenge fetching. Either
true or false (default) true or false (default)
- use_ad_playback_context: Skip preroll ads to eliminate the mandatory
wait period before download. Do NOT use this when passing premium
account cookies to yt-dlp, as it will result in a loss of premium
formats. Only effective with the web, web_safari, web_music and mweb
player clients. Either true or false (default)
youtube-ejs youtube-ejs
- jitless: Run suported Javascript engines in JIT-less mode. Supported - jitless: Run supported Javascript engines in JIT-less mode.
runtimes are deno, node and bun. Provides better security at the Supported runtimes are deno, node and bun. Provides better security
cost of performance/speed. Do note that node and bun are still at the cost of performance/speed. Do note that node and bun are
considered unsecure. Either true or false (default) still considered insecure. Either true or false (default)
youtubepot-webpo youtubepot-webpo
@@ -2568,10 +2591,11 @@ tver
vimeo vimeo
- client: Client to extract video data from. The currently available - client: Client to extract video data from. The currently available
clients are android, ios, and web. Only one client can be used. The clients are android, ios, macos and web. Only one client can be
web client is used by default. The web client only works with used. The macos client is used by default, but the web client is
account cookies or login credentials. The android and ios clients used when logged-in. The web client only works with account cookies
only work with previously cached OAuth tokens or login credentials. The android and ios clients only work with
previously cached OAuth tokens
- original_format_policy: Policy for when to try extracting original - original_format_policy: Policy for when to try extracting original
formats. One of always, never, or auto. The default auto policy formats. One of always, never, or auto. The default auto policy
tries to avoid exceeding the web client's API rate-limit by only tries to avoid exceeding the web client's API rate-limit by only
@@ -3085,7 +3109,7 @@ and youtube-dlc:
files by default. Use --mtime or --compat-options mtime-by-default files by default. Use --mtime or --compat-options mtime-by-default
to revert this. to revert this.
For ease of use, a few more compat options are available: For convenience, there are some compat option aliases available to use:
- --compat-options all: Use all compat options (Do NOT use this!) - --compat-options all: Use all compat options (Do NOT use this!)
- --compat-options youtube-dl: Same as - --compat-options youtube-dl: Same as
@@ -3097,8 +3121,13 @@ For ease of use, a few more compat options are available:
- --compat-options 2022: Same as - --compat-options 2022: Same as
--compat-options 2023,playlist-match-filter,no-external-downloader-progress,prefer-legacy-http-handler,manifest-filesize-approx --compat-options 2023,playlist-match-filter,no-external-downloader-progress,prefer-legacy-http-handler,manifest-filesize-approx
- --compat-options 2023: Same as --compat-options 2024,prefer-vp9-sort - --compat-options 2023: Same as --compat-options 2024,prefer-vp9-sort
- --compat-options 2024: Same as --compat-options mtime-by-default. - --compat-options 2024: Same as
Use this to enable all future compat options --compat-options 2025,mtime-by-default
- --compat-options 2025: Currently does nothing. Use this to enable
all future compat options
Using one of the yearly compat option aliases will pin yt-dlp's default
behavior to what it was at the end of that calendar year.
The following compat options restore vulnerable behavior from before The following compat options restore vulnerable behavior from before
security patches: security patches:

View File

@@ -50,7 +50,7 @@ complete --command yt-dlp --long-option geo-bypass-country
complete --command yt-dlp --long-option geo-bypass-ip-block complete --command yt-dlp --long-option geo-bypass-ip-block
complete --command yt-dlp --long-option playlist-start complete --command yt-dlp --long-option playlist-start
complete --command yt-dlp --long-option playlist-end complete --command yt-dlp --long-option playlist-end
complete --command yt-dlp --long-option playlist-items --short-option I --description 'Comma separated playlist_index of the items to download. You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. Use negative indices to count from the right and negative STEP to download in reverse order. E.g. "-I 1:3,7,-5::2" used on a playlist of size 15 will download the items at index 1,2,3,7,11,13,15' complete --command yt-dlp --long-option playlist-items --short-option I --description 'Comma-separated playlist_index of the items to download. You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. Use negative indices to count from the right and negative STEP to download in reverse order. E.g. "-I 1:3,7,-5::2" used on a playlist of size 15 will download the items at index 1,2,3,7,11,13,15'
complete --command yt-dlp --long-option match-title complete --command yt-dlp --long-option match-title
complete --command yt-dlp --long-option reject-title complete --command yt-dlp --long-option reject-title
complete --command yt-dlp --long-option min-filesize --description 'Abort download if filesize is smaller than SIZE, e.g. 50k or 44.6M' complete --command yt-dlp --long-option min-filesize --description 'Abort download if filesize is smaller than SIZE, e.g. 50k or 44.6M'
@@ -199,6 +199,7 @@ complete --command yt-dlp --long-option max-sleep-interval --description 'Maximu
complete --command yt-dlp --long-option sleep-subtitles --description 'Number of seconds to sleep before each subtitle download' complete --command yt-dlp --long-option sleep-subtitles --description 'Number of seconds to sleep before each subtitle download'
complete --command yt-dlp --long-option format --short-option f --description 'Video format code, see "FORMAT SELECTION" for more details' complete --command yt-dlp --long-option format --short-option f --description 'Video format code, see "FORMAT SELECTION" for more details'
complete --command yt-dlp --long-option format-sort --short-option S --description 'Sort the formats by the fields given, see "Sorting Formats" for more details' complete --command yt-dlp --long-option format-sort --short-option S --description 'Sort the formats by the fields given, see "Sorting Formats" for more details'
complete --command yt-dlp --long-option format-sort-reset --description 'Disregard previous user specified sort order and reset to the default'
complete --command yt-dlp --long-option format-sort-force --description 'Force user specified sort order to have precedence over all fields, see "Sorting Formats" for more details (Alias: --S-force)' complete --command yt-dlp --long-option format-sort-force --description 'Force user specified sort order to have precedence over all fields, see "Sorting Formats" for more details (Alias: --S-force)'
complete --command yt-dlp --long-option no-format-sort-force --description 'Some fields have precedence over the user specified sort order (default)' complete --command yt-dlp --long-option no-format-sort-force --description 'Some fields have precedence over the user specified sort order (default)'
complete --command yt-dlp --long-option video-multistreams --description 'Allow multiple video streams to be merged into a single file' complete --command yt-dlp --long-option video-multistreams --description 'Allow multiple video streams to be merged into a single file'

View File

@@ -265,7 +265,7 @@ One of \[dq]default\[dq] (only when known to be useful),
.SS Video Selection: .SS Video Selection:
.TP .TP
-I, --playlist-items \f[I]ITEM_SPEC\f[R] -I, --playlist-items \f[I]ITEM_SPEC\f[R]
Comma separated playlist_index of the items to download. Comma-separated playlist_index of the items to download.
You can specify a range using \[dq][START]:[STOP][:STEP]\[dq]. You can specify a range using \[dq][START]:[STOP][:STEP]\[dq].
For backward compatibility, START-STOP is also supported. For backward compatibility, START-STOP is also supported.
Use negative indices to count from the right and negative STEP to Use negative indices to count from the right and negative STEP to
@@ -811,6 +811,9 @@ Video format code, see \[dq]FORMAT SELECTION\[dq] for more details
Sort the formats by the fields given, see \[dq]Sorting Formats\[dq] for Sort the formats by the fields given, see \[dq]Sorting Formats\[dq] for
more details more details
.TP .TP
--format-sort-reset
Disregard previous user specified sort order and reset to the default
.TP
--format-sort-force --format-sort-force
Force user specified sort order to have precedence over all fields, see Force user specified sort order to have precedence over all fields, see
\[dq]Sorting Formats\[dq] for more details (Alias: --S-force) \[dq]Sorting Formats\[dq] for more details (Alias: --S-force)
@@ -1513,7 +1516,7 @@ E.g.
\f[V]diouxXeEfFgGcrs\f[R], yt-dlp additionally supports converting to \f[V]diouxXeEfFgGcrs\f[R], yt-dlp additionally supports converting to
\f[V]B\f[R] = \f[B]B\f[R]ytes, \f[V]j\f[R] = \f[B]j\f[R]son (flag \f[V]B\f[R] = \f[B]B\f[R]ytes, \f[V]j\f[R] = \f[B]j\f[R]son (flag
\f[V]#\f[R] for pretty-printing, \f[V]+\f[R] for Unicode), \f[V]h\f[R] = \f[V]#\f[R] for pretty-printing, \f[V]+\f[R] for Unicode), \f[V]h\f[R] =
HTML escaping, \f[V]l\f[R] = a comma separated \f[B]l\f[R]ist (flag HTML escaping, \f[V]l\f[R] = a comma-separated \f[B]l\f[R]ist (flag
\f[V]#\f[R] for \f[V]\[rs]n\f[R] newline-separated), \f[V]q\f[R] = a \f[V]#\f[R] for \f[V]\[rs]n\f[R] newline-separated), \f[V]q\f[R] = a
string \f[B]q\f[R]uoted for the terminal (flag \f[V]#\f[R] to split a string \f[B]q\f[R]uoted for the terminal (flag \f[V]#\f[R] to split a
list into different arguments), \f[V]D\f[R] = add \f[B]D\f[R]ecimal list into different arguments), \f[V]D\f[R] = add \f[B]D\f[R]ecimal
@@ -1650,6 +1653,9 @@ scale used depends on the webpage
some extractors, comments are only downloaded at the end, and so this some extractors, comments are only downloaded at the end, and so this
field cannot be used) field cannot be used)
.IP \[bu] 2 .IP \[bu] 2
\f[V]save_count\f[R] (numeric): Number of times the video has been saved
or bookmarked
.IP \[bu] 2
\f[V]age_limit\f[R] (numeric): Age restriction for the video (years) \f[V]age_limit\f[R] (numeric): Age restriction for the video (years)
.IP \[bu] 2 .IP \[bu] 2
\f[V]live_status\f[R] (string): One of \[dq]not_live\[dq], \f[V]live_status\f[R] (string): One of \[dq]not_live\[dq],
@@ -2349,6 +2355,18 @@ filesize instead.
So it is generally better to use So it is generally better to use
\f[V]-f best -S +size,+br,+res,+fps\f[R]. \f[V]-f best -S +size,+br,+res,+fps\f[R].
.PP .PP
If you use the \f[V]-S\f[R]/\f[V]--format-sort\f[R] option multiple
times, each subsequent sorting argument will be prepended to the
previous one, and only the highest priority entry of any duplicated
field will be preserved.
E.g.
\f[V]-S proto -S res\f[R] is equivalent to \f[V]-S res,proto\f[R], and
\f[V]-S res:720,fps -S vcodec,res:1080\f[R] is equivalent to
\f[V]-S vcodec,res:1080,fps\f[R].
You can use \f[V]--format-sort-reset\f[R] to disregard any previously
passed \f[V]-S\f[R]/\f[V]--format-sort\f[R] arguments and reset to the
default order.
.PP
\f[B]Tip\f[R]: You can use the \f[V]-v -F\f[R] to see how the formats \f[B]Tip\f[R]: You can use the \f[V]-v -F\f[R] to see how the formats
have been sorted (worst to best). have been sorted (worst to best).
.SS Format Selection examples .SS Format Selection examples
@@ -2582,12 +2600,13 @@ T}
T{ T{
\f[V]genre\f[R] \f[V]genre\f[R]
T}@T{ T}@T{
\f[V]genre\f[R] or \f[V]genres\f[R] \f[V]genre\f[R], \f[V]genres\f[R], \f[V]categories\f[R] or
\f[V]tags\f[R]
T} T}
T{ T{
\f[V]album\f[R] \f[V]album\f[R]
T}@T{ T}@T{
\f[V]album\f[R] \f[V]album\f[R] or \f[V]series\f[R]
T} T}
T{ T{
\f[V]album_artist\f[R] \f[V]album_artist\f[R]
@@ -2637,6 +2656,9 @@ $ yt-dlp --parse-metadata \[dq]title:%(artist)s - %(title)s\[dq]
# Regex example # Regex example
$ yt-dlp --parse-metadata \[dq]description:Artist - (?P<artist>.+)\[dq] $ yt-dlp --parse-metadata \[dq]description:Artist - (?P<artist>.+)\[dq]
# Copy the episode field to the title field (with FROM and TO as single fields)
$ yt-dlp --parse-metadata \[dq]episode:title\[dq]
# Set title as \[dq]Series name S01E05\[dq] # Set title as \[dq]Series name S01E05\[dq]
$ yt-dlp --parse-metadata \[dq]%(series)s S%(season_number)02dE%(episode_number)02d:%(title)s\[dq] $ yt-dlp --parse-metadata \[dq]%(series)s S%(season_number)02dE%(episode_number)02d:%(title)s\[dq]
@@ -2691,14 +2713,14 @@ respectively
\f[V]player_client\f[R]: Clients to extract video data from. \f[V]player_client\f[R]: Clients to extract video data from.
The currently available clients are \f[V]web\f[R], \f[V]web_safari\f[R], The currently available clients are \f[V]web\f[R], \f[V]web_safari\f[R],
\f[V]web_embedded\f[R], \f[V]web_music\f[R], \f[V]web_creator\f[R], \f[V]web_embedded\f[R], \f[V]web_music\f[R], \f[V]web_creator\f[R],
\f[V]mweb\f[R], \f[V]ios\f[R], \f[V]android\f[R], \f[V]mweb\f[R], \f[V]ios\f[R], \f[V]ios_downgraded\f[R],
\f[V]android_sdkless\f[R], \f[V]android_vr\f[R], \f[V]tv\f[R], \f[V]android\f[R], \f[V]android_vr\f[R], \f[V]tv\f[R],
\f[V]tv_simply\f[R], \f[V]tv_downgraded\f[R], and \f[V]tv_embedded\f[R]. \f[V]tv_simply\f[R], \f[V]tv_downgraded\f[R], and \f[V]tv_embedded\f[R].
By default, \f[V]tv,android_sdkless,web\f[R] is used. By default, \f[V]android_vr,ios_downgraded,web,web_safari\f[R] is used.
If no JavaScript runtime is available, then If no JavaScript runtime/engine is available, then
\f[V]android_sdkless,web_safari,web\f[R] is used. \f[V]android_vr,ios_downgraded\f[R] is used.
If logged-in cookies are passed to yt-dlp, then If logged-in cookies are passed to yt-dlp, then
\f[V]tv_downgraded,web_safari,web\f[R] is used for free accounts and \f[V]tv_downgraded,web,web_safari\f[R] is used for free accounts and
\f[V]tv_downgraded,web_creator,web\f[R] is used for premium accounts. \f[V]tv_downgraded,web_creator,web\f[R] is used for premium accounts.
The \f[V]web_music\f[R] client is added for \f[V]music.youtube.com\f[R] The \f[V]web_music\f[R] client is added for \f[V]music.youtube.com\f[R]
URLs when logged-in cookies are used. URLs when logged-in cookies are used.
@@ -2757,13 +2779,18 @@ choose comment sorting mode (on YouTube\[aq]s side)
.IP \[bu] 2 .IP \[bu] 2
\f[V]max_comments\f[R]: Limit the amount of comments to gather. \f[V]max_comments\f[R]: Limit the amount of comments to gather.
Comma-separated list of integers representing Comma-separated list of integers representing
\f[V]max-comments,max-parents,max-replies,max-replies-per-thread\f[R]. \f[V]max-comments,max-parents,max-replies,max-replies-per-thread,max-depth\f[R].
Default is \f[V]all,all,all,all\f[R] Default is \f[V]all,all,all,all,all\f[R]
.RS 2 .RS 2
.IP \[bu] 2 .IP \[bu] 2
A \f[V]max-depth\f[R] value of \f[V]1\f[R] will discard all replies,
regardless of the \f[V]max-replies\f[R] or
\f[V]max-replies-per-thread\f[R] values given
.IP \[bu] 2
E.g. E.g.
\f[V]all,all,1000,10\f[R] will get a maximum of 1000 replies total, with \f[V]all,all,1000,10,2\f[R] will get a maximum of 1000 replies total,
up to 10 replies per thread. with up to 10 replies per thread, and only 2 levels of depth (i.e.
top-level comments plus their immediate replies).
\f[V]1000,all,100\f[R] will get a maximum of 1000 comments, with a \f[V]1000,all,100\f[R] will get a maximum of 1000 comments, with a
maximum of 100 replies total maximum of 100 replies total
.RE .RE
@@ -2801,7 +2828,7 @@ If a session from a browser is wanted, you should pass cookies instead
(which contain the Visitor ID) (which contain the Visitor ID)
.IP \[bu] 2 .IP \[bu] 2
\f[V]po_token\f[R]: Proof of Origin (PO) Token(s) to use. \f[V]po_token\f[R]: Proof of Origin (PO) Token(s) to use.
Comma seperated list of PO Tokens in the format Comma-separated list of PO Tokens in the format
\f[V]CLIENT.CONTEXT+PO_TOKEN\f[R], e.g. \f[V]CLIENT.CONTEXT+PO_TOKEN\f[R], e.g.
\f[V]youtube:po_token=web.gvs+XXX,web.player=XXX,web_safari.gvs+YYY\f[R]. \f[V]youtube:po_token=web.gvs+XXX,web.player=XXX,web_safari.gvs+YYY\f[R].
Context can be any of \f[V]gvs\f[R] (Google Video Server URLs), Context can be any of \f[V]gvs\f[R] (Google Video Server URLs),
@@ -2818,20 +2845,23 @@ client requires one for the given context), \f[V]never\f[R] (never fetch
a PO Token), or \f[V]auto\f[R] (default; only fetch a PO Token if the a PO Token), or \f[V]auto\f[R] (default; only fetch a PO Token if the
client requires one for the given context) client requires one for the given context)
.IP \[bu] 2 .IP \[bu] 2
\f[V]playback_wait\f[R]: Duration (in seconds) to wait inbetween the
extraction and download stages in order to ensure the formats are
available.
The default is \f[V]6\f[R] seconds
.IP \[bu] 2
\f[V]jsc_trace\f[R]: Enable debug logging for JS Challenge fetching. \f[V]jsc_trace\f[R]: Enable debug logging for JS Challenge fetching.
Either \f[V]true\f[R] or \f[V]false\f[R] (default) Either \f[V]true\f[R] or \f[V]false\f[R] (default)
.IP \[bu] 2
\f[V]use_ad_playback_context\f[R]: Skip preroll ads to eliminate the
mandatory wait period before download.
Do NOT use this when passing premium account cookies to yt-dlp, as it
will result in a loss of premium formats.
Only effective with the \f[V]web\f[R], \f[V]web_safari\f[R],
\f[V]web_music\f[R] and \f[V]mweb\f[R] player clients.
Either \f[V]true\f[R] or \f[V]false\f[R] (default)
.SS youtube-ejs .SS youtube-ejs
.IP \[bu] 2 .IP \[bu] 2
\f[V]jitless\f[R]: Run suported Javascript engines in JIT-less mode. \f[V]jitless\f[R]: Run supported Javascript engines in JIT-less mode.
Supported runtimes are \f[V]deno\f[R], \f[V]node\f[R] and \f[V]bun\f[R]. Supported runtimes are \f[V]deno\f[R], \f[V]node\f[R] and \f[V]bun\f[R].
Provides better security at the cost of performance/speed. Provides better security at the cost of performance/speed.
Do note that \f[V]node\f[R] and \f[V]bun\f[R] are still considered Do note that \f[V]node\f[R] and \f[V]bun\f[R] are still considered
unsecure. insecure.
Either \f[V]true\f[R] or \f[V]false\f[R] (default) Either \f[V]true\f[R] or \f[V]false\f[R] (default)
.SS youtubepot-webpo .SS youtubepot-webpo
.IP \[bu] 2 .IP \[bu] 2
@@ -3045,9 +3075,10 @@ Default is \f[V]asc\f[R]
.IP \[bu] 2 .IP \[bu] 2
\f[V]client\f[R]: Client to extract video data from. \f[V]client\f[R]: Client to extract video data from.
The currently available clients are \f[V]android\f[R], \f[V]ios\f[R], The currently available clients are \f[V]android\f[R], \f[V]ios\f[R],
and \f[V]web\f[R]. \f[V]macos\f[R] and \f[V]web\f[R].
Only one client can be used. Only one client can be used.
The \f[V]web\f[R] client is used by default. The \f[V]macos\f[R] client is used by default, but the \f[V]web\f[R]
client is used when logged-in.
The \f[V]web\f[R] client only works with account cookies or login The \f[V]web\f[R] client only works with account cookies or login
credentials. credentials.
The \f[V]android\f[R] and \f[V]ios\f[R] clients only work with The \f[V]android\f[R] and \f[V]ios\f[R] clients only work with
@@ -3161,8 +3192,8 @@ Python versions 3.10+ (CPython) and 3.11+ (PyPy) are supported.
Other versions and implementations may or may not work correctly. Other versions and implementations may or may not work correctly.
.PP .PP
While all the other dependencies are optional, \f[V]ffmpeg\f[R], While all the other dependencies are optional, \f[V]ffmpeg\f[R],
\f[V]ffprobe\f[R], \f[V]yt-dlp-ejs\f[R] and a JavaScript runtime are \f[V]ffprobe\f[R], \f[V]yt-dlp-ejs\f[R] and a supported JavaScript
highly recommended runtime/engine are highly recommended
.SS Strongly recommended .SS Strongly recommended
.IP \[bu] 2 .IP \[bu] 2
\f[B]ffmpeg\f[R] and \f[B]ffprobe\f[R] (https://www.ffmpeg.org) - \f[B]ffmpeg\f[R] and \f[B]ffprobe\f[R] (https://www.ffmpeg.org) -
@@ -3185,8 +3216,8 @@ for details on the specific issues solved by these builds
name (https://pypi.org/project/ffmpeg) name (https://pypi.org/project/ffmpeg)
.RE .RE
.IP \[bu] 2 .IP \[bu] 2
\f[B]yt-dlp-ejs\f[R] (https://github.com/yt-dlp/ejs) - Required for \f[B]yt-dlp-ejs\f[R] (https://github.com/yt-dlp/ejs) - Required for full
deciphering YouTube n/sig values. YouTube support.
Licensed under Licensed under
Unlicense (https://github.com/yt-dlp/ejs/blob/main/LICENSE), bundles Unlicense (https://github.com/yt-dlp/ejs/blob/main/LICENSE), bundles
MIT (https://github.com/davidbonnet/astring/blob/main/LICENSE) and MIT (https://github.com/davidbonnet/astring/blob/main/LICENSE) and
@@ -3194,7 +3225,7 @@ ISC (https://github.com/meriyah/meriyah/blob/main/LICENSE.md)
components. components.
.RS 2 .RS 2
.PP .PP
A JavaScript runtime like \f[B]deno\f[R] (https://deno.land) A JavaScript runtime/engine like \f[B]deno\f[R] (https://deno.land)
(recommended), \f[B]node.js\f[R] (https://nodejs.org), (recommended), \f[B]node.js\f[R] (https://nodejs.org),
\f[B]bun\f[R] (https://bun.sh), or \f[B]bun\f[R] (https://bun.sh), or
\f[B]QuickJS\f[R] (https://bellard.org/quickjs/) is also required to run \f[B]QuickJS\f[R] (https://bellard.org/quickjs/) is also required to run
@@ -3237,7 +3268,7 @@ Licensed under
MIT (https://github.com/lexiforest/curl_cffi/blob/main/LICENSE) MIT (https://github.com/lexiforest/curl_cffi/blob/main/LICENSE)
.RS 2 .RS 2
.IP \[bu] 2 .IP \[bu] 2
Can be installed with the \f[V]curl-cffi\f[R] group, e.g. Can be installed with the \f[V]curl-cffi\f[R] extra, e.g.
\f[V]pip install \[dq]yt-dlp[default,curl-cffi]\[dq]\f[R] \f[V]pip install \[dq]yt-dlp[default,curl-cffi]\[dq]\f[R]
.IP \[bu] 2 .IP \[bu] 2
Currently included in most builds \f[I]except\f[R] \f[V]yt-dlp\f[R] Currently included in most builds \f[I]except\f[R] \f[V]yt-dlp\f[R]
@@ -3326,7 +3357,7 @@ You can run the following commands:
.IP .IP
.nf .nf
\f[C] \f[C]
python devscripts/install_deps.py --include-group pyinstaller python devscripts/install_deps.py --include-extra pyinstaller
python devscripts/make_lazy_extractors.py python devscripts/make_lazy_extractors.py
python -m bundle.pyinstaller python -m bundle.pyinstaller
\f[R] \f[R]
@@ -4056,7 +4087,7 @@ default.
Use \f[V]--mtime\f[R] or \f[V]--compat-options mtime-by-default\f[R] to Use \f[V]--mtime\f[R] or \f[V]--compat-options mtime-by-default\f[R] to
revert this. revert this.
.PP .PP
For ease of use, a few more compat options are available: For convenience, there are some compat option aliases available to use:
.IP \[bu] 2 .IP \[bu] 2
\f[V]--compat-options all\f[R]: Use all compat options (\f[B]Do NOT use \f[V]--compat-options all\f[R]: Use all compat options (\f[B]Do NOT use
this!\f[R]) this!\f[R])
@@ -4077,9 +4108,15 @@ this!\f[R])
\f[V]--compat-options 2024,prefer-vp9-sort\f[R] \f[V]--compat-options 2024,prefer-vp9-sort\f[R]
.IP \[bu] 2 .IP \[bu] 2
\f[V]--compat-options 2024\f[R]: Same as \f[V]--compat-options 2024\f[R]: Same as
\f[V]--compat-options mtime-by-default\f[R]. \f[V]--compat-options 2025,mtime-by-default\f[R]
.IP \[bu] 2
\f[V]--compat-options 2025\f[R]: Currently does nothing.
Use this to enable all future compat options Use this to enable all future compat options
.PP .PP
Using one of the yearly compat option aliases will pin yt-dlp\[aq]s
default behavior to what it was at the \f[I]end\f[R] of that calendar
year.
.PP
The following compat options restore vulnerable behavior from before The following compat options restore vulnerable behavior from before
security patches: security patches:
.IP \[bu] 2 .IP \[bu] 2

File diff suppressed because one or more lines are too long

View File

@@ -91,7 +91,9 @@ def search_google_images_and_save(x: str, audio):
if x.endswith(".flac"): if x.endswith(".flac"):
songpath = join(".",str(audio["artist"]),str(audio["album"])) songpath = join(".",str(audio["artist"]),str(audio["album"]))
else: else:
songpath = join(".",str(audio["TPE2"]),str(audio["TALB"])) # Use TPE2 if available, otherwise fallback to TPE1
artist_folder = str(audio.get("TPE2", audio.get("TPE1", "Unknown Artist")))
songpath = join(".", artist_folder, str(audio["TALB"]))
if "\x00" in songpath: if "\x00" in songpath:
# having null bytes in os.replace will throw an error # having null bytes in os.replace will throw an error
songpath = songpath.replace("\x00",", ") songpath = songpath.replace("\x00",", ")
@@ -189,7 +191,7 @@ def create_ID3_tag(audio, tagname: str, textvalue: str):
def check_tag(audio, filename: str, ID3_tag: str, normal_tag) -> bool: def check_tag(audio, filename: str, ID3_tag: str, normal_tag) -> bool:
res = False res = False
# check if the ID3 artist tag exists # check if the ID3 tag exists
if (ID3_tag in audio.keys() and len(str(audio[ID3_tag])) != 0): if (ID3_tag in audio.keys() and len(str(audio[ID3_tag])) != 0):
logging.info(ID3_tag + " ID3 tag found! " + str(audio[ID3_tag])) logging.info(ID3_tag + " ID3 tag found! " + str(audio[ID3_tag]))
@@ -201,7 +203,7 @@ def check_tag(audio, filename: str, ID3_tag: str, normal_tag) -> bool:
logging.info("Set " + normal_tag + " to " + str(audio[normal_tag])) logging.info("Set " + normal_tag + " to " + str(audio[normal_tag]))
res = True res = True
# check if general album tag exists # check if general tag exists
elif (normal_tag in audio.keys() and len(str(audio[normal_tag])) != 0): elif (normal_tag in audio.keys() and len(str(audio[normal_tag])) != 0):
logging.info(normal_tag + " normal tag found! " + str(audio[normal_tag])) logging.info(normal_tag + " normal tag found! " + str(audio[normal_tag]))
if audio[normal_tag] is not str: if audio[normal_tag] is not str:
@@ -228,6 +230,11 @@ def check_title_songname(x: str, audio):
if (" - " in x): if (" - " in x):
items = x.split(" - ") items = x.split(" - ")
# If the format is 'artist - Topic - title', remove 'Topic'
if len(items) > 2 and items[1].strip().lower() == "topic":
logging.info("Detected ' - Topic - ' in name, removing 'Topic'.")
# Rebuild items without 'Topic'
items = [items[0]] + items[2:]
if (len(items) > 2): if (len(items) > 2):
logging.info("song title has more than 1 part after the -: " + str(items)) logging.info("song title has more than 1 part after the -: " + str(items))
if (items[1].count(".mp3") >= 1): if (items[1].count(".mp3") >= 1):
@@ -266,7 +273,7 @@ def check_for_multiple_artists(audio, filename: str, name: str):
artists = name.split(",") artists = name.split(",")
elif ("/" in name): elif ("/" in name):
artists = name.split("/") artists = name.split("/")
elif ("\x00" in name): elif ("\x00" in name):
artists = name.split("\x00") artists = name.split("\x00")
if (len(artists) > 0): if (len(artists) > 0):
@@ -276,7 +283,11 @@ def check_for_multiple_artists(audio, filename: str, name: str):
else: else:
audio["TPE1"] = TPE2(encoding=3,text=["\0".join(artists)]) audio["TPE1"] = TPE2(encoding=3,text=["\0".join(artists)])
else: else:
logging.info("no multiple artists found in name " + name) logging.info("no multiple artists found in name " + name + ", setting artist to " + name)
if filename.endswith(".flac"):
audio["artist"] = TPE2(encoding=3,text=name)
else:
audio["TPE1"] = TPE2(encoding=3,text=name)
# checks for any artist from the song name. If it exists it sets the properties of the file # checks for any artist from the song name. If it exists it sets the properties of the file
@@ -297,6 +308,9 @@ def check_artist(audio, filename: str) -> bool:
res = False res = False
# check if the ID3 artist tag exists # check if the ID3 artist tag exists
check_tag(audio, filename, "TPE1","artist")
check_tag(audio, filename, "TPE2","artist")
if ("TPE1" in audio.keys()): if ("TPE1" in audio.keys()):
if (len(str(audio["TPE1"])) != 0): if (len(str(audio["TPE1"])) != 0):
logging.info("TPE1 tag was found! " + str(audio["TPE1"])) logging.info("TPE1 tag was found! " + str(audio["TPE1"]))
@@ -445,9 +459,9 @@ def check_spotify_album_and_save(spotify, audio,x: str) -> bool:
comment ="Spotify ID: {0}. Release date precision: {1}, total tracks in album: {2}. This album has {3} version(s)".format(album["id"],album["release_date_precision"], album["total_tracks"],len(results["albums"]["items"])) comment ="Spotify ID: {0}. Release date precision: {1}, total tracks in album: {2}. This album has {3} version(s)".format(album["id"],album["release_date_precision"], album["total_tracks"],len(results["albums"]["items"]))
logging.info("Comment: " + comment) logging.info("Comment: " + comment)
if x.endswith(".flac"): if x.endswith(".flac"):
audio["comment"] = comment audio["comment"] = audio["comment"] + comment
else: else:
audio["COMM"] = COMM(encoding=3,text=comment) audio["COMM"] = COMM(encoding=3,text=comment + audio["COMM"])
if x.endswith(".flac"): if x.endswith(".flac"):
remove_flac_ID3_tags(audio,x) remove_flac_ID3_tags(audio,x)
@@ -748,10 +762,12 @@ def main():
logging.info("valid artist found. making folder for artist " + str(audio["artist"][0])) logging.info("valid artist found. making folder for artist " + str(audio["artist"][0]))
make_folder(join(".",str(audio["artist"][0]))) make_folder(join(".",str(audio["artist"][0])))
else: else:
logging.info("valid artist found. making folder for artist " + str(audio["TPE1"])) # Use TPE2 if available, otherwise fallback to TPE1
if "/" in audio["TPE2"]: artist_folder = str(audio.get("TPE2", audio.get("TPE1", "Unknown Artist")))
audio["TPE2"] = audio["TPE2"].replace("/","") logging.info("valid artist found. making folder for artist " + artist_folder)
make_folder(join(".",str(audio["TPE2"]))) if "/" in artist_folder:
artist_folder = artist_folder.replace("/","")
make_folder(join(".", artist_folder))
if (has_valid_album): if (has_valid_album):
if (x.endswith(".flac")): if (x.endswith(".flac")):