Some checks failed
gitleaks / scan (push) Failing after 5s
YouTube's 2026 poToken/BotGuard enforcement now rejects the pot-less ANDROID client outright (playabilityStatus "sign in to confirm you're not a bot"), which aborted the whole extraction since ANDROID was the required primary. stream_info_with() now cascades ANDROID -> VISIONOS for the primary player response: when ANDROID is unusable (fetch error, failed playability, or decoy), retry with VISIONOS (client 101) as the primary. VISIONOS is pot-free, visitorData-based, and needs no JS player -- the current survivor (yt-dlp default; NewPipeExtractor #1508). Only if VISIONOS also fails do we surface the ORIGINAL ANDROID error (keeps the real bot-wall reason visible). The fallback drops the (poisoned) visitorData cache first so VISIONOS mints a fresh one (the ingredient that passes attestation). On the VISIONOS-primary path the primary source carries no poToken (null) and uses the VISIONOS cpn, so no ANDROID pot/cpn is appended to a visionOS URL (would 403); the redundant add-on VISIONOS fetch is skipped. Output shape is unchanged (still the muxed itag-18 the app plays) -- no app or delivery-labeling change. 5 new unit tests.
50 lines
1.6 KiB
Rust
50 lines
1.6 KiB
Rust
// Throwaway live diagnostic (playback-outage triage). Not shipped.
|
|
use std::sync::Arc;
|
|
use strawcore_core::downloader::ReqwestDownloader;
|
|
use strawcore_core::youtube::stream_extractor::{stream_info_with, ExtractOptions};
|
|
use strawcore_core::NewPipe;
|
|
|
|
fn client_of(url: &str) -> String {
|
|
url.split('&')
|
|
.find_map(|kv| kv.strip_prefix("c="))
|
|
.unwrap_or("?")
|
|
.to_string()
|
|
}
|
|
|
|
fn report(label: &str, vid: &str, visionos: bool) {
|
|
let opts = ExtractOptions {
|
|
fetch_visionos_client: visionos,
|
|
..Default::default()
|
|
};
|
|
match stream_info_with(vid, opts) {
|
|
Ok(i) => {
|
|
let a = i.audio_streams.first().map(|s| client_of(&s.url));
|
|
let v = i
|
|
.video_streams
|
|
.first()
|
|
.or_else(|| i.video_only_streams.first())
|
|
.map(|s| client_of(&s.url));
|
|
println!(
|
|
"[{label}] OK audio={} video={} video_only={} dash={} hls={} | first audio c={:?} first video c={:?}",
|
|
i.audio_streams.len(),
|
|
i.video_streams.len(),
|
|
i.video_only_streams.len(),
|
|
i.dash_manifest_url.is_some(),
|
|
i.hls_manifest_url.is_some(),
|
|
a,
|
|
v,
|
|
);
|
|
}
|
|
Err(e) => println!("[{label}] ERR {e:?}"),
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let dl = Arc::new(ReqwestDownloader::new().expect("downloader"));
|
|
NewPipe::init(dl);
|
|
let vid = std::env::args()
|
|
.nth(1)
|
|
.unwrap_or_else(|| "dQw4w9WgXcQ".into());
|
|
report("visionOS ON (shipped)", &vid, true);
|
|
report("visionOS OFF (like 91) ", &vid, false);
|
|
}
|