Phase 4 (partial) — stream value types + InnerTube /player helpers

Lands the data shapes + the HTTP layer for stream extraction. The
extractor orchestrator + DASH manifest creator are deferred to the
next session — the parsing logic is dense enough to want a focused
pass.

src/stream/
  * mod.rs       — StreamInfo + StreamInfoItem (full + 'card' shapes)
                   mirroring NPE StreamInfo.java + StreamInfoItem.java
  * delivery.rs  — DeliveryMethod (Progressive/Dash/Hls/Torrent)
  * audio.rs     — AudioStream (itag, format, url, bitrate, codec,
                   audio_track_id, content_length, etc.)
  * video.rs     — VideoStream (itag, format, url, resolution, fps,
                   bandwidth, codec, video_only flag)
  * subtitles.rs — SubtitlesStream (url, lang, auto_generated, mime)

src/youtube/stream_helper.rs
  * generate_content_playback_nonce() — 16-char LCG-shuffled cpn
  * get_web_metadata_player_response       (microformat + thumbnails only)
  * get_web_embedded_player_response       (embed-url + signatureTimestamp)
  * get_android_player_response            (full Android /player + poToken)
  * get_android_reel_player_response       (no-poToken fallback)
  * get_ios_player_response                (iOS — flagged with 917 KiB cap
                                            warning in the doc comment)

Per-helper headers + URL shapes match audit Track C §2.7 verbatim:
Android/iOS hit gapis endpoint with mobile UA; WEB family hits
www.youtube.com with the WEB headers.

Tests: 64 lib unit pass (up from 62 in Phase 3).

Next session: full stream_extractor.rs orchestrator + dash_manifest/
creator + Phase 4 done-when smoke (extract NCS Spektrem).
This commit is contained in:
Sulkta 2026-05-24 17:01:03 -07:00
parent fb70166f5d
commit 589e7446c3
9 changed files with 419 additions and 1 deletions

20
src/stream/audio.rs Normal file
View file

@ -0,0 +1,20 @@
// AudioStream — one DASH or progressive audio variant.
use crate::stream::DeliveryMethod;
use crate::youtube::itag::MediaFormat;
#[derive(Clone, Debug)]
pub struct AudioStream {
pub itag: u32,
pub url: String,
pub format: MediaFormat,
pub delivery: DeliveryMethod,
pub average_bitrate_kbps: Option<u32>,
pub codec: Option<String>,
pub content_length_bytes: Option<i64>,
pub audio_track_id: Option<String>,
pub audio_track_name: Option<String>,
pub audio_locale: Option<String>,
pub is_descriptive: bool,
pub itag_url_format: Option<String>,
}