From 63d2a0fb360cd84e8a19791486ecd083f8f1dd42 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Thu, 15 Sep 2022 13:06:45 +0200 Subject: [PATCH] fix: accept video streams without content length/average bitrate --- cli/src/main.rs | 3 +- src/client2/player.rs | 55 +++++-------------- src/client2/response/player.rs | 10 ++-- ...layer__tests__map_player_data_android.snap | 20 ++++++- src/model/mod.rs | 2 +- src/report.rs | 2 +- 6 files changed, 42 insertions(+), 50 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 7f581d6..0c120f8 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -59,6 +59,7 @@ async fn download_single_video( let res = async { let player_data = rp + .query() .get_player(video_id.as_str(), ClientType::TvHtml5Embed) .await .context(format!( @@ -148,7 +149,7 @@ async fn download_playlist( .expect("unable to build the HTTP client"); let rp = RustyPipe::default(); - let playlist = rp.get_playlist(id).await.unwrap(); + let playlist = rp.query().get_playlist(id).await.unwrap(); // Indicatif setup let multi = MultiProgress::new(); diff --git a/src/client2/player.rs b/src/client2/player.rs index 27571c9..079ef26 100644 --- a/src/client2/player.rs +++ b/src/client2/player.rs @@ -59,15 +59,10 @@ struct QContentPlaybackContext { impl RustyPipeQuery { pub async fn get_player(self, video_id: &str, client_type: ClientType) -> Result { - // let (context, deobf) = tokio::join!(self.get_context(client_type, false), self.get_deobf()); - // let deobf = deobf?; - let q1 = self.clone(); let t_context = tokio::spawn(async move { q1.get_context(client_type, false).await }); let q2 = self.clone(); let t_deobf = tokio::spawn(async move { q2.get_deobf().await }); - // let context = t_context.await.unwrap(); - // let deobf = t_deobf.await.unwrap()?; let (context, deobf) = tokio::join!(t_context, t_deobf); let context = context.unwrap(); @@ -234,7 +229,7 @@ impl MapResponse for response::Player { audio_streams.push(c); }; } - (false, false) => warnings.push(format!("invalid format: {}", f.itag)), + (false, false) => warnings.push(format!("invalid stream: itag {}", f.itag)), } } @@ -406,38 +401,16 @@ fn map_video_stream( url, itag: f.itag, bitrate: f.bitrate, - average_bitrate: f.average_bitrate, + average_bitrate: f.average_bitrate.unwrap_or(f.bitrate), size: f.content_length, index_range: f.index_range, init_range: f.init_range, - width: some_or_bail!( - f.width, - MapResult { - c: None, - warnings: map_res.warnings - } - ), - height: some_or_bail!( - f.height, - MapResult { - c: None, - warnings: map_res.warnings - } - ), - fps: some_or_bail!( - f.fps, - MapResult { - c: None, - warnings: map_res.warnings - } - ), - quality: some_or_bail!( - f.quality_label, - MapResult { - c: None, - warnings: map_res.warnings - } - ), + // Note that the format has already been verified using + // is_video(), so these unwraps are safe + width: f.width.unwrap(), + height: f.height.unwrap(), + fps: f.fps.unwrap(), + quality: f.quality_label.unwrap(), hdr: f.color_info.unwrap_or_default().primaries == player::Primaries::ColorPrimariesBt2020, mime: f.mime_type.to_owned(), @@ -445,7 +418,7 @@ fn map_video_stream( get_video_format(mtype), MapResult { c: None, - warnings: vec![format!("no valid format in video format")] + warnings: vec![format!("invalid video format. itag: {}", f.itag)] } ), codec: get_video_codec(codecs), @@ -485,8 +458,8 @@ fn map_audio_stream( url, itag: f.itag, bitrate: f.bitrate, - average_bitrate: f.average_bitrate, - size: f.content_length, + average_bitrate: f.average_bitrate.unwrap_or(f.bitrate), + size: f.content_length.unwrap(), index_range: f.index_range, init_range: f.init_range, mime: f.mime_type.to_owned(), @@ -494,7 +467,7 @@ fn map_audio_stream( get_audio_format(mtype), MapResult { c: None, - warnings: vec![format!("invalid format in audio format {}", f.itag)] + warnings: vec![format!("invalid audio format. itag: {}", f.itag)] } ), codec: get_audio_codec(codecs), @@ -759,7 +732,7 @@ mod tests { // Bitrates may change between requests assert_approx(video.bitrate as f64, 1507068.0); assert_eq!(video.average_bitrate, 1345149); - assert_eq!(video.size, 43553412); + assert_eq!(video.size.unwrap(), 43553412); assert_eq!(video.width, 1280); assert_eq!(video.height, 720); assert_eq!(video.fps, 30); @@ -789,7 +762,7 @@ mod tests { assert_approx(video.bitrate as f64, 1340829.0); assert_approx(video.average_bitrate as f64, 1233444.0); - assert_approx(video.size as f64, 39936630.0); + assert_approx(video.size.unwrap() as f64, 39936630.0); assert_eq!(video.width, 1280); assert_eq!(video.height, 720); assert_eq!(video.fps, 30); diff --git a/src/client2/response/player.rs b/src/client2/response/player.rs index eb6a1b7..501c0d2 100644 --- a/src/client2/response/player.rs +++ b/src/client2/response/player.rs @@ -80,15 +80,15 @@ pub struct Format { #[serde_as(as = "Option")] pub init_range: Option>, - #[serde_as(as = "JsonString")] - pub content_length: u64, + #[serde_as(as = "Option")] + pub content_length: Option, #[serde(default)] #[serde_as(deserialize_as = "DefaultOnError")] pub quality: Option, pub fps: Option, pub quality_label: Option, - pub average_bitrate: u32, + pub average_bitrate: Option, pub color_info: Option, // Audio only @@ -106,7 +106,9 @@ pub struct Format { impl Format { pub fn is_audio(&self) -> bool { - self.audio_quality.is_some() && self.audio_sample_rate.is_some() + self.content_length.is_some() + && self.audio_quality.is_some() + && self.audio_sample_rate.is_some() } pub fn is_video(&self) -> bool { diff --git a/src/client2/snapshots/rustypipe__client2__player__tests__map_player_data_android.snap b/src/client2/snapshots/rustypipe__client2__player__tests__map_player_data_android.snap index 845ccda..4cc0a00 100644 --- a/src/client2/snapshots/rustypipe__client2__player__tests__map_player_data_android.snap +++ b/src/client2/snapshots/rustypipe__client2__player__tests__map_player_data_android.snap @@ -1,6 +1,6 @@ --- -source: src/client/player.rs -expression: player_data +source: src/client2/player.rs +expression: map_res.c --- info: id: pPvd8UxmSbQ @@ -184,6 +184,22 @@ video_only_streams: format: mp4 codec: av01 throttled: false + - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&dur=163.096&ei=q1jpYtOPEYSBgQeHmqbwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=4&id=o-AEDMTCojVtwpIKOdhBaxEHE5s322qnAJHGqa2r1F46BM&initcwndbps=1527500&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=22&lmt=1580005750956837&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659459429&mv=m&mvi=5&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgFlQZgR63Yz9UgY9gVqiyGDVkZmSmACRP3-MmKN7CRzQCIAMHAwZbHmWL1qNH4Nu3A0pXZwErXMVPzMIt-PyxeZqa&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cratebypass%2Cdur%2Clmt&txp=2211222&vprv=1" + itag: 22 + bitrate: 1574434 + average_bitrate: 1574434 + size: ~ + index_range: ~ + init_range: ~ + width: 1280 + height: 720 + fps: 30 + quality: 720p + hdr: false + mime: "video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"" + format: mp4 + codec: avc1 + throttled: false - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=22365208&dur=163.046&ei=q1jpYtOPEYSBgQeHmqbwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AEDMTCojVtwpIKOdhBaxEHE5s322qnAJHGqa2r1F46BM&initcwndbps=1527500&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=398&keepalive=yes&lmt=1608048380553749&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659459429&mv=m&mvi=5&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgR6KqCOoig_FMl2tWKa7qHSmCjIZa9S7ABzEI16qdO2sCIFXccwql4bqV9CHlqXY4tgxyMFUsp7vW4XUjxs3AyG6H&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1" itag: 398 bitrate: 1348419 diff --git a/src/model/mod.rs b/src/model/mod.rs index 7853896..a7f2f53 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -59,7 +59,7 @@ pub struct VideoStream { pub itag: u32, pub bitrate: u32, pub average_bitrate: u32, - pub size: u64, + pub size: Option, pub index_range: Option>, pub init_range: Option>, pub width: u32, diff --git a/src/report.rs b/src/report.rs index 2c6df25..7406f6a 100644 --- a/src/report.rs +++ b/src/report.rs @@ -122,7 +122,7 @@ impl YamlFileReporter { impl Default for YamlFileReporter { fn default() -> Self { Self { - path: Path::new("RustyPipeReports").to_path_buf(), + path: Path::new("rustypipe_reports").to_path_buf(), } } }