Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package yt-dlp for openSUSE:Factory checked 
in at 2026-03-13 21:17:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yt-dlp (Old)
 and      /work/SRC/openSUSE:Factory/.yt-dlp.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yt-dlp"

Fri Mar 13 21:17:44 2026 rev:89 rq:1338667 version:2026.03.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/yt-dlp/yt-dlp.changes    2026-03-07 
20:15:21.981359849 +0100
+++ /work/SRC/openSUSE:Factory/.yt-dlp.new.8177/yt-dlp.changes  2026-03-13 
21:21:49.681775823 +0100
@@ -1,0 +2,16 @@
+Fri Mar 13 09:19:22 UTC 2026 - Luigi Baldoni <[email protected]>
+
+- Update to version 2026.03.13
+  * Extractor changes:
+  * tiktok: Fix challenge solving
+  * yt: Fix android_vr player client
+  * yt: Fix use_ad_playback_context extractor-arg
+  * yt: Fix web_embedded player client
+  * yt: Request web_safari & web_creator client configs
+  * tab: Fix album extraction
+  * tab: Improve description extraction
+  * Update ejs to 0.7.0                             
+  * ejs: Fix sig value encoding by
+  * ejs: Solve new player variants
+
+-------------------------------------------------------------------

Old:
----
  yt_dlp_ejs-0.5.0-py3-none-any.whl

New:
----
  yt_dlp_ejs-0.7.0-py3-none-any.whl

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yt-dlp.spec ++++++
--- /var/tmp/diff_new_pack.mL0v5c/_old  2026-03-13 21:21:50.505809815 +0100
+++ /var/tmp/diff_new_pack.mL0v5c/_new  2026-03-13 21:21:50.509809980 +0100
@@ -27,8 +27,8 @@
 %endif
 
 Name:           yt-dlp
-Version:        2026.03.03
-%define ejsver  0.5.0
+Version:        2026.03.13
+%define ejsver  0.7.0
 Release:        0
 Summary:        Enhanced fork of youtube-dl, a video site downloader for 
offline watching
 License:        CC-BY-SA-3.0 AND SUSE-Public-Domain

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.mL0v5c/_old  2026-03-13 21:21:50.557811960 +0100
+++ /var/tmp/diff_new_pack.mL0v5c/_new  2026-03-13 21:21:50.561812125 +0100
@@ -1,5 +1,5 @@
-mtime: 1772648117
-commit: ffb0e8fa4812abe13422a4a47afd3325fdddc1ac324dbbaa88d69cc060b69dc9
+mtime: 1773395486
+commit: 4dcaef1d42b3f31d08e089a22c26f3e8d491326150f53e226d7251a38e21492b
 url: https://src.opensuse.org/jengelh/yt-dlp
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-03-13 10:51:35.000000000 +0100
@@ -0,0 +1 @@
+.osc

++++++ yt-dlp.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/AUTHORS new/yt-dlp/AUTHORS
--- old/yt-dlp/AUTHORS  2026-03-03 17:37:40.000000000 +0100
+++ new/yt-dlp/AUTHORS  2026-03-13 09:45:34.000000000 +0100
@@ -396,6 +396,7 @@
 François Revol
 Frederic Bournival
 Frederik Nordahl Jul Sabroe
+Frieder Hannenheim
 Friedrich Rehren
 GD-Slime
 GDR!
@@ -842,6 +843,7 @@
 Peisen Wang
 Pete Hemery
 Peter
+Peter Devine
 Peter Hosey
 Peter Oettig
 Peter Pitzulo
@@ -996,6 +998,7 @@
 Soebb
 Sojiroh
 Sonic
+SparseOrnament15
 SsSsS
 Stanislav Kupryakhin
 Stanny Nuytkens
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/CONTRIBUTORS new/yt-dlp/CONTRIBUTORS
--- old/yt-dlp/CONTRIBUTORS     2026-03-03 17:37:22.000000000 +0100
+++ new/yt-dlp/CONTRIBUTORS     2026-03-13 09:45:34.000000000 +0100
@@ -874,3 +874,6 @@
 regulad
 stastix
 syphyr
+FriederHannenheim
+Peter-Devine
+SparseOrnament15
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/Changelog.md new/yt-dlp/Changelog.md
--- old/yt-dlp/Changelog.md     2026-03-03 17:37:33.000000000 +0100
+++ new/yt-dlp/Changelog.md     2026-03-13 09:45:29.000000000 +0100
@@ -4,6 +4,20 @@
 # To create a release, dispatch the 
https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on 
master
 -->
 
+### 2026.03.13
+
+#### Extractor changes
+- **tiktok**: [Fix challenge 
solving](https://github.com/yt-dlp/yt-dlp/commit/db62e438a15743b156ca5ebfc6dbe160e9bc1662)
 ([#16223](https://github.com/yt-dlp/yt-dlp/issues/16223)) by 
[bashonly](https://github.com/bashonly)
+- **youtube**
+    - [Fix `android_vr` player 
client](https://github.com/yt-dlp/yt-dlp/commit/ff459e5fc04b1a061212672626b7bfa23ff3cdcd)
 ([#16168](https://github.com/yt-dlp/yt-dlp/issues/16168)) by 
[gamer191](https://github.com/gamer191)
+    - [Fix `use_ad_playback_context` 
extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/7e145ac1cae8f891e18c9375fa23097f1dfa0b19)
 ([#16196](https://github.com/yt-dlp/yt-dlp/issues/16196)) by 
[bashonly](https://github.com/bashonly)
+    - [Fix `web_embedded` player 
client](https://github.com/yt-dlp/yt-dlp/commit/f2bd3202c0ffa3f0c0069c44ca53b625dca568bc)
 ([#16177](https://github.com/yt-dlp/yt-dlp/issues/16177)) by 
[bashonly](https://github.com/bashonly), 
[SparseOrnament15](https://github.com/SparseOrnament15)
+    - [Request `web_safari` & `web_creator` client 
configs](https://github.com/yt-dlp/yt-dlp/commit/48a61d0f38b156785d24df628d42892441e008c4)
 ([#16198](https://github.com/yt-dlp/yt-dlp/issues/16198)) by 
[bashonly](https://github.com/bashonly)
+    - [Update ejs to 
0.7.0](https://github.com/yt-dlp/yt-dlp/commit/92f1d99dbe1e10d942ef0963f625dbc5bc0768aa)
 ([#16231](https://github.com/yt-dlp/yt-dlp/issues/16231)) by 
[bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
+    - tab
+        - [Fix album 
extraction](https://github.com/yt-dlp/yt-dlp/commit/ae025da02364f4d085953f41fd0d32ade3c4afb9)
 ([#16041](https://github.com/yt-dlp/yt-dlp/issues/16041)) by 
[FriederHannenheim](https://github.com/FriederHannenheim)
+        - [Improve description 
extraction](https://github.com/yt-dlp/yt-dlp/commit/3e36cf9cdb12ef566416c5620a1a95b5a0221017)
 ([#16057](https://github.com/yt-dlp/yt-dlp/issues/16057)) by 
[Peter-Devine](https://github.com/Peter-Devine)
+
 ### 2026.03.03
 
 #### Extractor changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/Makefile new/yt-dlp/Makefile
--- old/yt-dlp/Makefile 2026-03-03 17:37:22.000000000 +0100
+++ new/yt-dlp/Makefile 2026-03-13 09:45:22.000000000 +0100
@@ -202,9 +202,9 @@
 
 # The following EJS_-prefixed variables are auto-generated by 
devscripts/update_ejs.py
 # DO NOT EDIT!
-EJS_VERSION = 0.5.0
-EJS_WHEEL_NAME = yt_dlp_ejs-0.5.0-py3-none-any.whl
-EJS_WHEEL_HASH = 
sha256:674fc0efea741d3100cdf3f0f9e123150715ee41edf47ea7a62fbdeda204bdec
+EJS_VERSION = 0.7.0
+EJS_WHEEL_NAME = yt_dlp_ejs-0.7.0-py3-none-any.whl
+EJS_WHEEL_HASH = 
sha256:967e9cbe114ddfd046ff4668af18b1827b4597e2e47a83deea668a355828c798
 EJS_PY_FOLDERS = yt_dlp_ejs yt_dlp_ejs/yt yt_dlp_ejs/yt/solver
 EJS_PY_FILES = yt_dlp_ejs/__init__.py yt_dlp_ejs/_version.py 
yt_dlp_ejs/yt/__init__.py yt_dlp_ejs/yt/solver/__init__.py
 EJS_JS_FOLDERS = yt_dlp_ejs/yt/solver
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/README.md new/yt-dlp/README.md
--- old/yt-dlp/README.md        2026-03-03 17:37:39.000000000 +0100
+++ new/yt-dlp/README.md        2026-03-13 09:45:33.000000000 +0100
@@ -1862,10 +1862,11 @@
 * `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction 
of the m3u8 manifests, dash manifests and [auto-translated 
subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032)
 respectively
 * `player_client`: Clients to extract video data from. The currently available 
clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, 
`mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. 
By default, `android_vr,web,web_safari` is used. If no JavaScript 
runtime/engine is available, then only `android_vr` is used. If logged-in 
cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for 
free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. 
The `web_music` client is added for `music.youtube.com` URLs when logged-in 
cookies are used. The `web_embedded` client is added for age-restricted videos 
but only successfully works around the age-restriction sometimes (e.g. if the 
video is embeddable), and may be added as a fallback if `android_vr` is unable 
to access a video. The `web_creator` client is added for age-restricted videos 
if account age-verification is required. Some clients, such as `web_crea
 tor` and `web_music`, require a `po_token` for their formats to be 
downloadable. Some clients, such as `web_creator`, will only work with 
authentication. Not all clients support authentication via cookies. 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 exclude it, e.g. 
`youtube:player_client=default,-web`
 * `player_skip`: Skip some network requests that are generally needed for 
robust extraction. One or more of `configs` (skip client configs), `webpage` 
(skip initial webpage), `js` (skip js player), `initial_data` (skip initial 
data/next ep request). While these options can help reduce the number of 
requests needed or avoid some rate-limiting, they could cause issues such as 
missing formats or metadata.  See 
[#860](https://github.com/yt-dlp/yt-dlp/pull/860) and 
[#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
-* `webpage_skip`: Skip extraction of embedded webpage data. One or both of 
`player_response`, `initial_data`. Using these will not skip any network 
requests, and in some cases will result in additional network requests. 
Currently, the default is `player_response`; however, typically these are for 
testing purposes only
+* `webpage_skip`: Skip extraction of embedded webpage data. One or both of 
`player_response`, `initial_data`. These options are for testing purposes and 
don't skip any network requests. Neither is skipped by default; however, if a 
`player_js_version` value other than `actual` is used, then 
`webpage_skip=player_response` is implied
+* `webpage_client`: Client to use for the video webpage request. One of `web` 
or `web_safari` (default)
 * `player_params`: YouTube player parameters to use for player requests. Will 
overwrite any default ones set by yt-dlp.
 * `player_js_variant`: The player javascript variant to use for n/sig 
deciphering. The known variants are: `main`, `tcc`, `tce`, `es5`, `es6`, 
`es6_tcc`, `es6_tce`, `tv`, `tv_es6`, `phone`, `house`. The default is `tv`, 
and the others are for debugging purposes. You can use `actual` to go with what 
is prescribed by the site
-* `player_js_version`: The player javascript version to use for n/sig 
deciphering, in the format of `signature_timestamp@hash` (e.g. 
`20348@0004de42`). Currently, the default is to force `20514@9f4cc5e4`. You can 
use `actual` to go with what is prescribed by the site
+* `player_js_version`: The player javascript version to use for n/sig 
deciphering, in the format of `signature_timestamp@hash` (e.g. 
`20348@0004de42`). The default is to use what is prescribed by the site, and 
can be selected with `actual`. Using any other value will imply 
`webpage_skip=player_response`
 * `comment_sort`: `top` or `new` (default) - choose comment sorting mode (on 
YouTube's side)
 * `max_comments`: Limit the amount of comments to gather. Comma-separated list 
of integers representing 
`max-comments,max-parents,max-replies,max-replies-per-thread,max-depth`. 
Default is `all,all,all,all,all`
     * A `max-depth` value of `1` will discard all replies, regardless of the 
`max-replies` or `max-replies-per-thread` values given
@@ -1880,7 +1881,7 @@
 * `pot_trace`: Enable debug logging for PO Token fetching. Either `true` or 
`false` (default)
 * `fetch_pot`: Policy to use for fetching a PO Token from providers. One of 
`always` (always try fetch a PO Token regardless if the client 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 for the given context)
 * `jsc_trace`: Enable debug logging for JS Challenge fetching. Either `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)
+* `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 
`mweb` and `web_music` player clients. Either `true` or `false` (default)
 
 #### youtube-ejs
 * `jitless`: Run supported Javascript engines in JIT-less mode. Supported 
runtimes are `deno`, `node` and `bun`. Provides better security at the cost of 
performance/speed. Do note that `node` and `bun` are still considered insecure. 
Either `true` or `false` (default)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/README.txt new/yt-dlp/README.txt
--- old/yt-dlp/README.txt       2026-03-03 17:37:40.000000000 +0100
+++ new/yt-dlp/README.txt       2026-03-13 09:45:34.000000000 +0100
@@ -2339,10 +2339,12 @@
     they could cause issues such as missing formats or metadata. See
     #860 and #12826 for more details
 -   webpage_skip: Skip extraction of embedded webpage data. One or both
-    of player_response, initial_data. Using these will not skip any
-    network requests, and in some cases will result in additional
-    network requests. Currently, the default is player_response;
-    however, typically these are for testing purposes only
+    of player_response, initial_data. These options are for testing
+    purposes and don't skip any network requests. Neither is skipped by
+    default; however, if a player_js_version value other than actual is
+    used, then webpage_skip=player_response is implied
+-   webpage_client: Client to use for the video webpage request. One of
+    web or web_safari (default)
 -   player_params: YouTube player parameters to use for player requests.
     Will overwrite any default ones set by yt-dlp.
 -   player_js_variant: The player javascript variant to use for n/sig
@@ -2352,8 +2354,9 @@
     what is prescribed by the site
 -   player_js_version: The player javascript version to use for n/sig
     deciphering, in the format of signature_timestamp@hash (e.g.
-    20348@0004de42). Currently, the default is to force 20514@9f4cc5e4.
-    You can use actual to go with what is prescribed by the site
+    20348@0004de42). The default is to use what is prescribed by the
+    site, and can be selected with actual. Using any other value will
+    imply webpage_skip=player_response
 -   comment_sort: top or new (default) - choose comment sorting mode (on
     YouTube's side)
 -   max_comments: Limit the amount of comments to gather.
@@ -2405,8 +2408,8 @@
 -   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)
+    formats. Only effective with the mweb and web_music player clients.
+    Either true or false (default)
 
 youtube-ejs
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/pyproject.toml new/yt-dlp/pyproject.toml
--- old/yt-dlp/pyproject.toml   2026-03-03 17:37:22.000000000 +0100
+++ new/yt-dlp/pyproject.toml   2026-03-13 09:45:22.000000000 +0100
@@ -55,7 +55,7 @@
     "requests>=2.32.2,<3",
     "urllib3>=2.0.2,<3",
     "websockets>=13.0",
-    "yt-dlp-ejs==0.5.0",
+    "yt-dlp-ejs==0.7.0",
 ]
 curl-cffi = [
     "curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.15; 
implementation_name=='cpython'",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/test/test_jsc/test_ejs_integration.py 
new/yt-dlp/test/test_jsc/test_ejs_integration.py
--- old/yt-dlp/test/test_jsc/test_ejs_integration.py    2026-03-03 
17:37:22.000000000 +0100
+++ new/yt-dlp/test/test_jsc/test_ejs_integration.py    2026-03-13 
09:45:22.000000000 +0100
@@ -53,117 +53,49 @@
 
 
 CHALLENGES: list[Challenge] = [
-    Challenge('3d3ba064', Variant.tce, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': 'qmtUsIz04xxiNW',
-        '4GMrWHyKI5cEvhDO': 'N9gmEX7YhKTSmw',
+    # 20518
+    Challenge('edc3ba07', Variant.tv, JsChallengeType.N, {
+        'BQoJvGBkC2nj1ZZLK-': '-m-se9fQVnvEofLx',
     }),
-    Challenge('3d3ba064', Variant.tce, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3gqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNG_1kNyBf6HPuAuCduh-a7O',
-    }),
-    Challenge('5ec65609', Variant.tce, JsChallengeType.N, {
-        '0eRGgQWJGfT5rFHFj': '4SvMpDQH-vBJCw',
-    }),
-    Challenge('5ec65609', Variant.tce, JsChallengeType.SIG, {
-        
'AAJAJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grH0rTMICA1mmDc0HoXgW3CAiAQQ4=CspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ=I':
-            
'AJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grI0rTMICA1mmDc0HoXgW3CAiAQQ4HCspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ==',
-    }),
-    Challenge('6742b2b9', Variant.tce, JsChallengeType.N, {
-        '_HPB-7GFg1VTkn9u': 'qUAsPryAO_ByYg',
-        'K1t_fcB6phzuq2SF': 'Y7PcOt3VE62mog',
-    }),
-    Challenge('6742b2b9', Variant.tce, JsChallengeType.SIG, {
-        
'MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA':
-            
'AJfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHM8EjoCACIEQnz-nKN5RgG6iUTnNJC58csYPSrnS_SzricuUMJZGM',
-    }),
-    Challenge('2b83d2e0', Variant.main, JsChallengeType.N, {
-        '0eRGgQWJGfT5rFHFj': 'euHbygrCMLksxd',
-    }),
-    Challenge('2b83d2e0', Variant.main, JsChallengeType.SIG, {
-        
'MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJA':
-            
'-MGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKnMznQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJ',
-    }),
-    Challenge('638ec5c6', Variant.main, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': '1qov8-KM-yH',
-    }),
-    Challenge('638ec5c6', Variant.main, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'MhudCuAuP-6fByOk1_GNXN7gNHHShjyXS2VOgsEItAJz0tipeav0OmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt',
-    }),
-    # c1c87fb0: tce variant broke sig solving; n and main variant are added 
only for regression testing
-    Challenge('c1c87fb0', Variant.main, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': 'jCHBK5GuAFNa2',
-    }),
-    Challenge('c1c87fb0', Variant.main, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3DqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNGa1kOyBf6HPuAuCduh-_',
-    }),
-    Challenge('c1c87fb0', Variant.tce, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': 'jCHBK5GuAFNa2',
-    }),
-    Challenge('c1c87fb0', Variant.tce, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3DqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNGa1kOyBf6HPuAuCduh-_',
-    }),
-    # 4e51e895: main variant broke sig solving; n challenge is added only for 
regression testing
-    Challenge('4e51e895', Variant.main, JsChallengeType.N, {
-        '0eRGgQWJGfT5rFHFj': 't5kO23_msekBur',
-    }),
-    Challenge('4e51e895', Variant.main, JsChallengeType.SIG, {
-        
'AL6p_8AwdY9yAhRzK8rYA_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7':
-            
'AwdY9yAhRzK8rYA_9n97Kizf7_9n97Kizf7_9n9pKizf7_9n97Kizf7_9n97Kizf7_9n97Kizf7',
-    }),
-    # 42c5570b: tce variant broke sig solving; n challenge is added only for 
regression testing
-    Challenge('42c5570b', Variant.tce, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': 'CRoXjB-R-R',
-    }),
-    Challenge('42c5570b', Variant.tce, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'EN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavcOmNdYN-wUtgEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt',
-    }),
-    # 54bd1de4: tce variant broke sig solving; n challenge is added only for 
regression testing
-    Challenge('54bd1de4', Variant.tce, JsChallengeType.N, {
-        'ZdZIqFPQK-Ty8wId': 'ka-slAQ31sijFN',
-    }),
-    Challenge('54bd1de4', Variant.tce, JsChallengeType.SIG, {
-        
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt':
-            
'gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0titeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtp',
-    }),
-    # 94667337: tce and es6 variants broke sig solving; n and main/tv variants 
are added only for regression testing
-    Challenge('94667337', Variant.main, JsChallengeType.N, {
-        'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
-    }),
-    Challenge('94667337', Variant.main, JsChallengeType.SIG, {
+    Challenge('edc3ba07', Variant.tv, JsChallengeType.SIG, {
         
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
-            
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
+            
'zwg=wgwCHlydB9zg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlh5mt5OX-8MB=tRPyyEdAM9MPM-kPfjgTxEK0IAhIgRwE0jiz',
     }),
-    Challenge('94667337', Variant.tv, JsChallengeType.N, {
-        'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
+    # 20521
+    Challenge('316b61b4', Variant.tv, JsChallengeType.N, {
+        'IlLiA21ny7gqA2m4p37': 'GchRcsUC_WmnhOUVGV',
     }),
-    Challenge('94667337', Variant.tv, JsChallengeType.SIG, {
+    Challenge('316b61b4', Variant.tv, JsChallengeType.SIG, {
         
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
-            
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
+            
'tJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRN=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwz',
     }),
-    Challenge('94667337', Variant.es6, JsChallengeType.N, {
-        'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
+    # 20522
+    Challenge('74edf1a3', Variant.tv, JsChallengeType.N, {
+        'IlLiA21ny7gqA2m4p37': '9nRTxrbM1f0yHg',
+        'eabGFpsUKuWHXGh6FR4': 'izmYqDEY6kl7Sg',
+        'eabGF/ps%UK=uWHXGh6FR4': 'LACmqlhaBpiPlgE-a',
     }),
-    Challenge('94667337', Variant.es6, JsChallengeType.SIG, {
+    Challenge('74edf1a3', Variant.tv, JsChallengeType.SIG, {
         
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
-            
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
-    }),
-    Challenge('94667337', Variant.tce, JsChallengeType.N, {
-        'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
+            
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hzMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzl',
+        
'\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49':
+            
'\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x49\x44\x45\x46\x47\x48\x43',
+    }),
+    # 20523
+    Challenge('901741ab', Variant.tv, JsChallengeType.N, {
+        'BQoJvGBkC2nj1ZZLK-': 'UMPovvBZRh-sjb',
     }),
-    Challenge('94667337', Variant.tce, JsChallengeType.SIG, {
+    Challenge('901741ab', Variant.tv, JsChallengeType.SIG, {
         
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
-            
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
+            
'wgwCHlydB9Hg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlhwmt5ON-8MB=5RPyyzdAM9MPM-kPfjgTxEK0IAhIgRwE0jiEJA',
     }),
-    Challenge('94667337', Variant.es6_tce, JsChallengeType.N, {
-        'BQoJvGBkC2nj1ZZLK-': 'ib1ShEOGoFXIIw',
+    # 20524
+    Challenge('e7573094', Variant.tv, JsChallengeType.N, {
+        'IlLiA21ny7gqA2m4p37': '3KuQ3235dojTSjo4',
     }),
-    Challenge('94667337', Variant.es6_tce, JsChallengeType.SIG, {
+    Challenge('e7573094', Variant.tv, JsChallengeType.SIG, {
         
'NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz':
-            
'AJEij0EwRgIhAI0KExTgjfPk-MPM9MNdzyyPRtzBM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=',
+            
'yEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyNPRt=BM8-XO5tm5hlMCSVNAiEAvpeP3CURqZJSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=g',
     }),
 ]
 
Binary files old/yt-dlp/yt-dlp and new/yt-dlp/yt-dlp differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt-dlp.1 new/yt-dlp/yt-dlp.1
--- old/yt-dlp/yt-dlp.1 2026-03-03 17:37:41.000000000 +0100
+++ new/yt-dlp/yt-dlp.1 2026-03-13 09:45:35.000000000 +0100
@@ -2752,10 +2752,14 @@
 .IP \[bu] 2
 \f[V]webpage_skip\f[R]: Skip extraction of embedded webpage data.
 One or both of \f[V]player_response\f[R], \f[V]initial_data\f[R].
-Using these will not skip any network requests, and in some cases will
-result in additional network requests.
-Currently, the default is \f[V]player_response\f[R]; however, typically
-these are for testing purposes only
+These options are for testing purposes and don\[aq]t skip any network
+requests.
+Neither is skipped by default; however, if a \f[V]player_js_version\f[R]
+value other than \f[V]actual\f[R] is used, then
+\f[V]webpage_skip=player_response\f[R] is implied
+.IP \[bu] 2
+\f[V]webpage_client\f[R]: Client to use for the video webpage request.
+One of \f[V]web\f[R] or \f[V]web_safari\f[R] (default)
 .IP \[bu] 2
 \f[V]player_params\f[R]: YouTube player parameters to use for player
 requests.
@@ -2773,8 +2777,9 @@
 n/sig deciphering, in the format of
 \f[V]signature_timestamp\[at]hash\f[R] (e.g.
 \f[V]20348\[at]0004de42\f[R]).
-Currently, the default is to force \f[V]20514\[at]9f4cc5e4\f[R].
-You can use \f[V]actual\f[R] to go with what is prescribed by the site
+The default is to use what is prescribed by the site, and can be
+selected with \f[V]actual\f[R].
+Using any other value will imply \f[V]webpage_skip=player_response\f[R]
 .IP \[bu] 2
 \f[V]comment_sort\f[R]: \f[V]top\f[R] or \f[V]new\f[R] (default) -
 choose comment sorting mode (on YouTube\[aq]s side)
@@ -2854,8 +2859,8 @@
 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.
+Only effective with the \f[V]mweb\f[R] and \f[V]web_music\f[R] player
+clients.
 Either \f[V]true\f[R] or \f[V]false\f[R] (default)
 .SS youtube-ejs
 .IP \[bu] 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/tiktok.py 
new/yt-dlp/yt_dlp/extractor/tiktok.py
--- old/yt-dlp/yt_dlp/extractor/tiktok.py       2026-03-03 17:37:22.000000000 
+0100
+++ new/yt-dlp/yt_dlp/extractor/tiktok.py       2026-03-13 09:45:22.000000000 
+0100
@@ -220,7 +220,7 @@
             raise ExtractorError('Unable to extract aweme detail info', 
video_id=aweme_id)
         return self._parse_aweme_video_app(aweme_detail)
 
-    def _solve_challenge_and_set_cookie(self, webpage):
+    def _solve_challenge_and_set_cookies(self, webpage):
         challenge_data = traverse_obj(webpage, (
             {find_element(id='cs', html=True)}, {extract_attributes}, 'class',
             filter, {lambda x: f'{x}==='}, {base64.b64decode}, {json.loads}))
@@ -250,17 +250,27 @@
         else:
             raise ExtractorError('Unable to solve JS challenge')
 
-        cookie_value = base64.b64encode(
+        wci_cookie_value = base64.b64encode(
             json.dumps(challenge_data, separators=(',', 
':')).encode()).decode()
 
-        # At time of writing, the cookie name was _wafchallengeid
-        cookie_name = traverse_obj(webpage, (
+        # At time of writing, the wci cookie name was `_wafchallengeid`
+        wci_cookie_name = traverse_obj(webpage, (
             {find_element(id='wci', html=True)}, {extract_attributes},
             'class', {require('challenge cookie name')}))
 
-        # Actual JS sets Max-Age=1, but we need to adjust for --sleep-requests 
and Python slowness
-        expire_time = int(time.time()) + 
(self.get_param('sleep_interval_requests') or 0) + 2
-        self._set_cookie('.tiktok.com', cookie_name, cookie_value, 
expire_time=expire_time)
+        # At time of writing, the **optional** rci cookie name was 
`waforiginalreid`
+        rci_cookie_name = traverse_obj(webpage, (
+            {find_element(id='rci', html=True)}, {extract_attributes}, 
'class'))
+        rci_cookie_value = traverse_obj(webpage, (
+            {find_element(id='rs', html=True)}, {extract_attributes}, 'class'))
+
+        # Actual JS sets Max-Age=1 for the cookies, but we'll manually clear 
them later instead
+        expire_time = int(time.time()) + 
(self.get_param('sleep_interval_requests') or 0) + 120
+        self._set_cookie('.tiktok.com', wci_cookie_name, wci_cookie_value, 
expire_time=expire_time)
+        if rci_cookie_name and rci_cookie_value:
+            self._set_cookie('.tiktok.com', rci_cookie_name, rci_cookie_value, 
expire_time=expire_time)
+
+        return wci_cookie_name, rci_cookie_name
 
     def _extract_web_data_and_status(self, url, video_id, fatal=True):
         video_data, status = {}, -1
@@ -287,7 +297,7 @@
         universal_data = self._get_universal_data(webpage, video_id)
         if not universal_data:
             try:
-                self._solve_challenge_and_set_cookie(webpage)
+                cookie_names = self._solve_challenge_and_set_cookies(webpage)
             except ExtractorError as e:
                 if fatal:
                     raise
@@ -295,6 +305,9 @@
                 return video_data, status
 
             webpage = get_webpage(note='Downloading webpage with challenge 
cookie')
+            # Manually clear challenge cookies that should expire immediately 
after webpage request
+            for cookie_name in filter(None, cookie_names):
+                self.cookiejar.clear(domain='.tiktok.com', path='/', 
name=cookie_name)
             if webpage is False:
                 return video_data, status
             universal_data = self._get_universal_data(webpage, video_id)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/youtube/_base.py 
new/yt-dlp/yt_dlp/extractor/youtube/_base.py
--- old/yt-dlp/yt_dlp/extractor/youtube/_base.py        2026-03-03 
17:37:22.000000000 +0100
+++ new/yt-dlp/yt_dlp/extractor/youtube/_base.py        2026-03-13 
09:45:22.000000000 +0100
@@ -104,7 +104,6 @@
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
         'SUPPORTS_COOKIES': True,
-        'SUPPORTS_AD_PLAYBACK_CONTEXT': True,
         **WEB_PO_TOKEN_POLICIES,
     },
     # Safari UA returns pre-merged video+audio 144p/240p/360p/720p/1080p HLS 
formats
@@ -118,7 +117,6 @@
         },
         'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
         'SUPPORTS_COOKIES': True,
-        'SUPPORTS_AD_PLAYBACK_CONTEXT': True,
         **WEB_PO_TOKEN_POLICIES,
     },
     'web_embedded': {
@@ -223,16 +221,17 @@
         },
         'PLAYER_PO_TOKEN_POLICY': PlayerPoTokenPolicy(required=False, 
recommended=True),
     },
-    # YouTube Kids videos aren't returned on this client for some reason
+    # "Made for kids" videos aren't available with this client
+    # Using a clientVersion>1.65 may return SABR streams only
     'android_vr': {
         'INNERTUBE_CONTEXT': {
             'client': {
                 'clientName': 'ANDROID_VR',
-                'clientVersion': '1.71.26',
+                'clientVersion': '1.65.10',
                 'deviceMake': 'Oculus',
                 'deviceModel': 'Quest 3',
                 'androidSdkVersion': 32,
-                'userAgent': 
'com.google.android.apps.youtube.vr.oculus/1.71.26 (Linux; U; Android 12L; 
eureka-user Build/SQ3A.220605.009.A1) gzip',
+                'userAgent': 
'com.google.android.apps.youtube.vr.oculus/1.65.10 (Linux; U; Android 12L; 
eureka-user Build/SQ3A.220605.009.A1) gzip',
                 'osName': 'Android',
                 'osVersion': '12L',
             },
@@ -369,7 +368,7 @@
 
 def _fix_embedded_ytcfg(ytcfg):
     ytcfg['INNERTUBE_CONTEXT'].setdefault('thirdParty', {}).update({
-        'embedUrl': 'https://www.youtube.com/',  # Can be any valid URL
+        'embedUrl': 'https://www.reddit.com/',  # Can be any valid non-YouTube 
URL
     })
 
 
@@ -958,16 +957,25 @@
         url = {
             'mweb': 'https://m.youtube.com',
             'web': 'https://www.youtube.com',
+            'web_safari': 'https://www.youtube.com',
             'web_music': 'https://music.youtube.com',
+            'web_creator': 'https://studio.youtube.com',
             'web_embedded': 
f'https://www.youtube.com/embed/{video_id}?html5=1',
             'tv': 'https://www.youtube.com/tv',
         }.get(client)
         if not url:
             return {}
+
+        default_ytcfg = self._get_default_ytcfg(client)
+
+        if default_ytcfg['REQUIRE_AUTH'] and not self.is_authenticated:
+            return {}
+
         webpage = self._download_webpage_with_retries(
             url, video_id, note=f'Downloading {client.replace("_", " 
").strip()} client config',
-            headers=traverse_obj(self._get_default_ytcfg(client), {
+            headers=traverse_obj(default_ytcfg, {
                 'User-Agent': ('INNERTUBE_CONTEXT', 'client', 'userAgent', 
{str}),
+                'Referer': ('INNERTUBE_CONTEXT', 'thirdParty', 'embedUrl', 
{str}),
             }))
 
         ytcfg = self.extract_ytcfg(video_id, webpage) or {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/youtube/_tab.py 
new/yt-dlp/yt_dlp/extractor/youtube/_tab.py
--- old/yt-dlp/yt_dlp/extractor/youtube/_tab.py 2026-03-03 17:37:22.000000000 
+0100
+++ new/yt-dlp/yt_dlp/extractor/youtube/_tab.py 2026-03-13 09:45:22.000000000 
+0100
@@ -81,7 +81,7 @@
             'reelPlayerHeaderSupportedRenderers', 'reelPlayerHeaderRenderer'))
 
         title = self._get_text(renderer, 'title', 'headline') or 
self._get_text(reel_header_renderer, 'reelTitleText')
-        description = self._get_text(renderer, 'descriptionSnippet')
+        description = self._get_text(renderer, 'descriptionSnippet', 
('detailedMetadataSnippets', ..., 'snippetText'))
 
         duration = int_or_none(renderer.get('lengthSeconds'))
         if duration is None:
@@ -2148,7 +2148,7 @@
                     f'https://music.youtube.com/playlist?list={item_id[2:]}', 
YoutubeTabIE, item_id[2:])
             elif item_id[:2] == 'MP':  # Resolve albums 
(/[channel/browse]/MP...) to their equivalent playlist
                 mdata = self._extract_tab_endpoint(
-                    f'https://music.youtube.com/channel/{item_id}', item_id, 
default_client='web_music')
+                    f'https://music.youtube.com/browse/{item_id}', item_id, 
default_client='web_music')
                 murl = traverse_obj(mdata, ('microformat', 
'microformatDataRenderer', 'urlCanonical'),
                                     get_all=False, expected_type=str)
                 if not murl:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/extractor/youtube/_video.py 
new/yt-dlp/yt_dlp/extractor/youtube/_video.py
--- old/yt-dlp/yt_dlp/extractor/youtube/_video.py       2026-03-03 
17:37:22.000000000 +0100
+++ new/yt-dlp/yt_dlp/extractor/youtube/_video.py       2026-03-13 
09:45:22.000000000 +0100
@@ -140,11 +140,13 @@
     _RETURN_TYPE = 'video'  # XXX: How to handle multifeed?
 
     _SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'srt', 'vtt')
-    _DEFAULT_CLIENTS = ('android_vr', 'web', 'web_safari')
+    _DEFAULT_CLIENTS = ('android_vr', 'web_safari')
     _DEFAULT_JSLESS_CLIENTS = ('android_vr',)
-    _DEFAULT_AUTHED_CLIENTS = ('tv_downgraded', 'web', 'web_safari')
+    _DEFAULT_AUTHED_CLIENTS = ('tv_downgraded', 'web_safari')
     # Premium does not require POT (except for subtitles)
-    _DEFAULT_PREMIUM_CLIENTS = ('tv_downgraded', 'web_creator', 'web')
+    _DEFAULT_PREMIUM_CLIENTS = ('tv_downgraded', 'web_creator')
+    _WEBPAGE_CLIENTS = ('web', 'web_safari')
+    _DEFAULT_WEBPAGE_CLIENT = 'web_safari'
 
     _GEO_BYPASS = False
 
@@ -1873,12 +1875,7 @@
         'params': {'skip_download': True},
     }]
 
-    @property
-    def _skipped_webpage_data(self):
-        # XXX: player_response as a default is a TEMPORARY workaround for 
pinning _DEFAULT_PLAYER_JS_VERSION
-        return self._configuration_arg('webpage_skip', 
default=['player_response'])
-
-    _DEFAULT_PLAYER_JS_VERSION = '20514@9f4cc5e4'
+    _DEFAULT_PLAYER_JS_VERSION = 'actual'
     _DEFAULT_PLAYER_JS_VARIANT = 'tv'
     _PLAYER_JS_VARIANT_MAP = {
         'main': 'player_ias.vflset/en_US/base.js',
@@ -1895,6 +1892,18 @@
     }
     _INVERSE_PLAYER_JS_VARIANT_MAP = {v: k for k, v in 
_PLAYER_JS_VARIANT_MAP.items()}
 
+    @functools.cached_property
+    def _player_js_version(self):
+        return self._configuration_arg('player_js_version', [None])[0] or 
self._DEFAULT_PLAYER_JS_VERSION
+
+    @functools.cached_property
+    def _skipped_webpage_data(self):
+        skipped = set(self._configuration_arg('webpage_skip'))
+        # If forcing a player version, the webpage player response must be 
skipped
+        if self._player_js_version != 'actual':
+            skipped.add('player_response')
+        return skipped
+
     @classmethod
     def suitable(cls, url):
         from yt_dlp.utils import parse_qs
@@ -2082,15 +2091,14 @@
             time.sleep(max(0, FETCH_SPAN + fetch_time - time.time()))
 
     def _get_player_js_version(self):
-        player_js_version = self._configuration_arg('player_js_version', 
[''])[0] or self._DEFAULT_PLAYER_JS_VERSION
-        if player_js_version == 'actual':
+        if self._player_js_version == 'actual':
             return None, None
-        if not re.fullmatch(r'[0-9]{5,}@[0-9a-f]{8,}', player_js_version):
+        if not re.fullmatch(r'[0-9]{5,}@[0-9a-f]{8,}', 
self._player_js_version):
             self.report_warning(
-                f'Invalid player JS version "{player_js_version}" specified. '
+                f'Invalid player JS version "{self._player_js_version}" 
specified. '
                 f'It should be "actual" or in the format of STS@HASH', 
only_once=True)
             return None, None
-        return player_js_version.split('@')
+        return self._player_js_version.split('@')
 
     def _construct_player_url(self, *, player_id=None, player_url=None):
         assert player_id or player_url, '_construct_player_url must take one 
of player_id or player_url'
@@ -2680,12 +2688,14 @@
         return {'contentCheckOk': True, 'racyCheckOk': True}
 
     @classmethod
-    def _generate_player_context(cls, sts=None, use_ad_playback_context=False):
+    def _generate_player_context(cls, sts=None, use_ad_playback_context=False, 
encrypted_context=None):
         context = {
             'html5Preference': 'HTML5_PREF_WANTS',
         }
         if sts is not None:
             context['signatureTimestamp'] = sts
+        if encrypted_context:
+            context['encryptedHostFlags'] = encrypted_context
 
         playback_context = {
             'contentPlaybackContext': context,
@@ -2930,7 +2940,19 @@
             self._configuration_arg('use_ad_playback_context', ['false'])[0] 
!= 'false'
             and traverse_obj(INNERTUBE_CLIENTS, (client, 
'SUPPORTS_AD_PLAYBACK_CONTEXT', {bool})))
 
-        yt_query.update(self._generate_player_context(sts, 
use_ad_playback_context))
+        # web_embedded player requests may need to include encryptedHostFlags 
in its contentPlaybackContext.
+        # This can be detected with the 
embeds_enable_encrypted_host_flags_enforcement experiemnt flag,
+        # but there is no harm in including encryptedHostFlags with all 
web_embedded player requests.
+        encrypted_context = None
+        if _split_innertube_client(client)[2] == 'embedded':
+            encrypted_context = traverse_obj(player_ytcfg, (
+                'WEB_PLAYER_CONTEXT_CONFIGS', 
'WEB_PLAYER_CONTEXT_CONFIG_ID_EMBEDDED_PLAYER', 'encryptedHostFlags'))
+
+        yt_query.update(
+            self._generate_player_context(
+                sts=sts,
+                use_ad_playback_context=use_ad_playback_context,
+                encrypted_context=encrypted_context))
 
         return self._extract_response(
             item_id=video_id, ep='player', query=yt_query,
@@ -3880,7 +3902,12 @@
 
         base_url = self.http_scheme() + '//www.youtube.com/'
         webpage_url = base_url + 'watch?v=' + video_id
-        webpage_client = 'web'
+        webpage_client = self._configuration_arg('webpage_client', 
[self._DEFAULT_WEBPAGE_CLIENT])[0]
+        if webpage_client not in self._WEBPAGE_CLIENTS:
+            self.report_warning(
+                f'Invalid webpage_client "{webpage_client}" requested; '
+                f'falling back to {self._DEFAULT_WEBPAGE_CLIENT}', 
only_once=True)
+            webpage_client = self._DEFAULT_WEBPAGE_CLIENT
 
         webpage, webpage_ytcfg, initial_data, is_premium_subscriber, 
player_responses, player_url = self._initial_extract(
             url, smuggled_data, webpage_url, webpage_client, video_id)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py 
new/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py
--- old/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py    
2026-03-03 17:37:22.000000000 +0100
+++ new/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/_info.py    
2026-03-13 09:45:22.000000000 +0100
@@ -1,10 +1,10 @@
 # This file is generated by devscripts/update_ejs.py. DO NOT MODIFY!
 
-VERSION = '0.5.0'
+VERSION = '0.7.0'
 HASHES = {
     'yt.solver.bun.lib.js': 
'6ff45e94de9f0ea936a183c48173cfa9ce526ee4b7544cd556428427c1dd53c8073ef0174e79b320252bf0e7c64b0032cc1cf9c4358f3fda59033b7caa01c241',
-    'yt.solver.core.js': 
'9742868113d7b0c29e24a95c8eb2c2bec7cdf95513dc7f55f523ba053c0ecf2af7dcb0138b1d933578304f0dda633a6b3bfff64e912b4c547b99dad083428c4b',
-    'yt.solver.core.min.js': 
'aee8c3354cfd535809c871c2a517d03231f89cd184e903af82ee274bcc2e90991ef19cb3f65f2ccc858c4963856ea87f8692fe16d71209f4fc7f41c44b828e36',
+    'yt.solver.core.js': 
'84e91a8ae91684272d11f1ef0970c757e9fec9ab277fb415b976c156163dde6ae2a9857c19c1ee21c9dcd01e2f89071098a1de2dc3072cf3ceeded84537db5e4',
+    'yt.solver.core.min.js': 
'd965ec01dcf44a0a9dea43f5935141c788471de9e8def5bf70d0b88ca656b79ca983d3e595f84b788d921dc98b900b7bf7380e9775ccb3b70a87c865482c71e3',
     'yt.solver.deno.lib.js': 
'9c8ee3ab6c23e443a5a951e3ac73c6b8c1c8fb34335e7058a07bf99d349be5573611de00536dcd03ecd3cf34014c4e9b536081de37af3637c5390c6a6fd6a0f0',
     'yt.solver.lib.js': 
'1ee3753a8222fc855f5c39db30a9ccbb7967dbe1fb810e86dc9a89aa073a0907f294c720e9b65427d560a35aa1ce6af19ef854d9126a05ca00afe03f72047733',
     'yt.solver.lib.min.js': 
'8420c259ad16e99ce004e4651ac1bcabb53b4457bf5668a97a9359be9a998a789fee8ab124ee17f91a2ea8fd84e0f2b2fc8eabcaf0b16a186ba734cf422ad053',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js 
new/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js
--- old/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js   
2026-03-03 17:37:22.000000000 +0100
+++ new/yt-dlp/yt_dlp/extractor/youtube/jsc/_builtin/vendor/yt.solver.core.js   
2026-03-13 09:45:22.000000000 +0100
@@ -39,7 +39,10 @@
   function isOneOf(value, ...of) {
     return of.includes(value);
   }
-  function _optionalChain$2(ops) {
+  function generateArrowFunction(data) {
+    return meriyah.parse(data).body[0].expression;
+  }
+  function _optionalChain$1(ops) {
     let lastAccessLHS = undefined;
     let value = ops[0];
     let i = 1;
@@ -60,94 +63,7 @@
     }
     return value;
   }
-  const nsig = {
-    type: 'CallExpression',
-    callee: { or: [{ type: 'Identifier' }, { type: 'SequenceExpression' }] },
-    arguments: [
-      {},
-      {
-        type: 'CallExpression',
-        callee: { type: 'Identifier', name: 'decodeURIComponent' },
-        arguments: [{}],
-      },
-    ],
-  };
-  const nsigAssignment = {
-    type: 'AssignmentExpression',
-    left: { type: 'Identifier' },
-    operator: '=',
-    right: nsig,
-  };
-  const nsigDeclarator = {
-    type: 'VariableDeclarator',
-    id: { type: 'Identifier' },
-    init: nsig,
-  };
-  const logicalExpression = {
-    type: 'ExpressionStatement',
-    expression: {
-      type: 'LogicalExpression',
-      left: { type: 'Identifier' },
-      right: {
-        type: 'SequenceExpression',
-        expressions: [
-          {
-            type: 'AssignmentExpression',
-            left: { type: 'Identifier' },
-            operator: '=',
-            right: {
-              type: 'CallExpression',
-              callee: { type: 'Identifier' },
-              arguments: {
-                or: [
-                  [
-                    {
-                      type: 'CallExpression',
-                      callee: {
-                        type: 'Identifier',
-                        name: 'decodeURIComponent',
-                      },
-                      arguments: [{ type: 'Identifier' }],
-                      optional: false,
-                    },
-                  ],
-                  [
-                    { type: 'Literal' },
-                    {
-                      type: 'CallExpression',
-                      callee: {
-                        type: 'Identifier',
-                        name: 'decodeURIComponent',
-                      },
-                      arguments: [{ type: 'Identifier' }],
-                      optional: false,
-                    },
-                  ],
-                  [
-                    { type: 'Literal' },
-                    { type: 'Literal' },
-                    {
-                      type: 'CallExpression',
-                      callee: {
-                        type: 'Identifier',
-                        name: 'decodeURIComponent',
-                      },
-                      arguments: [{ type: 'Identifier' }],
-                      optional: false,
-                    },
-                  ],
-                ],
-              },
-              optional: false,
-            },
-          },
-          { type: 'CallExpression' },
-        ],
-      },
-      operator: '&&',
-    },
-  };
-  const identifier$1 = {
+  const identifier = {
     or: [
       {
         type: 'ExpressionStatement',
@@ -155,339 +71,108 @@
           type: 'AssignmentExpression',
           operator: '=',
           left: { or: [{ type: 'Identifier' }, { type: 'MemberExpression' }] },
-          right: { type: 'FunctionExpression' },
+          right: { type: 'FunctionExpression', async: false },
         },
       },
-      { type: 'FunctionDeclaration' },
+      { type: 'FunctionDeclaration', async: false, id: { type: 'Identifier' } 
},
       {
         type: 'VariableDeclaration',
         declarations: {
           anykey: [
             {
               type: 'VariableDeclarator',
-              init: { type: 'FunctionExpression' },
+              init: { type: 'FunctionExpression', async: false },
             },
           ],
         },
       },
     ],
   };
-  function extract$1(node) {
-    const blocks = [];
-    if (matchesStructure(node, identifier$1)) {
-      if (
-        node.type === 'ExpressionStatement' &&
-        node.expression.type === 'AssignmentExpression' &&
-        node.expression.right.type === 'FunctionExpression' &&
-        node.expression.right.params.length >= 3
-      ) {
-        blocks.push(node.expression.right.body);
-      } else if (node.type === 'VariableDeclaration') {
-        for (const decl of node.declarations) {
-          if (
-            _optionalChain$2([
-              decl,
-              'access',
-              (_) => _.init,
-              'optionalAccess',
-              (_2) => _2.type,
-            ]) === 'FunctionExpression' &&
-            decl.init.params.length >= 3
-          ) {
-            blocks.push(decl.init.body);
-          }
-        }
-      } else if (
-        node.type === 'FunctionDeclaration' &&
-        node.params.length >= 3
-      ) {
-        blocks.push(node.body);
-      } else {
-        return null;
-      }
-    } else if (
-      node.type === 'ExpressionStatement' &&
-      node.expression.type === 'SequenceExpression'
-    ) {
-      for (const expr of node.expression.expressions) {
-        if (
-          expr.type === 'AssignmentExpression' &&
-          expr.right.type === 'FunctionExpression' &&
-          expr.right.params.length === 3
-        ) {
-          blocks.push(expr.right.body);
-        }
-      }
-    } else {
-      return null;
-    }
-    for (const block of blocks) {
-      let call = null;
-      for (const stmt of block.body) {
-        if (matchesStructure(stmt, logicalExpression)) {
-          if (
-            stmt.type === 'ExpressionStatement' &&
-            stmt.expression.type === 'LogicalExpression' &&
-            stmt.expression.right.type === 'SequenceExpression' &&
-            stmt.expression.right.expressions[0].type ===
-              'AssignmentExpression' &&
-            stmt.expression.right.expressions[0].right.type === 
'CallExpression'
-          ) {
-            call = stmt.expression.right.expressions[0].right;
-          }
-        } else if (stmt.type === 'IfStatement') {
-          let consequent = stmt.consequent;
-          while (consequent.type === 'LabeledStatement') {
-            consequent = consequent.body;
-          }
-          if (consequent.type !== 'BlockStatement') {
-            continue;
-          }
-          for (const n of consequent.body) {
-            if (n.type !== 'VariableDeclaration') {
-              continue;
-            }
-            for (const decl of n.declarations) {
-              if (
-                matchesStructure(decl, nsigDeclarator) &&
-                _optionalChain$2([
-                  decl,
-                  'access',
-                  (_3) => _3.init,
-                  'optionalAccess',
-                  (_4) => _4.type,
-                ]) === 'CallExpression'
-              ) {
-                call = decl.init;
-                break;
-              }
-            }
-            if (call) {
-              break;
-            }
-          }
-        } else if (stmt.type === 'ExpressionStatement') {
-          if (
-            stmt.expression.type !== 'LogicalExpression' ||
-            stmt.expression.operator !== '&&' ||
-            stmt.expression.right.type !== 'SequenceExpression'
-          ) {
-            continue;
-          }
-          for (const expr of stmt.expression.right.expressions) {
-            if (matchesStructure(expr, nsigAssignment) && expr.type) {
-              if (
-                expr.type === 'AssignmentExpression' &&
-                expr.right.type === 'CallExpression'
-              ) {
-                call = expr.right;
-                break;
-              }
-            }
-          }
-        }
-        if (call) {
-          break;
-        }
-      }
-      if (!call) {
-        continue;
-      }
-      return {
-        type: 'ArrowFunctionExpression',
-        params: [{ type: 'Identifier', name: 'sig' }],
-        body: {
-          type: 'CallExpression',
-          callee: call.callee,
-          arguments: call.arguments.map((arg) => {
-            if (
-              arg.type === 'CallExpression' &&
-              arg.callee.type === 'Identifier' &&
-              arg.callee.name === 'decodeURIComponent'
-            ) {
-              return { type: 'Identifier', name: 'sig' };
-            }
-            return arg;
-          }),
-          optional: false,
-        },
-        async: false,
-        expression: false,
-        generator: false,
-      };
-    }
-    return null;
-  }
-  function _optionalChain$1(ops) {
-    let lastAccessLHS = undefined;
-    let value = ops[0];
-    let i = 1;
-    while (i < ops.length) {
-      const op = ops[i];
-      const fn = ops[i + 1];
-      i += 2;
-      if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) 
{
-        return undefined;
-      }
-      if (op === 'access' || op === 'optionalAccess') {
-        lastAccessLHS = value;
-        value = fn(value);
-      } else if (op === 'call' || op === 'optionalCall') {
-        value = fn((...args) => value.call(lastAccessLHS, ...args));
-        lastAccessLHS = undefined;
-      }
-    }
-    return value;
-  }
-  const identifier = {
-    or: [
-      {
-        type: 'VariableDeclaration',
-        kind: 'var',
-        declarations: {
-          anykey: [
-            {
-              type: 'VariableDeclarator',
-              id: { type: 'Identifier' },
-              init: {
-                type: 'ArrayExpression',
-                elements: [{ type: 'Identifier' }],
-              },
-            },
-          ],
-        },
-      },
-      {
-        type: 'ExpressionStatement',
-        expression: {
-          type: 'AssignmentExpression',
-          left: { type: 'Identifier' },
-          operator: '=',
-          right: {
-            type: 'ArrayExpression',
-            elements: [{ type: 'Identifier' }],
-          },
-        },
-      },
-    ],
-  };
-  const catchBlockBody = [
-    {
-      type: 'ReturnStatement',
-      argument: {
-        type: 'BinaryExpression',
-        left: {
-          type: 'MemberExpression',
-          object: { type: 'Identifier' },
-          computed: true,
-          property: { type: 'Literal' },
-          optional: false,
-        },
-        right: { type: 'Identifier' },
-        operator: '+',
+  const asdasd = {
+    type: 'ExpressionStatement',
+    expression: {
+      type: 'CallExpression',
+      callee: {
+        type: 'MemberExpression',
+        object: { type: 'Identifier' },
+        property: {},
+        optional: false,
       },
+      arguments: [
+        { type: 'Literal', value: 'alr' },
+        { type: 'Literal', value: 'yes' },
+      ],
+      optional: false,
     },
-  ];
+  };
   function extract(node) {
     if (!matchesStructure(node, identifier)) {
-      let name = null;
-      let block = null;
-      switch (node.type) {
-        case 'ExpressionStatement': {
-          if (
-            node.expression.type === 'AssignmentExpression' &&
-            node.expression.left.type === 'Identifier' &&
-            node.expression.right.type === 'FunctionExpression' &&
-            node.expression.right.params.length === 1
-          ) {
-            name = node.expression.left.name;
-            block = node.expression.right.body;
-          }
-          break;
-        }
-        case 'FunctionDeclaration': {
-          if (node.params.length === 1) {
-            name = _optionalChain$1([
-              node,
-              'access',
-              (_) => _.id,
-              'optionalAccess',
-              (_2) => _2.name,
-            ]);
-            block = node.body;
-          }
-          break;
-        }
-      }
-      if (!block || !name) {
-        return null;
-      }
-      const tryNode = block.body.at(-2);
+      return null;
+    }
+    const options = [];
+    if (node.type === 'FunctionDeclaration') {
       if (
-        _optionalChain$1([tryNode, 'optionalAccess', (_3) => _3.type]) !==
-          'TryStatement' ||
+        node.id &&
         _optionalChain$1([
-          tryNode,
+          node,
           'access',
-          (_4) => _4.handler,
+          (_) => _.body,
           'optionalAccess',
-          (_5) => _5.type,
-        ]) !== 'CatchClause'
+          (_2) => _2.body,
+        ])
       ) {
+        options.push({
+          name: node.id,
+          statements: _optionalChain$1([
+            node,
+            'access',
+            (_3) => _3.body,
+            'optionalAccess',
+            (_4) => _4.body,
+          ]),
+        });
+      }
+    } else if (node.type === 'ExpressionStatement') {
+      if (node.expression.type !== 'AssignmentExpression') {
         return null;
       }
-      const catchBody = tryNode.handler.body.body;
-      if (matchesStructure(catchBody, catchBlockBody)) {
-        return makeSolverFuncFromName(name);
+      const name = node.expression.left;
+      const body = _optionalChain$1([
+        node.expression.right,
+        'optionalAccess',
+        (_5) => _5.body,
+        'optionalAccess',
+        (_6) => _6.body,
+      ]);
+      if (name && body) {
+        options.push({ name: name, statements: body });
       }
-      return null;
-    }
-    if (node.type === 'VariableDeclaration') {
+    } else if (node.type === 'VariableDeclaration') {
       for (const declaration of node.declarations) {
-        if (
-          declaration.type !== 'VariableDeclarator' ||
-          !declaration.init ||
-          declaration.init.type !== 'ArrayExpression' ||
-          declaration.init.elements.length !== 1
-        ) {
-          continue;
-        }
-        const [firstElement] = declaration.init.elements;
-        if (firstElement && firstElement.type === 'Identifier') {
-          return makeSolverFuncFromName(firstElement.name);
+        const name = declaration.id;
+        const body = _optionalChain$1([
+          declaration.init,
+          'optionalAccess',
+          (_7) => _7.body,
+          'optionalAccess',
+          (_8) => _8.body,
+        ]);
+        if (name && body) {
+          options.push({ name: name, statements: body });
         }
       }
-    } else if (node.type === 'ExpressionStatement') {
-      const expr = node.expression;
-      if (
-        expr.type === 'AssignmentExpression' &&
-        expr.left.type === 'Identifier' &&
-        expr.operator === '=' &&
-        expr.right.type === 'ArrayExpression' &&
-        expr.right.elements.length === 1
-      ) {
-        const [firstElement] = expr.right.elements;
-        if (firstElement && firstElement.type === 'Identifier') {
-          return makeSolverFuncFromName(firstElement.name);
-        }
+    }
+    for (const { name: name, statements: statements } of options) {
+      if (matchesStructure(statements, { anykey: [asdasd] })) {
+        return createSolver(name);
       }
     }
     return null;
   }
-  function makeSolverFuncFromName(name) {
-    return {
-      type: 'ArrowFunctionExpression',
-      params: [{ type: 'Identifier', name: 'n' }],
-      body: {
-        type: 'CallExpression',
-        callee: { type: 'Identifier', name: name },
-        arguments: [{ type: 'Identifier', name: 'n' }],
-        optional: false,
-      },
-      async: false,
-      expression: false,
-      generator: false,
-    };
+  function createSolver(expression) {
+    return generateArrowFunction(
+      `\n({sig, n}) => {\n  const url = 
(${astring.generate(expression)})("https://youtube.com/watch?v=yt-dlp-wins";, 
"s", sig ? encodeURIComponent(sig) : undefined);\n  url.set("n", n);\n  const 
proto = Object.getPrototypeOf(url);\n  const keys = 
Object.keys(proto).concat(Object.getOwnPropertyNames(proto));\n  for (const key 
of keys) {\n    if (!["constructor", "set", "get", "clone"].includes(key)) {\n  
    url[key]();\n      break;\n    }\n  }\n  const s = url.get("s");\n  return 
{\n    sig: s ? decodeURIComponent(s) : null,\n    n: url.get("n") ?? null,\n  
};\n}\n`,
+    );
   }
   const setupNodes = meriyah.parse(
     `\nif (typeof globalThis.XMLHttpRequest === "undefined") {\n    
globalThis.XMLHttpRequest = { prototype: {} };\n}\nconst window = 
Object.create(null);\nif (typeof URL === "undefined") {\n    window.location = 
{\n        hash: "",\n        host: "www.youtube.com",\n        hostname: 
"www.youtube.com",\n        href: 
"https://www.youtube.com/watch?v=yt-dlp-wins",\n        origin: 
"https://www.youtube.com",\n        password: "",\n        pathname: 
"/watch",\n        port: "",\n        protocol: "https:",\n        search: 
"?v=yt-dlp-wins",\n        username: "",\n    };\n} else {\n    window.location 
= new URL("https://www.youtube.com/watch?v=yt-dlp-wins";);\n}\nif (typeof 
globalThis.document === "undefined") {\n    globalThis.document = 
Object.create(null);\n}\nif (typeof globalThis.navigator === "undefined") {\n   
 globalThis.navigator = Object.create(null);\n}\nif (typeof globalThis.self === 
"undefined") {\n    globalThis.self = globalThis;\n}\n`,
@@ -585,236 +270,60 @@
   function getSolutions(statements) {
     const found = { n: [], sig: [] };
     for (const statement of statements) {
-      const n = extract(statement);
-      if (n) {
-        found.n.push(n);
-      }
-      const sig = extract$1(statement);
-      if (sig) {
-        found.sig.push(sig);
+      const result = extract(statement);
+      if (result) {
+        found.n.push(makeSolver(result, { type: 'Identifier', name: 'n' }));
+        found.sig.push(makeSolver(result, { type: 'Identifier', name: 'sig' 
}));
       }
     }
     return found;
   }
-  function getFromPrepared(code) {
-    const resultObj = { n: null, sig: null };
-    Function('_result', code)(resultObj);
-    return resultObj;
-  }
-  function multiTry(generators) {
+  function makeSolver(result, ident) {
     return {
       type: 'ArrowFunctionExpression',
-      params: [{ type: 'Identifier', name: '_input' }],
+      params: [ident],
       body: {
-        type: 'BlockStatement',
-        body: [
-          {
-            type: 'VariableDeclaration',
-            kind: 'const',
-            declarations: [
-              {
-                type: 'VariableDeclarator',
-                id: { type: 'Identifier', name: '_results' },
-                init: {
-                  type: 'NewExpression',
-                  callee: { type: 'Identifier', name: 'Set' },
-                  arguments: [],
-                },
-              },
-            ],
-          },
-          {
-            type: 'ForOfStatement',
-            left: {
-              type: 'VariableDeclaration',
-              kind: 'const',
-              declarations: [
-                {
-                  type: 'VariableDeclarator',
-                  id: { type: 'Identifier', name: '_generator' },
-                  init: null,
-                },
-              ],
-            },
-            right: { type: 'ArrayExpression', elements: generators },
-            body: {
-              type: 'BlockStatement',
-              body: [
-                {
-                  type: 'TryStatement',
-                  block: {
-                    type: 'BlockStatement',
-                    body: [
-                      {
-                        type: 'ExpressionStatement',
-                        expression: {
-                          type: 'CallExpression',
-                          callee: {
-                            type: 'MemberExpression',
-                            object: { type: 'Identifier', name: '_results' },
-                            computed: false,
-                            property: { type: 'Identifier', name: 'add' },
-                            optional: false,
-                          },
-                          arguments: [
-                            {
-                              type: 'CallExpression',
-                              callee: {
-                                type: 'Identifier',
-                                name: '_generator',
-                              },
-                              arguments: [
-                                { type: 'Identifier', name: '_input' },
-                              ],
-                              optional: false,
-                            },
-                          ],
-                          optional: false,
-                        },
-                      },
-                    ],
-                  },
-                  handler: {
-                    type: 'CatchClause',
-                    param: null,
-                    body: { type: 'BlockStatement', body: [] },
-                  },
-                  finalizer: null,
-                },
-              ],
-            },
-            await: false,
-          },
-          {
-            type: 'IfStatement',
-            test: {
-              type: 'UnaryExpression',
-              operator: '!',
-              argument: {
-                type: 'MemberExpression',
-                object: { type: 'Identifier', name: '_results' },
-                computed: false,
-                property: { type: 'Identifier', name: 'size' },
-                optional: false,
-              },
-              prefix: true,
-            },
-            consequent: {
-              type: 'BlockStatement',
-              body: [
-                {
-                  type: 'ThrowStatement',
-                  argument: {
-                    type: 'TemplateLiteral',
-                    expressions: [],
-                    quasis: [
-                      {
-                        type: 'TemplateElement',
-                        value: { cooked: 'no solutions', raw: 'no solutions' },
-                        tail: true,
-                      },
-                    ],
-                  },
-                },
-              ],
-            },
-            alternate: null,
-          },
-          {
-            type: 'IfStatement',
-            test: {
-              type: 'BinaryExpression',
-              left: {
-                type: 'MemberExpression',
-                object: { type: 'Identifier', name: '_results' },
-                computed: false,
-                property: { type: 'Identifier', name: 'size' },
-                optional: false,
-              },
-              right: { type: 'Literal', value: 1 },
-              operator: '!==',
-            },
-            consequent: {
-              type: 'BlockStatement',
-              body: [
+        type: 'MemberExpression',
+        object: {
+          type: 'CallExpression',
+          callee: result,
+          arguments: [
+            {
+              type: 'ObjectExpression',
+              properties: [
                 {
-                  type: 'ThrowStatement',
-                  argument: {
-                    type: 'TemplateLiteral',
-                    expressions: [
-                      {
-                        type: 'CallExpression',
-                        callee: {
-                          type: 'MemberExpression',
-                          object: { type: 'Identifier', name: '_results' },
-                          computed: false,
-                          property: { type: 'Identifier', name: 'join' },
-                          optional: false,
-                        },
-                        arguments: [{ type: 'Literal', value: ', ' }],
-                        optional: false,
-                      },
-                    ],
-                    quasis: [
-                      {
-                        type: 'TemplateElement',
-                        value: {
-                          cooked: 'invalid solutions: ',
-                          raw: 'invalid solutions: ',
-                        },
-                        tail: false,
-                      },
-                      {
-                        type: 'TemplateElement',
-                        value: { cooked: '', raw: '' },
-                        tail: true,
-                      },
-                    ],
-                  },
-                },
-              ],
-            },
-            alternate: null,
-          },
-          {
-            type: 'ReturnStatement',
-            argument: {
-              type: 'MemberExpression',
-              object: {
-                type: 'CallExpression',
-                callee: {
-                  type: 'MemberExpression',
-                  object: {
-                    type: 'CallExpression',
-                    callee: {
-                      type: 'MemberExpression',
-                      object: { type: 'Identifier', name: '_results' },
-                      computed: false,
-                      property: { type: 'Identifier', name: 'values' },
-                      optional: false,
-                    },
-                    arguments: [],
-                    optional: false,
-                  },
+                  type: 'Property',
+                  key: ident,
+                  value: ident,
+                  kind: 'init',
                   computed: false,
-                  property: { type: 'Identifier', name: 'next' },
-                  optional: false,
+                  method: false,
+                  shorthand: true,
                 },
-                arguments: [],
-                optional: false,
-              },
-              computed: false,
-              property: { type: 'Identifier', name: 'value' },
-              optional: false,
+              ],
             },
-          },
-        ],
+          ],
+          optional: false,
+        },
+        computed: false,
+        property: ident,
+        optional: false,
       },
       async: false,
-      expression: false,
+      expression: true,
       generator: false,
     };
   }
+  function getFromPrepared(code) {
+    const resultObj = { n: null, sig: null };
+    Function('_result', code)(resultObj);
+    return resultObj;
+  }
+  function multiTry(generators) {
+    return generateArrowFunction(
+      `\n(_input) => {\n  const _results = new Set();\n  const errors = [];\n  
for (const _generator of ${astring.generate({ type: 'ArrayExpression', 
elements: generators })}) {\n    try {\n      
_results.add(_generator(_input));\n    } catch (e) {\n      errors.push(e);\n   
 }\n  }\n  if (!_results.size) {\n    throw \`no solutions: \${errors.join(", 
")}\`;\n  }\n  if (_results.size !== 1) {\n    throw \`invalid solutions: 
\${[..._results].map(x => JSON.stringify(x)).join(", ")}\`;\n  }\n  return 
_results.values().next().value;\n}\n`,
+    );
+  }
   function main(input) {
     const preprocessedPlayer =
       input.type === 'player'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yt-dlp/yt_dlp/version.py new/yt-dlp/yt_dlp/version.py
--- old/yt-dlp/yt_dlp/version.py        2026-03-03 17:37:32.000000000 +0100
+++ new/yt-dlp/yt_dlp/version.py        2026-03-13 09:45:29.000000000 +0100
@@ -1,8 +1,8 @@
 # Autogenerated by devscripts/update-version.py
 
-__version__ = '2026.03.03'
+__version__ = '2026.03.13'
 
-RELEASE_GIT_HEAD = '2ecc4c3bc300701d85e2cbaeb2b28a921a68f0f0'
+RELEASE_GIT_HEAD = '92f1d99dbe1e10d942ef0963f625dbc5bc0768aa'
 
 VARIANT = None
 
@@ -12,4 +12,4 @@
 
 ORIGIN = 'yt-dlp/yt-dlp'
 
-_pkg_version = '2026.03.03'
+_pkg_version = '2026.03.13'

Reply via email to