// Differential-verification JSON emitter (Phase-1 harness, NOT shipped). // // Additive example only — adds no production code. Emits strawcore's // extraction for one video id as the harness's normalized JSON schema on // stdout, so it can be diffed against the upstream NewPipe-Extractor (Java) // oracle. See /root/build/npe-diff/ for the driver + differ. // // cargo run --example emit_json -- [visionos-on] // // Default matches the shipped app path (ExtractOptions::default(), visionOS // OFF). Pass `visionos-on` to fetch the visionOS client (client 101) — that // is what upstream NPE does UNCONDITIONALLY, so `visionos-on` is the // apples-to-apples mode for an NPE fidelity diff. use std::sync::Arc; use serde_json::{json, Value}; use strawcore_core::stream::{AudioStream, DeliveryMethod, StreamInfo, VideoStream}; use strawcore_core::youtube::stream_extractor::{stream_info_with, ExtractOptions}; use strawcore_core::NewPipe; /// Parse the innertube client tag (`&c=WEB` / `&c=ANDROID` / ...) off a /// googlevideo URL — this is the "which client sourced this stream" signal /// that made the visionOS outage visible. fn client_source(url: &str) -> Value { url.split(['&', '?']) .find_map(|kv| kv.strip_prefix("c=")) .map(|c| Value::String(c.to_string())) .unwrap_or(Value::Null) } fn delivery_str(d: DeliveryMethod) -> &'static str { match d { DeliveryMethod::Progressive => "progressive", DeliveryMethod::Dash => "dash", DeliveryMethod::Hls => "hls", DeliveryMethod::Torrent => "torrent", } } fn video_json(s: &VideoStream, kind: &str) -> Value { json!({ "kind": kind, "itag": s.itag, "delivery": delivery_str(s.delivery), "format": s.format.extension(), "mime": s.format.mime(), "codec": s.codec, "resolution": if s.resolution.is_empty() { Value::Null } else { json!(s.resolution) }, "fps": s.fps, "bitrate": s.bandwidth, "has_url": !s.url.is_empty(), "client_source": client_source(&s.url), }) } fn audio_json(s: &AudioStream) -> Value { json!({ "kind": "audio", "itag": s.itag, "delivery": delivery_str(s.delivery), "format": s.format.extension(), "mime": s.format.mime(), "codec": s.codec, "resolution": Value::Null, "fps": 0, "bitrate": s.average_bitrate_kbps, "has_url": !s.url.is_empty(), "client_source": client_source(&s.url), }) } fn emit(info: &StreamInfo) -> Value { let mut streams: Vec = Vec::new(); for s in &info.video_streams { streams.push(video_json(s, "muxed")); } for s in &info.video_only_streams { streams.push(video_json(s, "video_only")); } for s in &info.audio_streams { streams.push(audio_json(s)); } // Deterministic order so diffs are stable: (kind, itag, delivery). streams.sort_by(|a, b| { ( a["kind"].as_str().unwrap_or(""), a["itag"].as_u64().unwrap_or(0), a["delivery"].as_str().unwrap_or(""), ) .cmp(&( b["kind"].as_str().unwrap_or(""), b["itag"].as_u64().unwrap_or(0), b["delivery"].as_str().unwrap_or(""), )) }); json!({ "source": "strawcore", "video_id": info.video_id, "meta": { "name": info.name, "duration_seconds": info.duration_seconds, "stream_type": format!("{:?}", info.stream_type), "uploader_id": info.uploader_id, "uploader_name": info.uploader_name, "view_count": info.view_count, }, "dash_present": info.dash_manifest_url.is_some(), "hls_present": info.hls_manifest_url.is_some(), "counts": { "muxed": info.video_streams.len(), "video_only": info.video_only_streams.len(), "audio": info.audio_streams.len(), }, "streams": streams, }) } fn main() { let mut args = std::env::args().skip(1); let vid = args.next().unwrap_or_else(|| "dQw4w9WgXcQ".into()); let visionos = args.next().as_deref() == Some("visionos-on"); let dl = Arc::new(strawcore_core::downloader::ReqwestDownloader::new().expect("build downloader")); NewPipe::init(dl); let opts = ExtractOptions { fetch_visionos_client: visionos, ..Default::default() }; match stream_info_with(&vid, opts) { Ok(info) => { println!("{}", serde_json::to_string_pretty(&emit(&info)).unwrap()); } Err(e) => { eprintln!("strawcore extraction FAILED for {vid}: {e:?}"); std::process::exit(2); } } }