diff --git a/rust/strawcore/src/stream.rs b/rust/strawcore/src/stream.rs index 8f550b7f3..1c28fc2b4 100644 --- a/rust/strawcore/src/stream.rs +++ b/rust/strawcore/src/stream.rs @@ -129,19 +129,15 @@ pub async fn stream_info(url: String) -> Result { log::info!("strawcore::stream_info id={}", id); let rp = RustyPipe::new(); - // rustypipe's default `player()` uses the Web client first, which - // returns signed URLs that need JS deobfuscation. Even the TV (TVHTML5) - // client signs URLs nowadays, so deobfuscation runs and currently - // fails ("could not extract sig fn name") because YT changed the - // obfuscation pattern after rustypipe 0.11.4's last cut. - // - // Android and iOS YT-app clients serve URLs UNSIGNED — no sig - // decryption needed, ExoPlayer plays them directly. This is the same - // path NewPipe uses for its mobile + iOS-embed strategies. - let player = rp - .query() - .player_from_clients(&id, &[ClientType::Android, ClientType::Ios]) - .await?; + // Use the fork's audit-fixed default client order. As of + // v0.11.5-sulkta.2 that's [Ios, Tv] without botguard — iOS first + // because it skips player.js deobfuscation AND doesn't require + // device attestation. Android is intentionally NOT in the default + // order: needs_po_token doesn't flag Android, so unsigned requests + // get YT's "Precondition check failed" / "Sign in to confirm + // you're not a bot" rejection, which is environmental-non-switchable. + // Re-add Android when a real po_token strategy lands. + let player = rp.query().player(&id).await?; let details = &player.details; // Progressive (combined audio+video) goes through video_streams; the