strawcore/src/stream/audio.rs
Cobb 2452f1785d
Some checks failed
gitleaks / scan (push) Failing after 1s
npe-sync: visitorData + visionOS(101) + xtags audio typing (best-effort, additive)
Brings the port up to current NewPipe Extractor coverage:
- visitorData: fetched + attached to the anonymous reel/web/ios/visionos
  InnerTube contexts (upstream "always pass a valid visitorData"). Best-effort
  — a failure returns None and extraction proceeds exactly as before. Cached
  process-wide with a 15-min TTL, and invalidated when the primary android
  response is rejected (decoy/playability) so a bad session self-heals.
- visionOS client (101): a 4th /player fetch, ON by default, recovering >360p
  streams for SABR-only / made-for-kids videos where android/ios cap at 360p.
  Formats merged android-first (android wins itag ties); a failure changes
  nothing. HLS + DASH manifest branches now skip empty urls (an empty visionOS
  url no longer shadows a real ios/android one).
- xtags: derive audio track type (original/dubbed/descriptive/secondary) from
  the format xtags protobuf, falling back to the audioIsDefault heuristic when
  absent. Hand-rolled protobuf walker, fuzzed (4M inputs, no panic); 32-bit
  length guarded via try_from.

FFI surface unchanged (AudioStream gains an additive track_type the wrapper
may later surface). 155 lib + 7 integration tests, clippy -D clean.
2026-07-29 07:07:42 -07:00

41 lines
1.6 KiB
Rust

// AudioStream — one DASH or progressive audio variant.
use crate::stream::DeliveryMethod;
use crate::youtube::itag::MediaFormat;
/// The track type of an [`AudioStream`]. Mirrors NPE
/// `stream/AudioTrackType.java`; derived from the format's `xtags` protobuf
/// (`acont` key) — see `youtube::xtags`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum AudioTrackType {
/// The original audio track of a video.
Original,
/// The original voices replaced, typically in a different language.
Dubbed,
/// A descriptive (audio-description) track for accessibility.
Descriptive,
/// A secondary track (e.g. an alternate/commentary track).
Secondary,
}
#[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>,
/// True iff this is a descriptive (audio-description) track. Preferentially
/// derived from `xtags` (`acont == descriptive`); falls back to the legacy
/// `audioTrack.audioIsDefault` heuristic when `xtags` is absent/unparseable.
pub is_descriptive: bool,
/// The authoritative audio track type from the format's `xtags` blob, or
/// `None` for single-track audio / when `xtags` is absent or unparseable.
pub track_type: Option<AudioTrackType>,
pub itag_url_format: Option<String>,
}