yt_live_rs/
types.rs

1//! Shared types for the yt-live-rs library.
2//!
3//! This module contains the core data structures used throughout the library
4//! for representing video information, stream formats, and codec types.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::fmt;
9use std::str::FromStr;
10
11/// Metadata about a YouTube video or live stream.
12///
13/// This struct contains all the basic information about a video,
14/// including title, channel, and live status.
15///
16/// # Example
17///
18/// ```no_run
19/// # use yt_live_rs::Client;
20/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
21/// let client = Client::builder().build()?;
22/// let info = client.get_video_info("https://youtube.com/watch?v=VIDEO_ID").await?;
23/// println!("Title: {}", info.title);
24/// println!("Channel: {}", info.channel);
25/// println!("Is Live: {}", info.is_live);
26/// # Ok(())
27/// # }
28/// ```
29#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
30pub struct VideoInfo {
31    /// YouTube video ID (e.g., "dQw4w9WgXcQ").
32    pub id: String,
33    /// Video title.
34    pub title: String,
35    /// Channel name.
36    pub channel: String,
37    /// Channel ID.
38    pub channel_id: String,
39    /// Video description.
40    pub description: String,
41    /// Whether the stream is currently live.
42    pub is_live: bool,
43    /// Thumbnail URL.
44    pub thumbnail: Option<String>,
45    /// Stream start timestamp (ISO 8601 format).
46    pub start_timestamp: Option<String>,
47    /// Video publish date.
48    pub publish_date: Option<String>,
49    /// Full video URL.
50    pub url: String,
51}
52
53/// Information about available streams for a video.
54///
55/// Contains the audio and video stream formats available for download,
56/// along with timing information.
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct StreamInfo {
59    /// Audio stream format (usually AAC at 128kbps).
60    pub audio: Option<StreamFormat>,
61    /// Video streams by quality label (e.g., "1080p60 (h264)").
62    pub video: HashMap<String, StreamFormat>,
63    /// Target duration of each fragment in seconds.
64    pub target_duration: u32,
65    /// Last known sequence number from the manifest.
66    pub last_sequence: Option<u64>,
67}
68
69/// Format information for a single stream.
70///
71/// Contains the URL template and metadata for downloading a specific
72/// audio or video stream.
73#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct StreamFormat {
75    /// YouTube itag identifier for this format.
76    pub itag: u32,
77    /// URL template with `%d` placeholder for sequence number.
78    pub url: String,
79    /// MIME type (e.g., "video/mp4", "audio/mp4").
80    pub mime_type: Option<String>,
81    /// Quality label (e.g., "1080p60", "audio").
82    pub quality_label: Option<String>,
83    /// Video/audio codec.
84    pub codec: Codec,
85}
86
87/// Video or audio codec type.
88///
89/// # Example
90///
91/// ```
92/// use yt_live_rs::Codec;
93/// use std::str::FromStr;
94///
95/// let codec = Codec::from_str("h264").unwrap();
96/// assert_eq!(codec, Codec::H264);
97/// assert_eq!(codec.to_string(), "h264");
98/// ```
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
100pub enum Codec {
101    /// H.264/AVC video codec. Most compatible.
102    H264,
103    /// VP9 video codec. Better compression than H.264.
104    VP9,
105    /// AV1 video codec. Best compression, but requires more CPU.
106    AV1,
107    /// AAC audio codec.
108    AAC,
109    /// Opus audio codec.
110    Opus,
111    /// Unknown or unsupported codec.
112    #[default]
113    Unknown,
114}
115
116impl fmt::Display for Codec {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        match self {
119            Codec::H264 => write!(f, "h264"),
120            Codec::VP9 => write!(f, "vp9"),
121            Codec::AV1 => write!(f, "av1"),
122            Codec::AAC => write!(f, "aac"),
123            Codec::Opus => write!(f, "opus"),
124            Codec::Unknown => write!(f, "unknown"),
125        }
126    }
127}
128
129impl FromStr for Codec {
130    type Err = String;
131
132    fn from_str(s: &str) -> Result<Self, Self::Err> {
133        match s.to_lowercase().as_str() {
134            "h264" | "avc" | "avc1" => Ok(Codec::H264),
135            "vp9" | "vp09" => Ok(Codec::VP9),
136            "av1" | "av01" => Ok(Codec::AV1),
137            "aac" | "mp4a" => Ok(Codec::AAC),
138            "opus" => Ok(Codec::Opus),
139            _ => Err(format!("Unknown codec: {}", s)),
140        }
141    }
142}