1use bitflags::bitflags;
2use serde::{Deserialize, Serialize};
3use serde_with::DefaultOnError;
4use serde_with::serde_as;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum VideoQuality {
9 P240 = 6,
11 P360 = 16,
13 P480 = 32,
15 P720 = 64,
18 P720_60 = 74,
20 P1080 = 80,
22 Smart = 100,
26 P1080Plus = 112,
28 P1080_60 = 116,
30 P4K = 120,
32 HDR = 125,
34 DolbyVision = 126,
36 P8K = 127,
38}
39
40impl VideoQuality {
41 pub fn as_u32(self) -> u32 {
42 self as u32
43 }
44}
45
46bitflags! {
47 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
48 pub struct Fnval: u32 {
49 const FLV = 0; const MP4 = 1; const DASH = 1 << 4; const HDR = 1 << 6; const FOURK = 1 << 7; const DOLBY_AUDIO = 1 << 8; const DOLBY_VISION = 1 << 9; const EIGHTK = 1 << 10; const AV1 = 1 << 11; const AI_FIX = 12240; }
62}
63impl Fnval {
64 pub fn is_fourk(&self) -> bool {
65 self.contains(Fnval::FOURK) || self.contains(Fnval::EIGHTK)
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum VideoCodec {
72 Avc = 7,
74 Hevc = 12,
76 Av1 = 13,
78}
79
80impl VideoCodec {
81 pub fn as_u32(self) -> u32 {
82 self as u32
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum AudioQuality {
89 K64 = 30216,
91 K132 = 30232,
93 K192 = 30280,
95}
96
97impl AudioQuality {
98 pub fn as_u32(self) -> u32 {
99 self as u32
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct VideoStreamData {
106 pub quality: u32,
108 pub accept_quality: Vec<u32>,
110 pub accept_format: String,
112 pub accept_description: Vec<String>,
114 pub format: String,
116 pub video_codecid: u32,
118
119 #[serde(default, rename = "durls")]
121 pub durl: Option<Vec<Durl>>,
122 #[serde(default)]
124 pub dash: Option<DashStreams>,
125 pub has_paid: bool,
127 pub support_formats: Vec<SupportFormat>,
129 #[serde(default)]
131 pub timelength: Option<u64>,
132 #[serde(default)]
134 pub fnval: Option<u32>,
135 #[serde(default)]
137 pub is_preview: Option<u32>,
138}
139
140impl VideoStreamData {
141 pub fn best_format(&self) -> Option<&SupportFormat> {
143 self.support_formats.iter().max_by_key(|f| f.quality)
144 }
145
146 pub fn best_video(&self) -> Option<&DashTrack> {
148 self.dash.as_ref().and_then(|dash| {
149 dash.video.iter().max_by(|a, b| {
150 let res_a = a.width * a.height;
152 let res_b = b.width * b.height;
153
154 res_a
155 .cmp(&res_b)
156 .then_with(|| a.bandwidth.cmp(&b.bandwidth))
157 .then_with(|| {
158 let codec_priority = |c: &str| {
159 if c.starts_with("hev1") || c.starts_with("hvc1") {
160 1
161 } else {
162 0
163 }
164 };
165 codec_priority(&a.codecs).cmp(&codec_priority(&b.codecs))
166 })
167 })
168 })
169 }
170
171 pub fn best_audio(&self) -> Option<&DashTrack> {
173 self.dash.as_ref().and_then(|dash| {
174 dash.audio.iter().max_by(|a, b| {
175 a.bandwidth
176 .cmp(&b.bandwidth)
177 .then_with(|| a.size.cmp(&b.size))
178 })
179 })
180 }
181
182 pub fn supports_dash(&self) -> bool {
184 self.dash.is_some()
185 }
186
187 pub fn supports_direct_url(&self) -> bool {
189 self.durl.is_some() && !self.durl.as_ref().unwrap().is_empty()
190 }
191
192 pub fn duration_seconds(&self) -> Option<u64> {
194 self.timelength.map(|ms| ms / 1000)
195 }
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct Durl {
200 pub size: u64,
202 pub ahead: String,
203 pub length: u64,
205 pub vhead: String,
206 pub backup_url: Vec<String>,
208 pub url: String,
210 pub order: u32,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct SupportFormat {
216 pub display_desc: String,
217 pub format: String,
218 pub description: String,
219 pub quality: u32,
220 pub new_description: String,
221
222 pub superscript: String,
223
224 #[serde(default)]
225 pub codecs: Vec<String>,
227
228 pub attribute: Option<u32>,
229 pub has_preview: Option<bool>,
230 pub sub_description: Option<String>,
231 pub need_login: Option<bool>,
232 pub need_vip: Option<bool>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct DashStreams {
237 pub duration: u64,
238 pub min_buffer_time: f64,
239 pub video: Vec<DashTrack>,
240 pub audio: Vec<DashTrack>,
241 pub dolby: Option<DashDolby>,
242 pub flac: Option<DashFlac>,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct DashFlac {
247 pub display_sample_rate: String,
248 pub audio: DashTrack,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct SegmentBase {
253 pub initialization: String,
254 pub index_range: String,
255}
256
257#[serde_as]
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct DashDolby {
260 #[serde_as(as = "DefaultOnError")]
261 pub r#type: u32,
262 pub audio: Vec<DashTrack>,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct DashTrack {
267 pub id: u32,
268 pub base_url: String,
269 pub backup_url: Vec<String>,
270 pub bandwidth: u32,
271 pub mime_type: String,
272 pub codecs: String,
273 pub width: u32,
274 pub height: u32,
275 pub frame_rate: String,
276 pub sar: String,
277 pub start_with_sap: u32,
278 pub segment_base: SegmentBase,
279 pub codecid: u32,
280 pub size: u64,
281 pub md5: Option<String>,
282}