From 097bc9b8d5dc4d40dd861457122acfda641c4f8a Mon Sep 17 00:00:00 2001 From: Mithronn Date: Mon, 17 Jun 2024 22:55:59 +0300 Subject: [PATCH] 17.06.2024 * Code quality improved --- src/constants.rs | 1862 +++++++++++++++++++++++++++++----------------- src/info.rs | 79 +- src/structs.rs | 50 -- src/utils.rs | 59 +- 4 files changed, 1235 insertions(+), 815 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 417936d..ec3d6e2 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,9 +1,10 @@ +use mime::Mime; use once_cell::sync::Lazy; use regex::Regex; use reqwest::header::{HeaderMap, USER_AGENT}; -use std::collections::HashMap; +use std::{collections::HashMap, str::FromStr}; -use crate::structs::{StaticFormat, StaticFormatRaw}; +use crate::structs::{MimeType, StaticFormat}; pub const BASE_URL: &str = "https://www.youtube.com/watch?v="; @@ -46,675 +47,1190 @@ pub(crate) static PARSE_INT_REGEX: Lazy = Lazy::new(|| Regex::new(r"(?m)^\s*((\-|\+)?[0-9]+)\s*").unwrap()); pub static FORMATS: Lazy> = Lazy::new(|| { - HashMap::from( - [ - ( - "5", - StaticFormatRaw { - mime_type: r#"video/flv; codecs="Sorenson H.283, mp3""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(250000), - audio_bitrate: Some(64), - }, - ), - ( - "6", - StaticFormatRaw { - mime_type: r#"video/flv; codecs="Sorenson H.263, mp3""#.to_string(), - quality_label: Some("270p".to_string()), - bitrate: Some(800000), - audio_bitrate: Some(64), - }, - ), - ( - "13", - StaticFormatRaw { - mime_type: r#"video/3gp; codecs="MPEG-4 Visual, aac""#.to_string(), - quality_label: None, - bitrate: Some(500000), - audio_bitrate: None, - }, - ), - ( - "17", - StaticFormatRaw { - mime_type: r#"video/3gp; codecs="MPEG-4 Visual, aac""#.to_string(), - quality_label: Some("144p".to_string()), - bitrate: Some(50000), - audio_bitrate: Some(24), - }, - ), - ( - "18", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(96), - }, - ), - ( - "22", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(2000000), - audio_bitrate: Some(192), - }, - ), - ( - "34", - StaticFormatRaw { - mime_type: r#"video/flv; codecs="H.264, aac""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(128), - }, - ), - ( - "35", - StaticFormatRaw { - mime_type: r#"video/flv; codecs="H.264, aac""#.to_string(), - quality_label: Some("480p".to_string()), - bitrate: Some(800000), - audio_bitrate: Some(128), - }, - ), - ( - "36", - StaticFormatRaw { - mime_type: r#"video/3gp; codecs="MPEG-4 Visual, aac""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(175000), - audio_bitrate: Some(32), - }, - ), - ( - "37", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(3000000), - audio_bitrate: Some(192), - }, - ), - ( - "38", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("3072p".to_string()), - bitrate: Some(3500000), - audio_bitrate: Some(192), - }, - ), - ( - "43", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(128), - }, - ), - ( - "44", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("480p".to_string()), - bitrate: Some(1000000), - audio_bitrate: Some(128), - }, - ), - ( - "45", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(2000000), - audio_bitrate: Some(192), - }, - ), - ( - "46", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="vp8, vorbis""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: None, - audio_bitrate: Some(192), - }, - ), - ( - "82", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(96), - }, - ), - ( - "83", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(96), - }, - ), - ( - "84", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(2000000), - audio_bitrate: Some(192), - }, - ), - ( - "85", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264, aac""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(3000000), - audio_bitrate: Some(192), - }, - ), - ( - "91", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("144p".to_string()), - bitrate: Some(100000), - audio_bitrate: Some(48), - }, - ), - ( - "92", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(150000), - audio_bitrate: Some(48), - }, - ), - ( - "93", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(500000), - audio_bitrate: Some(128), - }, - ), - ( - "94", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("480p".to_string()), - bitrate: Some(800000), - audio_bitrate: Some(128), - }, - ), - ( - "95", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(1500000), - audio_bitrate: Some(256), - }, - ), - ( - "96", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(2500000), - audio_bitrate: Some(256), - }, - ), - ( - "100", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: None, - audio_bitrate: Some(128), - }, - ), - ( - "101", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: None, - audio_bitrate: Some(192), - }, - ), - ( - "102", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="VP8, vorbis""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: None, - audio_bitrate: Some(192), - }, - ), - ( - "120", - StaticFormatRaw { - mime_type: r#"video/flv; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(2000000), - audio_bitrate: Some(128), - }, - ), - ( - "127", - StaticFormatRaw { - mime_type: r#"audio/ts; codecs="aac""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(96), - }, - ), - ( - "128", - StaticFormatRaw { - mime_type: r#"audio/ts; codecs="aac""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(96), - }, - ), - ( - "132", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(150000), - audio_bitrate: Some(48), - }, - ), - ( - "133", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(200000), - audio_bitrate: None, - }, - ), - ( - "134", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(300000), - audio_bitrate: None, - }, - ), - ( - "135", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("480p".to_string()), - bitrate: Some(500000), - audio_bitrate: None, - }, - ), - ( - "136", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(1000000), - audio_bitrate: None, - }, - ), - ( - "137", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(2500000), - audio_bitrate: None, - }, - ), - ( - "138", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("4320p".to_string()), - bitrate: Some(13500000), - audio_bitrate: None, - }, - ), - ( - "139", - StaticFormatRaw { - mime_type: r#"audio/mp4; codecs="aac""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(48), - }, - ), - ( - "140", - StaticFormatRaw { - mime_type: r#"audio/m4a; codecs="aac""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(128), - }, - ), - ( - "141", - StaticFormatRaw { - mime_type: r#"audio/mp4; codecs="aac""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(256), - }, - ), - ( - "151", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(50000), - audio_bitrate: Some(24), - }, - ), - ( - "160", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("144p".to_string()), - bitrate: Some(100000), - audio_bitrate: None, - }, - ), - ( - "171", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="vorbis""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(128), - }, - ), - ( - "172", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="vorbis""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(192), - }, - ), - ( - "242", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("240p".to_string()), - bitrate: Some(100000), - audio_bitrate: None, - }, - ), - ( - "243", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("360p".to_string()), - bitrate: Some(250000), - audio_bitrate: None, - }, - ), - ( - "244", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("480p".to_string()), - bitrate: Some(500000), - audio_bitrate: None, - }, - ), - ( - "247", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(700000), - audio_bitrate: None, - }, - ), - ( - "248", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(1500000), - audio_bitrate: None, - }, - ), - ( - "249", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="opus""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(48), - }, - ), - ( - "250", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="opus""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(64), - }, - ), - ( - "251", - StaticFormatRaw { - mime_type: r#"audio/webm; codecs="opus""#.to_string(), - quality_label: None, - bitrate: None, - audio_bitrate: Some(160), - }, - ), - ( - "264", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("1440p".to_string()), - bitrate: Some(4000000), - audio_bitrate: None, - }, - ), - ( - "266", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("2160p".to_string()), - bitrate: Some(12500000), - audio_bitrate: None, - }, - ), - ( - "271", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1440p".to_string()), - bitrate: Some(9000000), - audio_bitrate: None, - }, - ), - ( - "272", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("4320p".to_string()), - bitrate: Some(20000000), - audio_bitrate: None, - }, - ), - ( - "278", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("144p 30fps".to_string()), - bitrate: Some(80000), - audio_bitrate: None, - }, - ), - ( - "298", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(3000000), - audio_bitrate: None, - }, - ), - ( - "299", - StaticFormatRaw { - mime_type: r#"video/mp4; codecs="H.264""#.to_string(), - quality_label: Some("1080p".to_string()), - bitrate: Some(5500000), - audio_bitrate: None, - }, - ), - ( - "300", - StaticFormatRaw { - mime_type: r#"video/ts; codecs="H.264, aac""#.to_string(), - quality_label: Some("720p".to_string()), - bitrate: Some(1318000), - audio_bitrate: Some(48), - }, - ), - ( - "302", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("720p HFR".to_string()), - bitrate: Some(2500000), - audio_bitrate: None, - }, - ), - ( - "303", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1080p HFR".to_string()), - bitrate: Some(5000000), - audio_bitrate: None, - }, - ), - ( - "308", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1440p HFR".to_string()), - bitrate: Some(10000000), - audio_bitrate: None, - }, - ), - ( - "313", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("2160p".to_string()), - bitrate: Some(13000000), - audio_bitrate: None, - }, - ), - ( - "315", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("2160p HFR".to_string()), - bitrate: Some(20000000), - audio_bitrate: None, - }, - ), - ( - "330", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("144p HDR, HFR".to_string()), - bitrate: Some(80000), - audio_bitrate: None, - }, - ), - ( - "331", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("240p HDR, HFR".to_string()), - bitrate: Some(100000), - audio_bitrate: None, - }, - ), - ( - "332", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("360p HDR, HFR".to_string()), - bitrate: Some(250000), - audio_bitrate: None, - }, - ), - ( - "333", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("240p HDR, HFR".to_string()), - bitrate: Some(500000), - audio_bitrate: None, - }, - ), - ( - "334", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("720p HDR, HFR".to_string()), - bitrate: Some(1000000), - audio_bitrate: None, - }, - ), - ( - "335", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1080p HDR, HFR".to_string()), - bitrate: Some(1500000), - audio_bitrate: None, - }, - ), - ( - "336", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("1440p HDR, HFR".to_string()), - bitrate: Some(5000000), - audio_bitrate: None, - }, - ), - ( - "337", - StaticFormatRaw { - mime_type: r#"video/webm; codecs="VP9""#.to_string(), - quality_label: Some("2160p HDR, HFR".to_string()), - bitrate: Some(12000000), - audio_bitrate: None, - }, - ), - ] - .map(|(itag, raw_static_format)| (itag, StaticFormat::from(raw_static_format))), - ) + HashMap::from([ + ( + "5", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/flv; codecs=\"Sorenson H.283, mp3\"") + .expect("Static mime error: itag 5"), + container: "flv".to_string(), + codecs: vec!["Sorenson H.283".to_string(), "mp3".to_string()], + video_codec: Some("Sorenson H.283".to_string()), + audio_codec: Some("mp3".to_string()), + }, + quality_label: Some("240p".to_string()), + bitrate: Some(250000), + audio_bitrate: Some(64), + }, + ), + ( + "6", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/flv; codecs=\"Sorenson H.263, mp3\"") + .expect("Static mime error: itag 6"), + container: "flv".to_string(), + codecs: vec!["Sorenson H.263".to_string(), "mp3".to_string()], + video_codec: Some("Sorenson H.263".to_string()), + audio_codec: Some("mp3".to_string()), + }, + quality_label: Some("270p".to_string()), + bitrate: Some(800000), + audio_bitrate: Some(64), + }, + ), + ( + "13", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/3gp; codecs=\"MPEG-4 Visual, aac\"") + .expect("Static mime error: itag 13"), + container: "3gp".to_string(), + codecs: vec!["MPEG-4 Visual".to_string(), "aac".to_string()], + video_codec: Some("MPEG-4 Visual".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: Some(500000), + audio_bitrate: None, + }, + ), + ( + "17", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/3gp; codecs=\"MPEG-4 Visual, aac\"") + .expect("Static mime error: itag 17"), + container: "3gp".to_string(), + codecs: vec!["MPEG-4 Visual".to_string(), "aac".to_string()], + video_codec: Some("MPEG-4 Visual".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("144p".to_string()), + bitrate: Some(50000), + audio_bitrate: Some(24), + }, + ), + ( + "18", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 18"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(96), + }, + ), + ( + "22", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 22"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(2000000), + audio_bitrate: Some(192), + }, + ), + ( + "34", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/flv; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 34"), + container: "flv".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(128), + }, + ), + ( + "35", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/flv; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 35"), + container: "flv".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("480p".to_string()), + bitrate: Some(800000), + audio_bitrate: Some(128), + }, + ), + ( + "36", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/3gp; codecs=\"MPEG-4 Visual, aac\"") + .expect("Static mime error: itag 36"), + container: "3gp".to_string(), + codecs: vec!["MPEG-4 Visual".to_string(), "aac".to_string()], + video_codec: Some("MPEG-4 Visual".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("240p".to_string()), + bitrate: Some(175000), + audio_bitrate: Some(32), + }, + ), + ( + "37", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 37"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(3000000), + audio_bitrate: Some(192), + }, + ), + ( + "38", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 38"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("3072p".to_string()), + bitrate: Some(3500000), + audio_bitrate: Some(192), + }, + ), + ( + "43", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP8, vorbis\"") + .expect("Static mime error: itag 43"), + container: "webm".to_string(), + codecs: vec!["VP8".to_string(), "vorbis".to_string()], + video_codec: Some("VP8".to_string()), + audio_codec: Some("vorbis".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(128), + }, + ), + ( + "44", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP8, vorbis\"") + .expect("Static mime error: itag 44"), + container: "webm".to_string(), + codecs: vec!["VP8".to_string(), "vorbis".to_string()], + video_codec: Some("VP8".to_string()), + audio_codec: Some("vorbis".to_string()), + }, + quality_label: Some("480p".to_string()), + bitrate: Some(1000000), + audio_bitrate: Some(128), + }, + ), + ( + "45", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP8, vorbis\"") + .expect("Static mime error: itag 45"), + container: "webm".to_string(), + codecs: vec!["VP8".to_string(), "vorbis".to_string()], + video_codec: Some("VP8".to_string()), + audio_codec: Some("vorbis".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(2000000), + audio_bitrate: Some(192), + }, + ), + ( + "46", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vp8, vorbis\"") + .expect("Static mime error: itag 46"), + container: "webm".to_string(), + codecs: vec!["vp8".to_string(), "vorbis".to_string()], + video_codec: None, + audio_codec: Some("vp8".to_string()), + }, + quality_label: Some("1080p".to_string()), + bitrate: None, + audio_bitrate: Some(192), + }, + ), + ( + "82", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 82"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(96), + }, + ), + ( + "83", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 83"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("240p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(96), + }, + ), + ( + "84", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 84"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(2000000), + audio_bitrate: Some(192), + }, + ), + ( + "85", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 85"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(3000000), + audio_bitrate: Some(192), + }, + ), + ( + "91", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 91"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("144p".to_string()), + bitrate: Some(100000), + audio_bitrate: Some(48), + }, + ), + ( + "92", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 92"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("240p".to_string()), + bitrate: Some(150000), + audio_bitrate: Some(48), + }, + ), + ( + "93", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 93"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: Some(500000), + audio_bitrate: Some(128), + }, + ), + ( + "94", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 94"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("480p".to_string()), + bitrate: Some(800000), + audio_bitrate: Some(128), + }, + ), + ( + "95", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 95"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(1500000), + audio_bitrate: Some(256), + }, + ), + ( + "96", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 96"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(2500000), + audio_bitrate: Some(256), + }, + ), + ( + "100", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vp8, vorbis\"") + .expect("Static mime error: itag 100"), + container: "webm".to_string(), + codecs: vec!["vp8".to_string(), "vorbis".to_string()], + video_codec: None, + audio_codec: Some("vp8".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: None, + audio_bitrate: Some(128), + }, + ), + ( + "101", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vp8, vorbis\"") + .expect("Static mime error: itag 101"), + container: "webm".to_string(), + codecs: vec!["vp8".to_string(), "vorbis".to_string()], + video_codec: None, + audio_codec: Some("vp8".to_string()), + }, + quality_label: Some("360p".to_string()), + bitrate: None, + audio_bitrate: Some(192), + }, + ), + ( + "102", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vp8, vorbis\"") + .expect("Static mime error: itag 102"), + container: "webm".to_string(), + codecs: vec!["vp8".to_string(), "vorbis".to_string()], + video_codec: None, + audio_codec: Some("vp8".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: None, + audio_bitrate: Some(192), + }, + ), + ( + "120", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/flv; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 120"), + container: "flv".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(2000000), + audio_bitrate: Some(128), + }, + ), + ( + "127", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/ts; codecs=\"aac\"") + .expect("Static mime error: itag 127"), + container: "ts".to_string(), + codecs: vec!["aac".to_string()], + video_codec: None, + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(96), + }, + ), + ( + "128", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/ts; codecs=\"aac\"") + .expect("Static mime error: itag 128"), + container: "ts".to_string(), + codecs: vec!["aac".to_string()], + video_codec: None, + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(96), + }, + ), + ( + "132", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 132"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("240p".to_string()), + bitrate: Some(150000), + audio_bitrate: Some(48), + }, + ), + ( + "133", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 133"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("240p".to_string()), + bitrate: Some(200000), + audio_bitrate: None, + }, + ), + ( + "134", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 134"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("360p".to_string()), + bitrate: Some(300000), + audio_bitrate: None, + }, + ), + ( + "135", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 135"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("480p".to_string()), + bitrate: Some(500000), + audio_bitrate: None, + }, + ), + ( + "136", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 136"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("720p".to_string()), + bitrate: Some(1000000), + audio_bitrate: None, + }, + ), + ( + "137", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 137"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(2500000), + audio_bitrate: None, + }, + ), + ( + "138", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 138"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("4320p".to_string()), + bitrate: Some(13500000), + audio_bitrate: None, + }, + ), + ( + "139", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/mp4; codecs=\"aac\"") + .expect("Static mime error: itag 139"), + container: "mp4".to_string(), + codecs: vec!["aac".to_string()], + video_codec: None, + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(48), + }, + ), + ( + "140", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/m4a; codecs=\"aac\"") + .expect("Static mime error: itag 140"), + container: "m4a".to_string(), + codecs: vec!["aac".to_string()], + video_codec: None, + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(128), + }, + ), + ( + "141", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/mp4; codecs=\"aac\"") + .expect("Static mime error: itag 141"), + container: "mp4".to_string(), + codecs: vec!["aac".to_string()], + video_codec: None, + audio_codec: Some("aac".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(256), + }, + ), + ( + "151", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 151"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(50000), + audio_bitrate: Some(24), + }, + ), + ( + "160", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 160"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("144p".to_string()), + bitrate: Some(100000), + audio_bitrate: None, + }, + ), + ( + "171", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vorbis\"") + .expect("Static mime error: itag 171"), + container: "webm".to_string(), + codecs: vec!["vorbis".to_string()], + video_codec: None, + audio_codec: Some("vorbis".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(128), + }, + ), + ( + "172", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"vorbis\"") + .expect("Static mime error: itag 172"), + container: "webm".to_string(), + codecs: vec!["vorbis".to_string()], + video_codec: None, + audio_codec: Some("vorbis".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(192), + }, + ), + ( + "242", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 242"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("240p".to_string()), + bitrate: Some(100000), + audio_bitrate: None, + }, + ), + ( + "243", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 243"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("360p".to_string()), + bitrate: Some(250000), + audio_bitrate: None, + }, + ), + ( + "244", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 244"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("480p".to_string()), + bitrate: Some(500000), + audio_bitrate: None, + }, + ), + ( + "247", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 247"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("720p".to_string()), + bitrate: Some(700000), + audio_bitrate: None, + }, + ), + ( + "248", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 248"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(1500000), + audio_bitrate: None, + }, + ), + ( + "249", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"opus\"") + .expect("Static mime error: itag 249"), + container: "webm".to_string(), + codecs: vec!["opus".to_string()], + video_codec: None, + audio_codec: Some("opus".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(48), + }, + ), + ( + "250", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"opus\"") + .expect("Static mime error: itag 250"), + container: "webm".to_string(), + codecs: vec!["opus".to_string()], + video_codec: None, + audio_codec: Some("opus".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(64), + }, + ), + ( + "251", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("audio/webm; codecs=\"opus\"") + .expect("Static mime error: itag 251"), + container: "webm".to_string(), + codecs: vec!["opus".to_string()], + video_codec: None, + audio_codec: Some("opus".to_string()), + }, + quality_label: None, + bitrate: None, + audio_bitrate: Some(160), + }, + ), + ( + "264", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 264"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("1440p".to_string()), + bitrate: Some(4000000), + audio_bitrate: None, + }, + ), + ( + "266", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 266"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("2160p".to_string()), + bitrate: Some(12500000), + audio_bitrate: None, + }, + ), + ( + "271", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 271"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1440p".to_string()), + bitrate: Some(9000000), + audio_bitrate: None, + }, + ), + ( + "272", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 272"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("4320p".to_string()), + bitrate: Some(20000000), + audio_bitrate: None, + }, + ), + ( + "278", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 278"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("144p 30fps".to_string()), + bitrate: Some(80000), + audio_bitrate: None, + }, + ), + ( + "298", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 298"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("720p".to_string()), + bitrate: Some(3000000), + audio_bitrate: None, + }, + ), + ( + "299", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/mp4; codecs=\"H.264\"") + .expect("Static mime error: itag 299"), + container: "mp4".to_string(), + codecs: vec!["H.264".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: None, + }, + quality_label: Some("1080p".to_string()), + bitrate: Some(5500000), + audio_bitrate: None, + }, + ), + ( + "300", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/ts; codecs=\"H.264, aac\"") + .expect("Static mime error: itag 300"), + container: "ts".to_string(), + codecs: vec!["H.264".to_string(), "aac".to_string()], + video_codec: Some("H.264".to_string()), + audio_codec: Some("aac".to_string()), + }, + quality_label: Some("720p".to_string()), + bitrate: Some(1318000), + audio_bitrate: Some(48), + }, + ), + ( + "302", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 302"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("720p HFR".to_string()), + bitrate: Some(2500000), + audio_bitrate: None, + }, + ), + ( + "303", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 303"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1080p HFR".to_string()), + bitrate: Some(5000000), + audio_bitrate: None, + }, + ), + ( + "308", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 308"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1440p HFR".to_string()), + bitrate: Some(10000000), + audio_bitrate: None, + }, + ), + ( + "313", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 313"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("2160p".to_string()), + bitrate: Some(13000000), + audio_bitrate: None, + }, + ), + ( + "315", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 315"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("2160p HFR".to_string()), + bitrate: Some(20000000), + audio_bitrate: None, + }, + ), + ( + "330", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 330"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("144p HDR, HFR".to_string()), + bitrate: Some(80000), + audio_bitrate: None, + }, + ), + ( + "331", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 331"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("240p HDR, HFR".to_string()), + bitrate: Some(100000), + audio_bitrate: None, + }, + ), + ( + "332", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 332"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("360p HDR, HFR".to_string()), + bitrate: Some(250000), + audio_bitrate: None, + }, + ), + ( + "333", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 333"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("240p HDR, HFR".to_string()), + bitrate: Some(500000), + audio_bitrate: None, + }, + ), + ( + "334", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 334"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("720p HDR, HFR".to_string()), + bitrate: Some(1000000), + audio_bitrate: None, + }, + ), + ( + "335", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 335"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1080p HDR, HFR".to_string()), + bitrate: Some(1500000), + audio_bitrate: None, + }, + ), + ( + "336", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 336"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("1440p HDR, HFR".to_string()), + bitrate: Some(5000000), + audio_bitrate: None, + }, + ), + ( + "337", + StaticFormat { + mime_type: MimeType { + mime: Mime::from_str("video/webm; codecs=\"VP9\"") + .expect("Static mime error: itag 337"), + container: "webm".to_string(), + codecs: vec!["VP9".to_string()], + video_codec: Some("VP9".to_string()), + audio_codec: None, + }, + quality_label: Some("2160p HDR, HFR".to_string()), + bitrate: Some(12000000), + audio_bitrate: None, + }, + ), + ]) }); diff --git a/src/info.rs b/src/info.rs index 4541e31..a7ad3e1 100644 --- a/src/info.rs +++ b/src/info.rs @@ -10,21 +10,19 @@ use url::Url; #[cfg(feature = "live")] use crate::stream::{LiveStream, LiveStreamOptions}; +#[cfg(feature = "ffmpeg")] +use crate::structs::FFmpegArgs; use crate::{ constants::BASE_URL, info_extras::{get_media, get_related_videos}, stream::{NonLiveStream, NonLiveStreamOptions, Stream}, structs::{PlayerResponse, VideoError, VideoInfo, VideoOptions}, -}; - -#[cfg(feature = "ffmpeg")] -use crate::structs::FFmpegArgs; - -use crate::utils::{ - between, choose_format, clean_video_details, get_functions, get_html, get_html5player, - get_random_v6_ip, get_video_id, is_not_yet_broadcasted, is_play_error, is_private_video, - is_rental, parse_live_video_formats, parse_video_formats, sort_formats, + utils::{ + between, choose_format, clean_video_details, get_functions, get_html, get_html5player, + get_random_v6_ip, get_video_id, is_not_yet_broadcasted, is_play_error, is_private_video, + is_rental, parse_live_video_formats, parse_video_formats, sort_formats, + }, }; // 10485760 -> Default is 10MB to avoid Youtube throttle (Bigger than this value can be throttle by Youtube) @@ -69,31 +67,32 @@ impl Video { ) -> Result { let video_id = get_video_id(&url_or_id.into()).ok_or(VideoError::VideoNotFound)?; - let client = if let Some(client) = options.request_options.client.as_ref() { - client.clone() - } else { - let mut client = Client::builder(); + let client = match options.request_options.client.clone() { + Some(client) => client, + None => { + let mut client_builder = Client::builder(); - if let Some(proxy) = options.request_options.proxy.as_ref() { - client = client.proxy(proxy.clone()); - } + if let Some(proxy) = &options.request_options.proxy { + client_builder = client_builder.proxy(proxy.clone()); + } - if let Some(ipv6_block) = options.request_options.ipv6_block.as_ref() { - let ipv6 = get_random_v6_ip(ipv6_block)?; - client = client.local_address(ipv6); - } + if let Some(ipv6_block) = &options.request_options.ipv6_block { + let ipv6 = get_random_v6_ip(ipv6_block)?; + client_builder = client_builder.local_address(ipv6); + } - if let Some(cookie) = options.request_options.cookies.as_ref() { - let mut headers = HeaderMap::new(); - headers.insert( - COOKIE, - HeaderValue::from_str(cookie).map_err(|_x| VideoError::CookieError)?, - ); + if let Some(cookie) = &options.request_options.cookies { + let mut headers = HeaderMap::new(); + headers.insert( + COOKIE, + HeaderValue::from_str(cookie).map_err(|_x| VideoError::CookieError)?, + ); - client = client.default_headers(headers) - } + client_builder = client_builder.default_headers(headers) + } - client.build().map_err(VideoError::Reqwest)? + client_builder.build().map_err(VideoError::Reqwest)? + } }; let retry_policy = ExponentialBackoff::builder() @@ -210,26 +209,12 @@ impl Video { /// - `HLS` and `DashMPD` formats included! #[cfg_attr(feature = "performance_analysis", flamer::flame)] pub async fn get_info(&self) -> Result { - let client = &self.client; - let mut info = self.get_basic_info().await?; - let has_manifest = info.dash_manifest_url.is_some() || info.hls_manifest_url.is_some(); - - // if has_manifest && info.dash_manifest_url.is_some() {} - - if has_manifest && info.hls_manifest_url.is_some() { - let url = info.hls_manifest_url.as_ref().expect("IMPOSSIBLE"); - let unformated_formats = get_m3u8(url, client).await; - - // Skip if error occured - if let Ok(unformated_formats) = unformated_formats { - // Push formated infos to formats - info.formats = [ - &info.formats[..], - &parse_live_video_formats(unformated_formats)[..], - ] - .concat() + if let Some(url) = &info.hls_manifest_url { + if let Ok(unformated_formats) = get_m3u8(url, &self.client).await { + info.formats + .extend(parse_live_video_formats(unformated_formats)); } } diff --git a/src/structs.rs b/src/structs.rs index 8a98106..6738d6c 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -551,56 +551,6 @@ pub struct StaticFormat { pub audio_bitrate: Option, } -impl From for StaticFormat { - fn from(value: StaticFormatRaw) -> Self { - let mime: Mime = Mime::from_str(&value.mime_type).expect("IMPOSSIBLE"); - - let codecs: Vec = mime - .get_param("codecs") - .map(|x| x.as_str().split(", ").map(|x| x.to_string()).collect()) - .unwrap_or_default(); - - let container: String = mime.subtype().to_string(); - - let video_codec = if mime.type_() == mime::VIDEO { - codecs.first().cloned() - } else { - None - }; - - let audio_codec = if mime.type_() == mime::AUDIO { - codecs.first().cloned() - } else { - codecs.get(1).cloned() - }; - - Self { - mime_type: MimeType { - mime, - container, - codecs, - video_codec, - audio_codec, - }, - quality_label: value.quality_label, - bitrate: value.bitrate, - audio_bitrate: value.audio_bitrate, - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] - -pub struct StaticFormatRaw { - #[serde(rename = "mimeType")] - pub mime_type: String, - #[serde(rename = "qualityLabel")] - pub quality_label: Option, - pub bitrate: Option, - #[serde(rename = "audioBitrate")] - pub audio_bitrate: Option, -} - pub trait StringUtils { fn substring(&self, start: usize, end: usize) -> &str; fn substr(&self, start: usize, len: usize) -> &str; diff --git a/src/utils.rs b/src/utils.rs index 61ffa96..0c27d2d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -228,22 +228,15 @@ pub fn choose_format<'a>( } #[cfg_attr(feature = "performance_analysis", flamer::flame)] -pub fn sort_formats_by(a: &VideoFormat, b: &VideoFormat, sort_by: Vec) -> Ordering +pub fn sort_formats_by(a: &VideoFormat, b: &VideoFormat, sort_by: &[F]) -> Ordering where F: Fn(&VideoFormat) -> i32, { - let mut res = Ordering::Equal; - - for func in sort_by { - res = func(b).cmp(&func(a)); - - // Is not equal return order - if res != Ordering::Equal { - break; - } - } - - res + sort_by + .iter() + .map(|func| func(b).cmp(&func(a))) + .find(|&order| order != Ordering::Equal) + .unwrap_or(Ordering::Equal) } #[cfg_attr(feature = "performance_analysis", flamer::flame)] @@ -276,7 +269,7 @@ pub fn sort_formats_by_video(a: &VideoFormat, b: &VideoFormat) -> Ordering { index }, ] - .to_vec(), + .as_ref(), ) } @@ -298,7 +291,7 @@ pub fn sort_formats_by_audio(a: &VideoFormat, b: &VideoFormat) -> Ordering { index }, ] - .to_vec(), + .as_ref(), ) } @@ -357,7 +350,7 @@ pub fn sort_formats(a: &VideoFormat, b: &VideoFormat) -> Ordering { index }, ] - .to_vec(), + .as_ref(), ) } @@ -994,11 +987,7 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { let mut functions: Vec<(String, String)> = vec![]; #[cfg_attr(feature = "performance_analysis", flamer::flame)] - fn extract_manipulations( - body: String, - caller: &str, - // cut_after_js_script: &mut js_sandbox::Script, - ) -> String { + fn extract_manipulations(body: String, caller: &str) -> String { let function_name = between(caller, r#"a=a.split("");"#, "."); if function_name.is_empty() { return String::new(); @@ -1013,9 +1002,6 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { let sub_body = body.slice((ndx.unwrap() + function_start.len() - 1)..); - // let cut_after_sub_body = cut_after_js_script.call("cutAfterJS", (&sub_body,)); - // let cut_after_sub_body: String = cut_after_sub_body.unwrap_or(String::from("null")); - let cut_after_sub_body = cut_after_js(sub_body).unwrap_or("null"); let return_formatted_string = format!("var {function_name}={cut_after_sub_body}"); @@ -1024,11 +1010,7 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { } #[cfg_attr(feature = "performance_analysis", flamer::flame)] - fn extract_decipher( - body: String, - functions: &mut Vec<(String, String)>, - // cut_after_js_script: &mut js_sandbox::Script, - ) { + fn extract_decipher(body: String, functions: &mut Vec<(String, String)>) { let function_name = between(body.as_str(), r#"a.set("alr","yes");c&&(c="#, "(decodeURIC"); // println!("decipher function name: {}", function_name); if !function_name.is_empty() { @@ -1038,9 +1020,6 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { if let Some(ndx_some) = ndx { let sub_body = body.slice((ndx_some + function_start.len())..); - // let cut_after_sub_body = cut_after_js_script.call("cutAfterJS", (&sub_body,)); - // let cut_after_sub_body: String = cut_after_sub_body.unwrap_or(String::from("{}")); - let cut_after_sub_body = cut_after_js(sub_body).unwrap_or("{}"); let mut function_body = format!("var {function_start}{cut_after_sub_body}"); @@ -1062,11 +1041,7 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { } #[cfg_attr(feature = "performance_analysis", flamer::flame)] - fn extract_ncode( - body: String, - functions: &mut Vec<(String, String)>, - // cut_after_js_script: &mut js_sandbox::Script, - ) { + fn extract_ncode(body: String, functions: &mut Vec<(String, String)>) { let mut function_name = between(body.as_str(), r#"&&(b=a.get("n"))&&(b="#, "(b)"); let left_name = format!( @@ -1091,9 +1066,6 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { if let Some(ndx_some) = ndx { let sub_body = body.slice((ndx_some + function_start.len())..); - // let cut_after_sub_body = cut_after_js_script.call("cutAfterJS", (&sub_body,)); - // let cut_after_sub_body: String = cut_after_sub_body.unwrap_or(String::from("{}")); - let cut_after_sub_body = cut_after_js(sub_body).unwrap_or("{}"); let mut function_body = format!("var {function_start}{cut_after_sub_body};"); @@ -1105,11 +1077,8 @@ pub fn extract_functions(body: String) -> Vec<(String, String)> { } } - extract_decipher( - body.clone(), - &mut functions, /*&mut cut_after_js_script*/ - ); - extract_ncode(body, &mut functions /*&mut cut_after_js_script*/); + extract_decipher(body.clone(), &mut functions); + extract_ncode(body, &mut functions); // println!("{:#?} {}", functions, functions.len()); functions