@@ -130,6 +130,10 @@ namespace Ytdl {
130130
131131 private const string UA = " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" ;
132132
133+ // Forced player version — must match what the EJS solver can handle.
134+ // Update this when yt-dlp updates _DEFAULT_PLAYER_JS_VERSION.
135+ private const string FORCED_PLAYER_ID = " 9f4cc5e4" ;
136+
133137 /**
134138 * Extract a playable download URL for a YouTube video.
135139 * Returns a VideoInfo with title and direct download URL.
@@ -138,20 +142,31 @@ namespace Ytdl {
138142 public VideoInfo extract (Soup .Session session , string video_id_or_url ) throws Error {
139143 string video_id = parse_video_id (video_id_or_url);
140144
141- // 1. Fetch watch page → player JS URL
145+ // 1. Fetch watch page
142146 string ? page = http_get (session, " https://www.youtube.com/watch?v=" + video_id);
143147 if (page == null ) throw new IOError .FAILED (" Could not fetch watch page" );
144148
145- string ? player_url = null ;
146- var re = new Regex (" /s/player/[a-f0-9]+/[^\" ]+base\\ .js" );
149+ // 2. Extract player JS URL from watch page as fallback
150+ string ? page_player_url = null ;
151+ var re = new Regex (" /s/player/[a-f0-9]+/[^\" ]+(?:base|tv-player-ias)\\ .js" );
147152 MatchInfo mi;
148153 if (re. match (page, 0 , out mi)) {
149- player_url = " https://www.youtube.com" + mi. fetch (0 );
154+ page_player_url = " https://www.youtube.com" + mi. fetch (0 );
150155 }
151- if (player_url == null ) throw new IOError .FAILED (" Could not find player JS URL" );
152156
153- // 2. Download player JS → extract STS
154- string ? base_js = http_get (session, player_url);
157+ // Force known-good player version (tv variant) — yt-dlp does the same
158+ string forced_player_url = " https://www.youtube.com/s/player/" + FORCED_PLAYER_ID
159+ + " /tv-player-ias.vflset/tv-player-ias.js" ;
160+ string ? player_url = null ;
161+
162+ // Try forced player first, then fallback to page player
163+ string ? base_js = http_get (session, forced_player_url);
164+ if (base_js != null ) {
165+ player_url = forced_player_url;
166+ } else if (page_player_url != null ) {
167+ base_js = http_get (session, page_player_url);
168+ player_url = page_player_url;
169+ }
155170 if (base_js == null ) throw new IOError .FAILED (" Could not download player JS" );
156171
157172 string sts = " 0" ;
0 commit comments