From 2ecb4b6d3fdb47affefc73205d7fa669ea227df4 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 17 Mar 2025 00:04:11 +0100 Subject: [PATCH 01/21] feat!: extract ABR streaming URL, make audio/video stream url optional --- downloader/src/lib.rs | 4 +- src/client/player.rs | 48 +++++++++++++++---- src/client/response/player.rs | 17 +++++++ ...layer__tests__map_player_data_android.snap | 34 ++++++------- ...layer__tests__map_player_data_desktop.snap | 42 ++++++++-------- ...__tests__map_player_data_desktopmusic.snap | 30 ++++++------ ...t__player__tests__map_player_data_ios.snap | 10 ++-- ...nt__player__tests__map_player_data_tv.snap | 40 ++++++++-------- src/model/mod.rs | 8 +++- src/model/traits.rs | 10 ++-- src/param/stream_filter.rs | 24 ++++++++-- tests/youtube.rs | 2 +- 12 files changed, 172 insertions(+), 97 deletions(-) diff --git a/downloader/src/lib.rs b/downloader/src/lib.rs index c63d5c5..2ba3590 100644 --- a/downloader/src/lib.rs +++ b/downloader/src/lib.rs @@ -815,7 +815,7 @@ impl DownloadQuery { if let Some(v) = video { downloads.push(StreamDownload { file: output_path.with_extension(format!("video{}", v.format.extension())), - url: v.url.clone(), + url: v.url.clone().unwrap(), video_codec: Some(v.codec), audio_codec: None, }); @@ -823,7 +823,7 @@ impl DownloadQuery { if let Some(a) = audio { downloads.push(StreamDownload { file: output_path.with_extension(format!("audio{}", a.format.extension())), - url: a.url.clone(), + url: a.url.clone().unwrap(), video_codec: None, audio_codec: Some(a.codec), }); diff --git a/src/client/player.rs b/src/client/player.rs index 9bae601..591d773 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -417,11 +417,27 @@ impl MapResponse for response::Player { is_live_content: video_details.is_live_content, }; + let mut mapper = StreamsMapper::new( + ctx.deobf, + ctx.session_po_token.as_ref().map(|t| t.po_token.as_str()), + )?; + + let abr_streaming_url = match &streaming_data.server_abr_streaming_url { + Some(url) => match mapper.map_url_abr(url) { + Ok(res) => Some(res), + Err(e) => { + warnings.push(format!("could not map abr_streaming_url: {e}")); + None + } + }, + None => None, + }; + let abr_ustreamer_config = self.player_config.media_common_config.map(|cfg| { + cfg.media_ustreamer_request_config + .video_playback_ustreamer_config + }); + let streams = if !is_live { - let mut mapper = StreamsMapper::new( - ctx.deobf, - ctx.session_po_token.as_ref().map(|t| t.po_token.as_str()), - )?; mapper.map_streams(streaming_data.formats); mapper.map_streams(streaming_data.adaptive_formats); let mut res = mapper.output()?; @@ -530,6 +546,8 @@ impl MapResponse for response::Player { valid_until, hls_manifest_url: streaming_data.hls_manifest_url, dash_manifest_url: streaming_data.dash_manifest_url, + abr_streaming_url, + abr_ustreamer_config, preview_frames, drm, client_type: ctx.client_type, @@ -708,9 +726,7 @@ impl<'a> StreamsMapper<'a> { ) }) } - None => Err(ExtractionError::InvalidData( - "stream contained neither url or cipher".into(), - )), + None => return Ok(UrlMapRes::default()), }, }?; @@ -723,11 +739,21 @@ impl<'a> StreamsMapper<'a> { .map_err(|_| ExtractionError::InvalidData("could not combine URL".into()))?; Ok(UrlMapRes { - url: url.to_string(), + url: Some(url.to_string()), xtags: url_params.get("xtags").cloned(), }) } + fn map_url_abr(&mut self, url: &str) -> Result { + let (url_base, mut url_params) = util::url_to_params(url).map_err(|_| { + ExtractionError::InvalidData(format!("Could not parse url `{url}`").into()) + })?; + self.deobf_nsig(&mut url_params)?; + let url = Url::parse_with_params(url_base.as_str(), url_params.iter()) + .map_err(|_| ExtractionError::InvalidData("could not combine URL".into()))?; + Ok(url.to_string()) + } + fn map_video_stream(&mut self, f: player::Format) -> Result { let Some((mtype, codecs)) = parse_mime(&f.mime_type) else { return Err(ExtractionError::InvalidData( @@ -850,8 +876,9 @@ impl<'a> StreamsMapper<'a> { } } +#[derive(Default)] struct UrlMapRes { - url: String, + url: Option, xtags: Option, } @@ -1013,7 +1040,8 @@ mod tests { let url = mapper .map_url(&None, &Some(signature_cipher.to_owned())) .unwrap() - .url; + .url + .unwrap(); assert_eq!(url, "https://rr5---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=3781277&dur=229.301&ei=vb7nYvH5BMK8gAfBj7ToBQ&expire=1659376413&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-AB_BABwrXZJN428ZwDxq5ScPn2AbcGODnRlTVhCQ3mj2&initcwndbps=1588750&ip=2003%3Ade%3Aaf06%3A6300%3Ac750%3A1b77%3Ac74a%3A80e3&itag=251&keepalive=yes&lmt=1655510291473933&lsig=AG3C_xAwRQIgCKCGJ1iu4wlaGXy3jcJyU3inh9dr1FIfqYOZEG_MdmACIQCbungkQYFk7EhD6K2YvLaHFMjKOFWjw001_tLb0lPDtg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=hH&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5ednsl&ms=au%2Conr&mt=1659354538&mv=m&mvi=5&n=XzXGSfGusw6OCQ&ns=b_Mq_qlTFcSGlG9RpwpM9xQH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAPIsKd7-xi4xVHEC9gb__dU4hzfzsHEj9ytd3nt0gEceAiACJWBcw-wFEq9qir35bwKHJZxtQ9mOL7SKiVkLQNDa6A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khi831z8dTejFIRCvCEwx_6romtM&txp=4532434&vprv=1"); } diff --git a/src/client/response/player.rs b/src/client/response/player.rs index a880dd5..9654b21 100644 --- a/src/client/response/player.rs +++ b/src/client/response/player.rs @@ -92,6 +92,7 @@ pub(crate) struct StreamingData { pub dash_manifest_url: Option, /// Only on livestreams pub hls_manifest_url: Option, + pub server_abr_streaming_url: Option, pub drm_params: Option, #[serde(default)] #[serde_as(deserialize_as = "VecSkipError<_>")] @@ -294,9 +295,13 @@ pub(crate) struct StoryboardRenderer { pub spec: String, } +#[serde_as] #[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct PlayerConfig { + #[serde(default)] + #[serde_as(deserialize_as = "DefaultOnError")] + pub media_common_config: Option, pub web_drm_config: Option, } @@ -306,6 +311,18 @@ pub(crate) struct WebDrmConfig { pub widevine_service_cert: Option, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MediaCommonConfig { + pub media_ustreamer_request_config: UstreamerRequestConfig, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UstreamerRequestConfig { + pub video_playback_ustreamer_config: String, +} + #[derive(Default, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct HeartbeatParams { diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap index 56cbc1c..7d3fbe6 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap @@ -61,7 +61,7 @@ VideoPlayer( ), video_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1619781&dur=163.143&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=17&lmt=1580005480199246&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2F3gpp&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659459429&mv=m&mvi=5&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAJ2s7Pm4w42X3u3PWYViDeqIaE2tE9J6oIGpd0KB9gFsAiAH84QaJ4oUNivdRDUBi1ZYI7JSxESsPQ53mLInajKzcQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1619781&dur=163.143&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=17&lmt=1580005480199246&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2F3gpp&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659459429&mv=m&mvi=5&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAJ2s7Pm4w42X3u3PWYViDeqIaE2tE9J6oIGpd0KB9gFsAiAH84QaJ4oUNivdRDUBi1ZYI7JSxESsPQ53mLInajKzcQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 17, bitrate: 79452, average_bitrate: 79428, @@ -81,7 +81,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=11439331&dur=163.096&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=18&lmt=1580005476071743&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=AOq0QJ8wRQIhAJAH-tWof01vrs8phEoz51XkWwdMzQ77k1UTrdY5XiuTAiA38z-qANX0jtfCiAl4EVMZaKo1ncrzJFRrCffZ6LagrA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=11439331&dur=163.096&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=18&lmt=1580005476071743&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=AOq0QJ8wRQIhAJAH-tWof01vrs8phEoz51XkWwdMzQ77k1UTrdY5XiuTAiA38z-qANX0jtfCiAl4EVMZaKo1ncrzJFRrCffZ6LagrA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 18, bitrate: 561339, average_bitrate: 561109, @@ -101,7 +101,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - 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", + url: Some("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, @@ -123,7 +123,7 @@ VideoPlayer( ], video_only_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1224002&dur=163.029&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=394&keepalive=yes&lmt=1608045375671513&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=AOq0QJ8wRQIgYCPleG9F86UoDRvzFL2xSUUI-HLZGw_P7qBOixlcmKsCIQChdmrJ1NvKo5Ra4QJ9ivR5V8fEcQs0f_3aUiqMhGB5DQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1224002&dur=163.029&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=394&keepalive=yes&lmt=1608045375671513&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=AOq0QJ8wRQIgYCPleG9F86UoDRvzFL2xSUUI-HLZGw_P7qBOixlcmKsCIQChdmrJ1NvKo5Ra4QJ9ivR5V8fEcQs0f_3aUiqMhGB5DQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 394, bitrate: 67637, average_bitrate: 60063, @@ -149,7 +149,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2238952&dur=163.029&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=395&keepalive=yes&lmt=1608045728968690&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=AOq0QJ8wRQIhAKCXHOCh_P3VlNWebTeWw0WdSln-zYe3BjZeEm2QiltCAiAQNcJBI4G-8dK5z1IUoqBZctk6ddjkl_QYKRFAKXyOcw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2238952&dur=163.029&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=395&keepalive=yes&lmt=1608045728968690&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=AOq0QJ8wRQIhAKCXHOCh_P3VlNWebTeWw0WdSln-zYe3BjZeEm2QiltCAiAQNcJBI4G-8dK5z1IUoqBZctk6ddjkl_QYKRFAKXyOcw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 395, bitrate: 135747, average_bitrate: 109867, @@ -175,7 +175,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=7808990&dur=163.029&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=134&keepalive=yes&lmt=1580005649163759&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=AOq0QJ8wRQIhAIjjrMvCEzSLlbvbrjItT4V9JdpggnO5IHye9i4PxTyzAiAmbaFCB2hH7evf9JX3JUx-tU9S6zv2IzSKz8ObGSVRjw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=7808990&dur=163.029&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=134&keepalive=yes&lmt=1580005649163759&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=AOq0QJ8wRQIhAIjjrMvCEzSLlbvbrjItT4V9JdpggnO5IHye9i4PxTyzAiAmbaFCB2hH7evf9JX3JUx-tU9S6zv2IzSKz8ObGSVRjw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 134, bitrate: 538143, average_bitrate: 383195, @@ -201,7 +201,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=4130385&dur=163.029&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=396&keepalive=yes&lmt=1608045761576250&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=AOq0QJ8wRQIgBrQhbygTP6RGjUk0lGbxBI5e3NdeR6C_SW8R_ckZ2PkCIQDaBg5cJxYVWfwRrrELQFgRMOJ4xS3oOOROayoQMjxaCA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=4130385&dur=163.029&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=396&keepalive=yes&lmt=1608045761576250&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=AOq0QJ8wRQIgBrQhbygTP6RGjUk0lGbxBI5e3NdeR6C_SW8R_ckZ2PkCIQDaBg5cJxYVWfwRrrELQFgRMOJ4xS3oOOROayoQMjxaCA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 396, bitrate: 258097, average_bitrate: 202682, @@ -227,7 +227,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=6873325&dur=163.029&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=397&keepalive=yes&lmt=1608045990917419&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=AOq0QJ8wRQIhAMqBb1hKVVzWl3Awrh1T8GQG9IrSWF84zW_ZfjgbAN5QAiAaP3jYyI4ox2aclcOCzYFzqWgByWCxj_FgTN-SfsARXw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=6873325&dur=163.029&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=397&keepalive=yes&lmt=1608045990917419&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=AOq0QJ8wRQIhAMqBb1hKVVzWl3Awrh1T8GQG9IrSWF84zW_ZfjgbAN5QAiAaP3jYyI4ox2aclcOCzYFzqWgByWCxj_FgTN-SfsARXw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 397, bitrate: 436843, average_bitrate: 337281, @@ -253,7 +253,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - 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", + url: Some("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, average_bitrate: 1097369, @@ -279,7 +279,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=65400181&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=299&keepalive=yes&lmt=1580005649161486&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=AOq0QJ8wRgIhAPjxbuzkozPDc1Nd_0q5X8x8H2SiDvAUFuqqMadtz3SNAiEA_3kXCeePb2kci-WB2779tzI56E6E0iKwoHnUSkKCzwU%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=65400181&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=299&keepalive=yes&lmt=1580005649161486&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=AOq0QJ8wRgIhAPjxbuzkozPDc1Nd_0q5X8x8H2SiDvAUFuqqMadtz3SNAiEA_3kXCeePb2kci-WB2779tzI56E6E0iKwoHnUSkKCzwU%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 299, bitrate: 4190323, average_bitrate: 3208919, @@ -305,7 +305,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=42567727&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=399&keepalive=yes&lmt=1608052932785283&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=AOq0QJ8wRAIgFguw-cmBNOQegpyRRzcCScp2WaSnq_o7FB1-AiBgFpICIAGlMj9-kzNCWb3nhpg98Mc239ls6YYyoL8z1QpM8VmL&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=42567727&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=399&keepalive=yes&lmt=1608052932785283&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=AOq0QJ8wRAIgFguw-cmBNOQegpyRRzcCScp2WaSnq_o7FB1-AiBgFpICIAGlMj9-kzNCWb3nhpg98Mc239ls6YYyoL8z1QpM8VmL&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 399, bitrate: 2572342, average_bitrate: 2088624, @@ -333,7 +333,7 @@ VideoPlayer( ], audio_streams: [ AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=995840&dur=163.189&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=139&keepalive=yes&lmt=1580005582214385&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%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=AOq0QJ8wRQIhALhtrbIL9_CQBeXsEwxFqyPY1XqBCOceQc7y00h7XBS9AiAH9VkMnkuFCU1ACkYU__uApTwcYeDoYNU74VYmKED3Gw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=995840&dur=163.189&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=139&keepalive=yes&lmt=1580005582214385&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%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=AOq0QJ8wRQIhALhtrbIL9_CQBeXsEwxFqyPY1XqBCOceQc7y00h7XBS9AiAH9VkMnkuFCU1ACkYU__uApTwcYeDoYNU74VYmKED3Gw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 139, bitrate: 49724, average_bitrate: 48818, @@ -357,7 +357,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=934449&dur=163.061&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=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRAIgPmadKd9As393GMRmu1Ow4RfQkDQhY6SbPRnkLMYyZOoCIE9AIgMMJ7n5HD2gKv3c8-HrnkMeakq_uWUOivnWquJX&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=934449&dur=163.061&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=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRAIgPmadKd9As393GMRmu1Ow4RfQkDQhY6SbPRnkLMYyZOoCIE9AIgMMJ7n5HD2gKv3c8-HrnkMeakq_uWUOivnWquJX&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 249, bitrate: 53039, average_bitrate: 45845, @@ -381,7 +381,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1245866&dur=163.061&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=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRQIge8uetzhejNg3DegY9EQkpvVam1gp8Jm-q6oqtb6Rn9wCIQD_VeQle7Z2H1uXB6qsYMGDU4OWA4h6YTTwMDmw5DDvuA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=1245866&dur=163.061&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=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRQIge8uetzhejNg3DegY9EQkpvVam1gp8Jm-q6oqtb6Rn9wCIQD_VeQle7Z2H1uXB6qsYMGDU4OWA4h6YTTwMDmw5DDvuA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 250, bitrate: 71268, average_bitrate: 61123, @@ -405,7 +405,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2640283&dur=163.096&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=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%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=AOq0QJ8wRQIhAI8YylDImOPxxRo251u_RX6ir_j0p-gP_yQPcI6SxareAiArCxOcgrF9pxYS5bNYEnLGEQxRiEFJ0sT2Ydpa1G7x5A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2640283&dur=163.096&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=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%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=AOq0QJ8wRQIhAI8YylDImOPxxRo251u_RX6ir_j0p-gP_yQPcI6SxareAiArCxOcgrF9pxYS5bNYEnLGEQxRiEFJ0sT2Ydpa1G7x5A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=2211222&vprv=1"), itag: 140, bitrate: 130268, average_bitrate: 129508, @@ -429,7 +429,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2476314&dur=163.061&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=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRQIgErpt4HOgIybMGrMD2qg9JB4O53n0jsCxkiI9JBxbz8ECIQDixyFJ54m4NsxhyFtIYPscMVp_G6RyvwrfKzdoya-62Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=ANDROID&clen=2476314&dur=163.061&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=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhAOiL-qJ04sA8FSOkEJfOYl3gFe4SzwYu_rAf3DMLHYigAiEA0Upi1HqqIu7NH_LTDL0jT1R5TTozQypL5FiSP9RoqtU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&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=AOq0QJ8wRQIgErpt4HOgIybMGrMD2qg9JB4O53n0jsCxkiI9JBxbz8ECIQDixyFJ54m4NsxhyFtIYPscMVp_G6RyvwrfKzdoya-62Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&txp=1311222&vprv=1"), itag: 251, bitrate: 140633, average_bitrate: 121491, @@ -465,6 +465,8 @@ VideoPlayer( valid_until: "[date]", hls_manifest_url: None, dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659481355/ei/q1jpYtOPEYSBgQeHmqbwAQ/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr5---sn-h0jeenek.googlevideo.com/mh/mQ/mm/31%2C29/mn/sn-h0jeenek%2Csn-h0jelnez/ms/au%2Crdu/mv/m/mvi/5/pl/37/hfr/1/as/fmp4_audio_clear%2Cfmp4_sd_hd_clear/initcwndbps/1527500/vprv/1/mt/1659459429/fvip/4/itag_bl/376%2C377%2C384%2C385%2C612%2C613%2C617%2C619%2C623%2C628%2C655%2C656%2C660%2C662%2C666%2C671/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cvprv%2Citag/sig/AOq0QJ8wRAIgMm4a_MIHA3YUszKeruSy3exs5JwNjJAyLAwxL0yPdNMCIANb9GDMSTp_NT-PPhbvYMwRULJ5a9BO6MYD9FuWprC1/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgETSOwhwWVMy7gmrFXZlJu655ToLzSwOEsT16oRyrWhACIQDkvOEw1fImz5omu4iVIRNFe-z-JC9v8WUyx281dW2NOw%3D%3D"), + abr_streaming_url: None, + abr_ustreamer_config: Some("Cs0CCAAlMZkqPi0AAIA_NT0Klz9YAXjoAoABAaABAbUB9ijcP-ABAegBA_ABAfkBAAAAAAAA0D-BAgAAAAAAABhAmALwAaAC6AK4AgDaAlUQsOoBGKhGIKCcASjYNjCYdXCIJ4AB9AO4AQHgAQGYAgyoAgGwAgG4AgHAAgHIAgHQAgLgAgHoAgLwAgGAAwaIA4gnmAMBqAMIsAMBuAMBwAMB2AMB-gIrCAwQGBgyIDItAABwQjUAAIxCQAFIAWUAAIBAaMBwzQEAAIA_8AEB6ALgA4IDAJADAaADAbADA-ADkE6wBAG4BAHKBFgKFQiA4gkQmHUYrAIlAAAAACgAMABAARDg1AMY0A8qNgoKdGJfY29zdF81MCAIKQAAAAAAAAAASAFQAV2amZk-ZQAAAD9tAAAAP3UAAAA_eMCpB5IBADAB6AQB8AQB-AQBkAUBGAEgATIMCKsCEI662NuboOcCMgwIjwMQg-na_r_Q7QIyDAiqAhCOutjbm6DnAjIMCI4DEJXUhISv0O0CMgwIhwEQjrrY25ug5wIyDAiNAxCr6siQptDtAjIMCIYBEO_L2NuboOcCMgwIjAMQuvqao6XQ7QIyDAiFARCOutjbm6DnAjIMCIsDEPLf1JOl0O0CMgwIoAEQjrrY25ug5wIyDAiKAxDZmZnro9DtAjIMCIsBEPGp4ruboOcCMgwIjAEQ6M3Jupug5wIyDAj5ARCykfms493tAjIMCPoBELju26zj3e0CMgwI-wEQ_NOLrePd7QI6AA=="), preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap index d140467..3ceaadf 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap @@ -66,7 +66,7 @@ VideoPlayer( ), video_streams: [ VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=11439331&dur=163.096&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=18&lmt=1580005476071743&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=ig_QojS86GYHYg&ns=cOm8mnsR9HFwfq55dDyGyqYH&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgNqstD2C4HG7Vn5En5Z4aUyH2mk7gAB9cyfOAWGCaWeoCIQDbxxJZuOnz_3RJNviFYADvgTO7u8YBYKtpFtp9Ujmk2w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=11439331&dur=163.096&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=18&lmt=1580005476071743&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=ig_QojS86GYHYg&ns=cOm8mnsR9HFwfq55dDyGyqYH&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgNqstD2C4HG7Vn5En5Z4aUyH2mk7gAB9cyfOAWGCaWeoCIQDbxxJZuOnz_3RJNviFYADvgTO7u8YBYKtpFtp9Ujmk2w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1"), itag: 18, bitrate: 561339, average_bitrate: 561109, @@ -88,7 +88,7 @@ VideoPlayer( ], video_only_streams: [ VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=1484736&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=278&keepalive=yes&lmt=1608509388295661&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgDYs7xrSqi-Co90zypk9zutEJ-aaEpNAHWnE57zVIfxgCIQDE0exs9SN8JH5OEJ8728Ke6bfa0CsUucFETHLk3IFF7w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=1484736&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=278&keepalive=yes&lmt=1608509388295661&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgDYs7xrSqi-Co90zypk9zutEJ-aaEpNAHWnE57zVIfxgCIQDE0exs9SN8JH5OEJ8728Ke6bfa0CsUucFETHLk3IFF7w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 278, bitrate: 87458, average_bitrate: 72857, @@ -114,7 +114,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=1224002&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=394&keepalive=yes&lmt=1608045375671513&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAI-uoNLUkMHpH35niVh1tBvwwFLtmSbeHyknmyCvccFVAiB2XriyJd0u2q-tGIRTx5qtKt6bJCs5ndXtMsdSxOheuA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=1224002&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=394&keepalive=yes&lmt=1608045375671513&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAI-uoNLUkMHpH35niVh1tBvwwFLtmSbeHyknmyCvccFVAiB2XriyJd0u2q-tGIRTx5qtKt6bJCs5ndXtMsdSxOheuA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 394, bitrate: 67637, average_bitrate: 60063, @@ -140,7 +140,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=2973283&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=242&keepalive=yes&lmt=1608509388282028&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgEleuqkeo7x7BsHur5aGPfHaT6KjKEG4c1d_xXwqlrsYCIQD85X_m050XwWyYlfLiWtZz-TX--H8H0UvfZCWKpY7m4Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=2973283&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=242&keepalive=yes&lmt=1608509388282028&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgEleuqkeo7x7BsHur5aGPfHaT6KjKEG4c1d_xXwqlrsYCIQD85X_m050XwWyYlfLiWtZz-TX--H8H0UvfZCWKpY7m4Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 242, bitrate: 184064, average_bitrate: 145902, @@ -166,7 +166,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=2238952&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=395&keepalive=yes&lmt=1608045728968690&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIBttTR02kTdGb4vdxQ9Gro88JOAY7u5z69nJbdmVS1sAiBr61rqkUtra4PHLdnp2w-s8ZSaN_4qZ3OEeeuIr5C13w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=2238952&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=395&keepalive=yes&lmt=1608045728968690&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIBttTR02kTdGb4vdxQ9Gro88JOAY7u5z69nJbdmVS1sAiBr61rqkUtra4PHLdnp2w-s8ZSaN_4qZ3OEeeuIr5C13w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 395, bitrate: 135747, average_bitrate: 109867, @@ -192,7 +192,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=7808990&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMBRhMAZ5GXFSZHN6D-XhXRdG_EWSNwnN2eLPlwVNQ6PAiEA75eH0iJLgwRkujaABZnaJxG2ni-4irYHEGD42x6uaQg%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=7808990&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMBRhMAZ5GXFSZHN6D-XhXRdG_EWSNwnN2eLPlwVNQ6PAiEA75eH0iJLgwRkujaABZnaJxG2ni-4irYHEGD42x6uaQg%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1"), itag: 134, bitrate: 538143, average_bitrate: 383195, @@ -218,7 +218,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=5169510&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=243&keepalive=yes&lmt=1608509388282405&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgNi0fwQbep6oKsEeEGfms2Ay4x2OL2G0hUX5GFhycgKkCIANiC-j-Gz3-noxsNeSKKPxy--T9mFBu_8V7Vi5-zDYS&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=5169510&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=243&keepalive=yes&lmt=1608509388282405&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgNi0fwQbep6oKsEeEGfms2Ay4x2OL2G0hUX5GFhycgKkCIANiC-j-Gz3-noxsNeSKKPxy--T9mFBu_8V7Vi5-zDYS&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 243, bitrate: 319085, average_bitrate: 253673, @@ -244,7 +244,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=4130385&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=396&keepalive=yes&lmt=1608045761576250&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgFuBoOIkqwq0D1_OmnNJx3C0jmhHUyskpzPrTMoaWRYECIFZ1Y4QbQ41GsWS8yRHox8l_nGVosfXhXfKu3v18AyeT&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=4130385&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=396&keepalive=yes&lmt=1608045761576250&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgFuBoOIkqwq0D1_OmnNJx3C0jmhHUyskpzPrTMoaWRYECIFZ1Y4QbQ41GsWS8yRHox8l_nGVosfXhXfKu3v18AyeT&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 396, bitrate: 258097, average_bitrate: 202682, @@ -270,7 +270,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=8890590&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=244&keepalive=yes&lmt=1608509388284632&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgMYF0KQQNgYI8oOhgdCwyRY6E_hvFnJiaAadyMf89MRoCIHnDnROTvUoy0iIBM3MzFAxJh_bLA-2vFl9KFDrHOf1B&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=8890590&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=244&keepalive=yes&lmt=1608509388284632&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgMYF0KQQNgYI8oOhgdCwyRY6E_hvFnJiaAadyMf89MRoCIHnDnROTvUoy0iIBM3MzFAxJh_bLA-2vFl9KFDrHOf1B&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 244, bitrate: 539056, average_bitrate: 436270, @@ -296,7 +296,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=6873325&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=397&keepalive=yes&lmt=1608045990917419&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAOtLGFoFtLHIXzNRoSrR7ULbIz91OYmaVQkcSatqNKAiAiEA23ZF7h2BZZCAGc0Zdd2p3PWRotmwLDyH6yYCuQpE8xw%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=6873325&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=397&keepalive=yes&lmt=1608045990917419&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAOtLGFoFtLHIXzNRoSrR7ULbIz91OYmaVQkcSatqNKAiAiEA23ZF7h2BZZCAGc0Zdd2p3PWRotmwLDyH6yYCuQpE8xw%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 397, bitrate: 436843, average_bitrate: 337281, @@ -322,7 +322,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=16547577&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=247&keepalive=yes&lmt=1608509388326822&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgfYKbT_196P-2EtjuqcTKdataiM480y65Ko0a73dv7WECIQC6nqWienQvu7swC1OW9HlwFWRH7VwTwj6H4yjY6FYvzg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=16547577&dur=163.029&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=247&keepalive=yes&lmt=1608509388326822&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgfYKbT_196P-2EtjuqcTKdataiM480y65Ko0a73dv7WECIQC6nqWienQvu7swC1OW9HlwFWRH7VwTwj6H4yjY6FYvzg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 247, bitrate: 982813, average_bitrate: 812006, @@ -348,7 +348,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=35955780&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=302&keepalive=yes&lmt=1608509234088626&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgQG8GPj3w_5_Lr2apagmte66IFBY3bYcZ2KnhwnUpshYCIFgvHYIZsz8WdYGSk9adpfMNKX0pzSP_l8cW47Gq2RTi&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=35955780&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=302&keepalive=yes&lmt=1608509234088626&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgQG8GPj3w_5_Lr2apagmte66IFBY3bYcZ2KnhwnUpshYCIFgvHYIZsz8WdYGSk9adpfMNKX0pzSP_l8cW47Gq2RTi&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 302, bitrate: 2354009, average_bitrate: 1764202, @@ -374,7 +374,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=22365208&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=398&keepalive=yes&lmt=1608048380553749&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAI-VhcBU6o8LGmeuVYC2_zbxeGvC6XWf7yIOQ1RvjURhAiEA0YcZlVOI2ZUtKl-31__Hzax2SOUPeekCRjqjfw4m15s%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=22365208&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=398&keepalive=yes&lmt=1608048380553749&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAI-VhcBU6o8LGmeuVYC2_zbxeGvC6XWf7yIOQ1RvjURhAiEA0YcZlVOI2ZUtKl-31__Hzax2SOUPeekCRjqjfw4m15s%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 398, bitrate: 1348419, average_bitrate: 1097369, @@ -400,7 +400,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=65400181&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAIdbG-deTvLhp7mD2b-QZYQamPFv75l1bNBEEOMihrxPAiEA1NYvRlFphbRRvFIBCP-Ij9-5q8OTwUskgsL6LyIrD7c%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=65400181&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAIdbG-deTvLhp7mD2b-QZYQamPFv75l1bNBEEOMihrxPAiEA1NYvRlFphbRRvFIBCP-Ij9-5q8OTwUskgsL6LyIrD7c%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1"), itag: 299, bitrate: 4190323, average_bitrate: 3208919, @@ -426,7 +426,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=62993617&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=303&keepalive=yes&lmt=1608509371758331&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAJ8n34LQhg6iEg1Ux9rDkk48e8l3vBR4WwuHeIpKnorlAiBopK4z-nq-pJTPTmrdbbKPW1Lfufdz2f9sGUKY-dzk5A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=62993617&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=303&keepalive=yes&lmt=1608509371758331&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAJ8n34LQhg6iEg1Ux9rDkk48e8l3vBR4WwuHeIpKnorlAiBopK4z-nq-pJTPTmrdbbKPW1Lfufdz2f9sGUKY-dzk5A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 303, bitrate: 3832648, average_bitrate: 3090839, @@ -452,7 +452,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=42567727&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=399&keepalive=yes&lmt=1608052932785283&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAMewAT3SgJRGn7wqDaDzNWcsAfrjFRu6k0wm7O_5YJeQAiANVhGmILp_gmNXnmixDesxsZ44_72YBT2SqjLLSZV32w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303%2C394%2C395%2C396%2C397%2C398%2C399&c=WEB&clen=42567727&dur=163.046&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=399&keepalive=yes&lmt=1608052932785283&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAMewAT3SgJRGn7wqDaDzNWcsAfrjFRu6k0wm7O_5YJeQAiANVhGmILp_gmNXnmixDesxsZ44_72YBT2SqjLLSZV32w%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 399, bitrate: 2572342, average_bitrate: 2088624, @@ -480,7 +480,7 @@ VideoPlayer( ], audio_streams: [ AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=934449&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAOdVu1woKNveQspV4WPm1PHrOBuzlrnPu2ZLvyiYZCSbAiAYODN_y5t1oU334SHUqqgyc4Wnt-9If-W98Fd966fy2A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=934449&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAOdVu1woKNveQspV4WPm1PHrOBuzlrnPu2ZLvyiYZCSbAiAYODN_y5t1oU334SHUqqgyc4Wnt-9If-W98Fd966fy2A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 249, bitrate: 53039, average_bitrate: 45845, @@ -504,7 +504,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=1245866&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAMJJ-uGQureE70LIxHjHP9hFxqcWwsSlxXX6EjGKmFfEAiAvQ98YKkqUrweNnBZOI7pXJk1kuU_1hSsQ0KeNU4CbyQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=1245866&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAMJJ-uGQureE70LIxHjHP9hFxqcWwsSlxXX6EjGKmFfEAiAvQ98YKkqUrweNnBZOI7pXJk1kuU_1hSsQ0KeNU4CbyQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 250, bitrate: 71268, average_bitrate: 61123, @@ -528,7 +528,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=2640283&dur=163.096&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhANXIw4pIwIPvMGWnJSrA_bnmBX6KPBPqak18aPtKsI8jAiBvisRnEtFax7OTrwKbOiktCihoMraLkCi7Rnnu6JGmeQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=2640283&dur=163.096&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhANXIw4pIwIPvMGWnJSrA_bnmBX6KPBPqak18aPtKsI8jAiBvisRnEtFax7OTrwKbOiktCihoMraLkCi7Rnnu6JGmeQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=2211222&vprv=1"), itag: 140, bitrate: 130268, average_bitrate: 129508, @@ -552,7 +552,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=2476314&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAKP_KjT_SSnz5WGXaveO56pJAEw166qT3cpBdAZI1zwCAiBWZKVQZxfOPWnqSp5FnRDyQBQ-6a2nZopyA1eHicgHtw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=2476314&dur=163.061&ei=q1jpYtq3BJCX1gKVyJGQDg&expire=1659481355&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AGfBIFoT5D_NZAwXN7lVCS2VYLDMMegfaJQqvSJp-Hhy&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhANxHzq0WC6OvdTpPJp52z3eGAm-jzUX7fcKiWlJ0T9kEAiEA02Bjesi_an2-pUh0kHdKQe0s_7micbcv3JKiBlxsYGs%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5edn6k&ms=au%2Conr&mt=1659459429&mv=m&mvi=4&n=T16m7p0RvV7UhQ&ns=tWuNfisHu8yiCA6Avm7nUlwH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAKP_KjT_SSnz5WGXaveO56pJAEw166qT3cpBdAZI1zwCAiBWZKVQZxfOPWnqSp5FnRDyQBQ-6a2nZopyA1eHicgHtw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-KhrZGE2opztWyVdAtyUNlb8dXPDs&txp=1311222&vprv=1"), itag: 251, bitrate: 140633, average_bitrate: 121491, @@ -588,6 +588,8 @@ VideoPlayer( valid_until: "[date]", hls_manifest_url: None, dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659481355/ei/q1jpYtq3BJCX1gKVyJGQDg/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr4---sn-h0jelnez.googlevideo.com/mh/mQ/mm/31%2C26/mn/sn-h0jelnez%2Csn-4g5edn6k/ms/au%2Conr/mv/m/mvi/4/pl/37/hfr/all/as/fmp4_audio_clear%2Cwebm_audio_clear%2Cwebm2_audio_clear%2Cfmp4_sd_hd_clear%2Cwebm2_sd_hd_clear/initcwndbps/1513750/spc/lT-KhrZGE2opztWyVdAtyUNlb8dXPDs/vprv/1/mt/1659459429/fvip/4/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cspc%2Cvprv%2Citag/sig/AOq0QJ8wRgIhAPEjHK19PKVHqQeia6WF4qubuMYk74LGi8F8lk5ZMPkFAiEAsaB2pKQWBvuPnNUnbdQXHc-izgsHJUP793woC2xNJlg%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgOY4xu4H9wqPVZ7vF2i0hFcOnqrur1XGoA43a7ZEuuSUCIQCyPxBKXUQrKFmknNEGpX5GSWySKgMw_xHBikWpKpKwvg%3D%3D"), + abr_streaming_url: None, + abr_ustreamer_config: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap index 47fbb1e..a6c2df6 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap @@ -34,7 +34,7 @@ VideoPlayer( ), video_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=11439331&dur=163.096&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=18&lmt=1580005476071743&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=mAEwZepBJSQPkQ&ns=orl5qWACo00YlHHyQZ7a6awH&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhANfXubbDcXpc25m3F5xQ97ygJRjrTvm8ruVxgnxgFAUBAiAEnj_3KacDNTTLUk-6ZEbL-52zxmBLU1iuTEDx0NvJzA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=11439331&dur=163.096&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=18&lmt=1580005476071743&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=mAEwZepBJSQPkQ&ns=orl5qWACo00YlHHyQZ7a6awH&pl=37&ratebypass=yes&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhANfXubbDcXpc25m3F5xQ97ygJRjrTvm8ruVxgnxgFAUBAiAEnj_3KacDNTTLUk-6ZEbL-52zxmBLU1iuTEDx0NvJzA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1"), itag: 18, bitrate: 561339, average_bitrate: 561109, @@ -56,7 +56,7 @@ VideoPlayer( ], video_only_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=1484736&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=278&keepalive=yes&lmt=1608509388295661&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgEQ0-VVvo41T4l2X26p5zP8Wo8sXOPmBWvCf2OW33ilgCIH2bIFOYgpmsml7FvRQj_SoLzPh7yBvmLZ61Kgsj4FUe&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=1484736&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=278&keepalive=yes&lmt=1608509388295661&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgEQ0-VVvo41T4l2X26p5zP8Wo8sXOPmBWvCf2OW33ilgCIH2bIFOYgpmsml7FvRQj_SoLzPh7yBvmLZ61Kgsj4FUe&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 278, bitrate: 87458, average_bitrate: 72857, @@ -82,7 +82,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2973283&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=242&keepalive=yes&lmt=1608509388282028&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAO7DI5E91yHpLhgiWg9C99NsMoJBVOWsNTNF3os9kREQAiAr2oC8vFtXIHwkJJt45q0sdmjiJdkTO2i8VAjUodk6Xw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2973283&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=242&keepalive=yes&lmt=1608509388282028&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAO7DI5E91yHpLhgiWg9C99NsMoJBVOWsNTNF3os9kREQAiAr2oC8vFtXIHwkJJt45q0sdmjiJdkTO2i8VAjUodk6Xw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 242, bitrate: 184064, average_bitrate: 145902, @@ -108,7 +108,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=7808990&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgTkOjFd0nExEtpr8sBIaNu9HhkxWNdjhSKufHMhLR8-8CIHJAmOuCD7VBv_krH6rn5zqXFqAfsq9rQPXlC3CcQrjM&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=7808990&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgTkOjFd0nExEtpr8sBIaNu9HhkxWNdjhSKufHMhLR8-8CIHJAmOuCD7VBv_krH6rn5zqXFqAfsq9rQPXlC3CcQrjM&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1"), itag: 134, bitrate: 538143, average_bitrate: 383195, @@ -134,7 +134,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=5169510&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=243&keepalive=yes&lmt=1608509388282405&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAPqQfxwIANgIC3DrQ6avaWOhCvIMLdzMPQtFOx2gwEXNAiAwJp2mgN9-zl4vPOB2uoQXOfmGsYDB470q1zg7wRW4Sw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=5169510&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=243&keepalive=yes&lmt=1608509388282405&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAPqQfxwIANgIC3DrQ6avaWOhCvIMLdzMPQtFOx2gwEXNAiAwJp2mgN9-zl4vPOB2uoQXOfmGsYDB470q1zg7wRW4Sw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 243, bitrate: 319085, average_bitrate: 253673, @@ -160,7 +160,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=8890590&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=244&keepalive=yes&lmt=1608509388284632&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIjdvhcThMxoo_v2bzEjaR_w0ryWFQDs0f0INaI5WPcVAiApQZUYTqcQJdfxZlNSsp7cl3FK8XPfDZ-qbVvj9GuauQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=8890590&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=244&keepalive=yes&lmt=1608509388284632&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIjdvhcThMxoo_v2bzEjaR_w0ryWFQDs0f0INaI5WPcVAiApQZUYTqcQJdfxZlNSsp7cl3FK8XPfDZ-qbVvj9GuauQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 244, bitrate: 539056, average_bitrate: 436270, @@ -186,7 +186,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=16547577&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=247&keepalive=yes&lmt=1608509388326822&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgBV4Oa1IQ0YNDvRrKO5ec3Pfbg65MxzmIxCcm0gOuwT0CIFysQdow6DQXzz1W9KZVuqACTdjXQ3-yiBj9GcmNw3HE&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=16547577&dur=163.029&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=247&keepalive=yes&lmt=1608509388326822&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgBV4Oa1IQ0YNDvRrKO5ec3Pfbg65MxzmIxCcm0gOuwT0CIFysQdow6DQXzz1W9KZVuqACTdjXQ3-yiBj9GcmNw3HE&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 247, bitrate: 982813, average_bitrate: 812006, @@ -212,7 +212,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=35955780&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=302&keepalive=yes&lmt=1608509234088626&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAOiqSNfGfOprZ9InWVMc7gY0KrTf8weLibcpK0W2Hfa6AiAFHW213qsByzlar5ivCAYttjo1rPciQnLEnh-izJ3ZhA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=35955780&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=302&keepalive=yes&lmt=1608509234088626&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAOiqSNfGfOprZ9InWVMc7gY0KrTf8weLibcpK0W2Hfa6AiAFHW213qsByzlar5ivCAYttjo1rPciQnLEnh-izJ3ZhA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 302, bitrate: 2354009, average_bitrate: 1764202, @@ -238,7 +238,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=65400181&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgdkJv6w9_Azf0m6poA-ULyX0eH_GKBtSJRwUY1lNBAZgCIDCrC0lnu__ycTaIhg0pUcsRUqay60S3QMo5084EWifd&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=65400181&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%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=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgdkJv6w9_Azf0m6poA-ULyX0eH_GKBtSJRwUY1lNBAZgCIDCrC0lnu__ycTaIhg0pUcsRUqay60S3QMo5084EWifd&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1"), itag: 299, bitrate: 4190323, average_bitrate: 3208919, @@ -264,7 +264,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=62993617&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=303&keepalive=yes&lmt=1608509371758331&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgZi9dDSMWh10NID8-QNn3azIH1zw5UooZrRTPZjVn7hYCIAm9bFc6NBwJ_DzY4V2R_zGmJSpOwQl8LEsfCb7hf6i7&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=62993617&dur=163.046&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=303&keepalive=yes&lmt=1608509371758331&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgZi9dDSMWh10NID8-QNn3azIH1zw5UooZrRTPZjVn7hYCIAm9bFc6NBwJ_DzY4V2R_zGmJSpOwQl8LEsfCb7hf6i7&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 303, bitrate: 3832648, average_bitrate: 3090839, @@ -292,7 +292,7 @@ VideoPlayer( ], audio_streams: [ AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=934449&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMUfr2X-eQJt1abn-IK1H4d5DtvKZuBaETo4opNi6mqCAiEAvBmrmuaoFjB1CJ2Kug87w-Uv6OCdxyrJ_3HIaHX9KBI%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=934449&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=249&keepalive=yes&lmt=1608509101590706&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMUfr2X-eQJt1abn-IK1H4d5DtvKZuBaETo4opNi6mqCAiEAvBmrmuaoFjB1CJ2Kug87w-Uv6OCdxyrJ_3HIaHX9KBI%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 249, bitrate: 53039, average_bitrate: 45845, @@ -316,7 +316,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=1245866&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIflUU4t4Ukf4CXW3ttB5c8SnP4z4z3ef-7EFVMFv4U8AiAlcKmmofCTzzr2NRRsRVosQdpDBphUqWyVzS7noGrixw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=1245866&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=250&keepalive=yes&lmt=1608509101111096&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAIflUU4t4Ukf4CXW3ttB5c8SnP4z4z3ef-7EFVMFv4U8AiAlcKmmofCTzzr2NRRsRVosQdpDBphUqWyVzS7noGrixw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 250, bitrate: 71268, average_bitrate: 61123, @@ -340,7 +340,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2640283&dur=163.096&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhALBveArAZ7DP9r1BIpNz6ZXst5MtzvUM72jhtYMrildCAiEArvwqaqcowZwR_UrRM-O7jq2CMxgBtbnmul27AEcBqEI%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2640283&dur=163.096&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhALBveArAZ7DP9r1BIpNz6ZXst5MtzvUM72jhtYMrildCAiEArvwqaqcowZwR_UrRM-O7jq2CMxgBtbnmul27AEcBqEI%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=2211222&vprv=1"), itag: 140, bitrate: 130268, average_bitrate: 129508, @@ -364,7 +364,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2476314&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgARPqD-6172OshMHeV8DpONV7tnPvdsxcg8QlaIGxcuMCICSe8LWvhRTEO2bdAQ43OzOoc5XfJcj3veyhScVXVz8O&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=WEB_REMIX&clen=2476314&dur=163.061&ei=knDpYub6BojEgAf6jbLgDw&expire=1659487474&fexp=24001373%2C24007246&fvip=4&gir=yes&id=o-AM-wcJVO-yYYbVFnuifnzM4eRnD-AG1bS1AhLoDqi_is&initcwndbps=1418750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=251&keepalive=yes&lmt=1608509101894140&lsig=AG3C_xAwRgIhAMwYJqxve8BSujC-oaSFBbq67p-rFi7saU5V8Yb3qrjLAiEAlrMKR_sadHrkFpy7o7lGzKOCmU1OQazCNBbXjDT2a-o%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1659465669&mv=m&mvi=5&n=1taQMNHGExb_Vg&ns=UTT8RXHZNhPYTw6NgkzWMWEH&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRAIgARPqD-6172OshMHeV8DpONV7tnPvdsxcg8QlaIGxcuMCICSe8LWvhRTEO2bdAQ43OzOoc5XfJcj3veyhScVXVz8O&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&spc=lT-Khox4YuJQ2wmH79zYALRvsWTPCUc&txp=1311222&vprv=1"), itag: 251, bitrate: 140633, average_bitrate: 121491, @@ -400,6 +400,8 @@ VideoPlayer( valid_until: "[date]", hls_manifest_url: None, dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659487474/ei/knDpYub6BojEgAf6jbLgDw/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr5---sn-h0jeenek.googlevideo.com/mh/mQ/mm/31%2C29/mn/sn-h0jeenek%2Csn-h0jelnez/ms/au%2Crdu/mv/m/mvi/5/pl/37/hfr/all/as/fmp4_audio_clear%2Cwebm_audio_clear%2Cwebm2_audio_clear%2Cfmp4_sd_hd_clear%2Cwebm2_sd_hd_clear/initcwndbps/1418750/spc/lT-Khox4YuJQ2wmH79zYALRvsWTPCUc/vprv/1/mt/1659465669/fvip/4/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cspc%2Cvprv%2Citag/sig/AOq0QJ8wRAIgErABhAEaoKHUDu9dDbpxE_8gR4b8WWAi61fnu8UKnuICIEYrEKcHvqHdO4V3R7cvSGwi_HGH34IlQsKbziOfMBov/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgJxHmH0Sxo3cY_pW_ZzQ3hW9-7oz6K_pZWcUdrDDQ2sQCIQDJYNINQwLgKelgbO3CZYx7sMxdUAFpWdokmRBQ77vwvw%3D%3D"), + abr_streaming_url: None, + abr_ustreamer_config: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap index 94d9f38..72669c4 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap @@ -57,7 +57,7 @@ VideoPlayer( video_streams: [], video_only_streams: [ VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=7808990&dur=163.029&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMFQo_RyC3Ud44QVGtKckMcuq5UQ3J7CgYsYl0bXaWMUAiEAhMi1h0ru4zoIGX0jBZT23dozvtrhf_m61p4qbAfEhZo%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=7808990&dur=163.029&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=134&keepalive=yes&lmt=1580005649163759&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMFQo_RyC3Ud44QVGtKckMcuq5UQ3J7CgYsYl0bXaWMUAiEAhMi1h0ru4zoIGX0jBZT23dozvtrhf_m61p4qbAfEhZo%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1"), itag: 134, bitrate: 538143, average_bitrate: 383195, @@ -83,7 +83,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=65400181&dur=163.046&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAP6zxXXA18ToZWUfalauhhsgOsDHTu-R0QrqNrJR7D5kAiEAi8HBa9OkYwmA0bcRxhgvXfN9JsFlXwCWJ-x4ty6TjoY%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=65400181&dur=163.046&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=299&keepalive=yes&lmt=1580005649161486&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAP6zxXXA18ToZWUfalauhhsgOsDHTu-R0QrqNrJR7D5kAiEAi8HBa9OkYwmA0bcRxhgvXfN9JsFlXwCWJ-x4ty6TjoY%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1"), itag: 299, bitrate: 4190323, average_bitrate: 3208919, @@ -111,7 +111,7 @@ VideoPlayer( ], audio_streams: [ AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=995840&dur=163.189&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=139&keepalive=yes&lmt=1580005582214385&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMXDvZZznm1LafIKh_pdGf-TjY5Kz-F9N67o6gXenKouAiEA5qji45i5ABmAytPDOORjw0OaBmwX88S7bgUWcmF-_LU%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=995840&dur=163.189&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=139&keepalive=yes&lmt=1580005582214385&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRgIhAMXDvZZznm1LafIKh_pdGf-TjY5Kz-F9N67o6gXenKouAiEA5qji45i5ABmAytPDOORjw0OaBmwX88S7bgUWcmF-_LU%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1"), itag: 139, bitrate: 49724, average_bitrate: 48818, @@ -135,7 +135,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=2640283&dur=163.096&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgcsPm6rrUAwCi1VTGf0FMDTjzjM01__iTC13PnzDTFeQCIQCJ_EGeKVZztkmK3Cr7gVuxUP83XCSlP01YLx5FO-PPcQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1", + url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&clen=2640283&dur=163.096&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&itag=140&keepalive=yes&lmt=1580005579712232&lsig=AG3C_xAwRQIgWKVoDpyI6QmVnkdGzdirFtjMAXhmLex64VTO7UUJd-4CIQDoJKkT2-Kpa7j0merJJoZDs4IkkXSjdNm3bvdCL8t2Pg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&otfp=1&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIgcsPm6rrUAwCi1VTGf0FMDTjzjM01__iTC13PnzDTFeQCIQCJ_EGeKVZztkmK3Cr7gVuxUP83XCSlP01YLx5FO-PPcQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cotfp%2Cdur%2Clmt&svpuc=1&txp=2211222&vprv=1"), itag: 140, bitrate: 130268, average_bitrate: 129508, @@ -171,6 +171,8 @@ VideoPlayer( valid_until: "[date]", hls_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1659481355/ei/q1jpYq-xHs7NgQev0bfwAQ/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr4---sn-h0jelnez.googlevideo.com/mh/mQ/mm/31%2C29/mn/sn-h0jelnez%2Csn-h0jeenek/ms/au%2Crdu/mv/m/mvi/4/pl/37/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/1513750/vprv/1/go/1/mt/1659459429/fvip/5/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/fexp/24001373%2C24007246/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AOq0QJ8wRQIhAIYnEHvIgJtJ8hehAXNtVY3qsgsq_GdOhWf2hkJZe6lCAiBxaRY_nubYp6hBizcAg_KFkKnkG-t2XYLRQ5wGdM3AjA%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRgIhAM_91Kk_0VLuSsR6nLCY7LdtWojyRAzXSScd_X9ShRROAiEA1AF4VY04F71NsAI8_j3iqjuXnWL9s6NoXHq7P8-bHx8%3D/file/index.m3u8"), dash_manifest_url: None, + abr_streaming_url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&keepalive=yes&lsig=AG3C_xAwRgIhAK6T5ehnFBsc0FOurPHH1ME_vGcVysI-g5jrtEsvX64sAiEArY-iAvQCsc4R8yg8dvMdpnuHPIcPMCnRgyh8E527HF0%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&pl=37&rbqsm=fr&requiressl=yes&sabr=1&sig=AOq0QJ8wRgIhAJCJpb5gE12jQc2qOUy-Y61vEHeiAP_F78weNCzj8VklAiEAwR2PK52CmwsVHfRVk75OOYOxwYKNW2g1eDBw3COBP9w%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Csvpuc%2Csabr&svpuc=1"), + abr_ustreamer_config: Some("CpYECp0DCAAQgAUY6AIl-n6qPi0AAIA_NT0Klz9oAXI6ChJtZnMyX2NtZnNfdjNfMV8wNDMSIAoeCgxkZXZpY2VfbW9kZWwSDgoMCgppcGhvbmUxNCw1GAAgAXIWChJtZnMyX2NtZnNfdjNfMV8wNDMYAHjoAoABAagBAbUB9ijcP6AC6AK4AgDaAmEQsOoBGKhGIKCcASjYNjCYdXCIJ4AB9AO4AQHgAQP4AQGQAgGYAgygAgGoAgGwAgG4AgHAAgHIAgHQAgLgAgHoAgLwAgGAAwKIA4gnmAMBqAMIwAMByAMB2AMB-LWR5QwB-gIvCAwQGBgyIDItAABwQjUAAIxCQAFIAVAKWAplAACAQGjAcM0BAACAP_ABAegC0AWCAwCQAwGgAwGoAwGwAwPQAwHYAwHgA5BOuAQBygRWChUI4NQDEJh1GOgHJQAAAAAoADAAQAEQ4NQDGNAPKjYKCnRiX2Nvc3RfNTAgDykAAAAAAAAAAEgBUAFdZmbmPmXNzEw-bZqZGT91mpkZP3jAqQeSAQDoBAHwBAH4BAGQBQGgBQEYASABMgwIqwIQjrrY25ug5wIyDAiqAhCOutjbm6DnAjIMCIcBEI662NuboOcCMgwIhgEQ78vY25ug5wIyDAiFARCOutjbm6DnAjIMCKABEI662NuboOcCMgwIiwEQ8aniu5ug5wIyDAiMARDozcm6m6DnAjoAEkwA8tjvwTBFAiAyo6mtW-M8Y8noBO_6Y3RmNo5U2LntCwiKcI2yye_zRgIhAK27d1UbqzhtkQhminIBAajD70ONeAQNwjt7VRpJRDimGgJlaQ=="), preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwGbA0g48quKqQOSA4gBAZUBAAAEQpgBMqABPKgBBLABELABDbABDLABELABFbABH7ABJrABLbABDrABDrABD7ABErABF7ABK7ABLLABKbABD7ABDrABELABFbABH7ABKrABMrABKbABD7ABEbABFLABGLABJrABPbABOLABLbABEbABFLABHrABKrABMbABS7ABR7ABNrABFbABHLABKbABLrABObABR7ABTbABP7ABJbABLrABN7ABPbABR7ABUrABUbABRbABM7ABQLABQrABQ7ABTLABRLABRrABQ7gBEbgBEbgBFbgBI7gBRLgBQ7gBQ7gBQ7gBEbgBE7gBFrgBL7gBQ7gBQ7gBQ7gBQ7gBFbgBFrgBKbgBQ7gBQ7gBQ7gBQ7gBQ7gBI7gBL7gBQ7gBQ7gBQ7gBQ7gBQ7gBQ7gBRLgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLCsCT8Lprh2S0ptmCRsWH7VtDl3YQ", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap index b7d5a29..32ba960 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap @@ -24,7 +24,7 @@ VideoPlayer( ), video_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IT4iUCpJNJWUitTMgIi6njuKSsi3MNed1Szyf0qysTX0v1Nf6AyCvjIGbek5Fn50kuBrGtRJ5q&c=TVHTML5&clen=10262148&dur=163.096&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=18&lmt=1700885551970466&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=BMzwItzIOB1HhmG&ns=YmgbZhlLp0C-9ilsQWGAyUAQ&pl=26&ratebypass=yes&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgUah4qH8RqPzmo75ExCWSiRYlUlsAk0v9gl638LitVNICICxFs5lK3CsmOAja0bsXavXkyykzpdhHZKGXOZQYT1f8&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&svpuc=1&txp=1318224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IT4iUCpJNJWUitTMgIi6njuKSsi3MNed1Szyf0qysTX0v1Nf6AyCvjIGbek5Fn50kuBrGtRJ5q&c=TVHTML5&clen=10262148&dur=163.096&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=18&lmt=1700885551970466&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=BMzwItzIOB1HhmG&ns=YmgbZhlLp0C-9ilsQWGAyUAQ&pl=26&ratebypass=yes&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgUah4qH8RqPzmo75ExCWSiRYlUlsAk0v9gl638LitVNICICxFs5lK3CsmOAja0bsXavXkyykzpdhHZKGXOZQYT1f8&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&svpuc=1&txp=1318224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 18, bitrate: 503574, average_bitrate: 503367, @@ -46,7 +46,7 @@ VideoPlayer( ], video_only_streams: [ VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2273274&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=160&keepalive=yes&lmt=1705967288821438&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgb8eXnQ6MSJ3PuvFVBdYIWTnFobH8mTC9zbZpBNxLbBYCICkPLKEm3gNbW5HIFXs7bwF5rSqUKHHnXNK91qMslQog&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2273274&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=160&keepalive=yes&lmt=1705967288821438&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgb8eXnQ6MSJ3PuvFVBdYIWTnFobH8mTC9zbZpBNxLbBYCICkPLKEm3gNbW5HIFXs7bwF5rSqUKHHnXNK91qMslQog&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 160, bitrate: 114816, average_bitrate: 111551, @@ -72,7 +72,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=1151892&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=278&keepalive=yes&lmt=1705966620402771&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAP4IybR7cZRpx7IX1ke6UIu_hdFZN3LOuHBDywg_xv5WAiB8_XEx8VhT9OlFxmM-cY0fl6-7GT9uj3clMIPDk2w7cA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=1151892&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=278&keepalive=yes&lmt=1705966620402771&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAP4IybR7cZRpx7IX1ke6UIu_hdFZN3LOuHBDywg_xv5WAiB8_XEx8VhT9OlFxmM-cY0fl6-7GT9uj3clMIPDk2w7cA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 278, bitrate: 70630, average_bitrate: 56524, @@ -98,7 +98,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=5026513&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=133&keepalive=yes&lmt=1705967298859029&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgPF0ms4OEe15BTjOFVCkvf52UeTUf0b62_pavCfEyGjcCIH-0AoxzyT8iioWFFaX7iYjqzzaUTpo8rgAPQ0uX8DJa&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=5026513&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=133&keepalive=yes&lmt=1705967298859029&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgPF0ms4OEe15BTjOFVCkvf52UeTUf0b62_pavCfEyGjcCIH-0AoxzyT8iioWFFaX7iYjqzzaUTpo8rgAPQ0uX8DJa&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 133, bitrate: 257417, average_bitrate: 246656, @@ -124,7 +124,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2541351&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=242&keepalive=yes&lmt=1705966614837727&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgKj1JyMGwYtf16zLJsmbnizz5_v3jaZSa7-j-ls8-qzECIQDKUd50iIc52h7zOX50Hf1SkbV9h-hP4QHs-wkik1fk6Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2541351&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=242&keepalive=yes&lmt=1705966614837727&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgKj1JyMGwYtf16zLJsmbnizz5_v3jaZSa7-j-ls8-qzECIQDKUd50iIc52h7zOX50Hf1SkbV9h-hP4QHs-wkik1fk6Q%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 242, bitrate: 149589, average_bitrate: 124706, @@ -150,7 +150,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=7810925&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=134&keepalive=yes&lmt=1705967286812435&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAJ92IgZgdk3_WLsfzJV_ZyrSFSbzpsoJh3DkRKDHbNxzAiEA9UbnVlXQ2S3BUimLmWC5TZQfhIkc-PlLnZ81fL0S5yA%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=7810925&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=134&keepalive=yes&lmt=1705967286812435&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAJ92IgZgdk3_WLsfzJV_ZyrSFSbzpsoJh3DkRKDHbNxzAiEA9UbnVlXQ2S3BUimLmWC5TZQfhIkc-PlLnZ81fL0S5yA%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 134, bitrate: 537902, average_bitrate: 383290, @@ -176,7 +176,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=4188954&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=243&keepalive=yes&lmt=1705966624121874&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgSCLGQvdZKNXym0zt7c3Yw_4e0J8-wNxtPagPRRn4dRoCIQCOj0IzalNG4EcowBIyK2LC6NLFDr8Zt6sNVkqPjw6lGg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=4188954&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=243&keepalive=yes&lmt=1705966624121874&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgSCLGQvdZKNXym0zt7c3Yw_4e0J8-wNxtPagPRRn4dRoCIQCOj0IzalNG4EcowBIyK2LC6NLFDr8Zt6sNVkqPjw6lGg%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 243, bitrate: 248858, average_bitrate: 205556, @@ -202,7 +202,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=14723538&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=135&keepalive=yes&lmt=1705967282545273&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAM843wAa1e7Gc1S69gfXckm7hdgIKPXp0bUSh3hO6W5zAiEA-DDEPGsZBmF5N8VbPy75dhy3rLpE1F18KtWgmrUm2Pg%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=14723538&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=135&keepalive=yes&lmt=1705967282545273&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAM843wAa1e7Gc1S69gfXckm7hdgIKPXp0bUSh3hO6W5zAiEA-DDEPGsZBmF5N8VbPy75dhy3rLpE1F18KtWgmrUm2Pg%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 135, bitrate: 978945, average_bitrate: 722499, @@ -228,7 +228,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=7788899&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=244&keepalive=yes&lmt=1705966622098793&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAKGyn799bfkVHYE195sPmD60dCMppqJrBM0O-sjgYTzzAiAoBjkNAtL90sXw2YP9UTW9JrMhPSvPiBI_KiCVMJAkFQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=7788899&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=244&keepalive=yes&lmt=1705966622098793&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAKGyn799bfkVHYE195sPmD60dCMppqJrBM0O-sjgYTzzAiAoBjkNAtL90sXw2YP9UTW9JrMhPSvPiBI_KiCVMJAkFQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 244, bitrate: 467884, average_bitrate: 382209, @@ -254,7 +254,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=24616305&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=136&keepalive=yes&lmt=1705967307531372&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAM57L2Utesn4xVyT0HSwR9Khv_S-efx4uFAbCPkZFoRXAiEAtIu63-jF2_FZkOMmZAqGU3SRU9QgxoajRjBhMFwcOuk%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=24616305&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=136&keepalive=yes&lmt=1705967307531372&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAM57L2Utesn4xVyT0HSwR9Khv_S-efx4uFAbCPkZFoRXAiEAtIu63-jF2_FZkOMmZAqGU3SRU9QgxoajRjBhMFwcOuk%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 136, bitrate: 1560439, average_bitrate: 1207947, @@ -280,7 +280,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=14723992&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=247&keepalive=yes&lmt=1705966613897741&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAL-upITxk7r9FQL5F4WL0A6SjPw673qyyzmXIC48eKfTAiEAlkdkx7IFYtehbhKakbffvIebpPXRtxSgBWLl7WEHCrE%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=14723992&dur=163.029&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=247&keepalive=yes&lmt=1705966613897741&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAL-upITxk7r9FQL5F4WL0A6SjPw673qyyzmXIC48eKfTAiEAlkdkx7IFYtehbhKakbffvIebpPXRtxSgBWLl7WEHCrE%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 247, bitrate: 929607, average_bitrate: 722521, @@ -306,7 +306,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=34544823&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=298&keepalive=yes&lmt=1705967092637061&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAIIGU41JunuODw9qIlSoYQcwkCYO6k9XOVlDn1Nxqnu7AiEAoiMOgYU8s8lp01fW0L86hHrSrtlvOLSI9XA50iyIGBc%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=34544823&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=298&keepalive=yes&lmt=1705967092637061&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRgIhAIIGU41JunuODw9qIlSoYQcwkCYO6k9XOVlDn1Nxqnu7AiEAoiMOgYU8s8lp01fW0L86hHrSrtlvOLSI9XA50iyIGBc%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 298, bitrate: 2188961, average_bitrate: 1694973, @@ -332,7 +332,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=30205331&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=302&keepalive=yes&lmt=1705966545733919&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAL428Az_BKxxff4FlH4WleHSy4Igq3mR71NuTMOc9xU3AiBN4lXfH9DklGaQUMnOT8wAhiMuzR73bW3cwr744TSoNA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=30205331&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=302&keepalive=yes&lmt=1705966545733919&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAL428Az_BKxxff4FlH4WleHSy4Igq3mR71NuTMOc9xU3AiBN4lXfH9DklGaQUMnOT8wAhiMuzR73bW3cwr744TSoNA%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 302, bitrate: 2250391, average_bitrate: 1482051, @@ -358,7 +358,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=62057888&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=299&keepalive=yes&lmt=1705967093743693&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgBEemc0Cvd3KhNooNRblgX64_fjNSP30RmWDfFwDR7qYCIQCXpQ9FO0_X93ZHcyvRZCKX5gbJuusCReaRcJbRLFsM_g%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=62057888&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=299&keepalive=yes&lmt=1705967093743693&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%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=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgBEemc0Cvd3KhNooNRblgX64_fjNSP30RmWDfFwDR7qYCIQCXpQ9FO0_X93ZHcyvRZCKX5gbJuusCReaRcJbRLFsM_g%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 299, bitrate: 3926810, average_bitrate: 3044926, @@ -384,7 +384,7 @@ VideoPlayer( drm_systems: [], ), VideoStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=55300085&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=303&keepalive=yes&lmt=1705966651743358&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgTZlmOcsLYJ_a9SnVLehXnaoajtreQO97qawEIDPEi8sCIQDKFdtBWWMuQUb9X8H-x92B3q-y0g8TvAPanR95cfklXQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C298%2C299%2C302%2C303&bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=55300085&dur=163.046&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=303&keepalive=yes&lmt=1705966651743358&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=video%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgTZlmOcsLYJ_a9SnVLehXnaoajtreQO97qawEIDPEi8sCIQDKFdtBWWMuQUb9X8H-x92B3q-y0g8TvAPanR95cfklXQ%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=130F224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 303, bitrate: 3473307, average_bitrate: 2713348, @@ -412,7 +412,7 @@ VideoPlayer( ], audio_streams: [ AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=934750&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=249&keepalive=yes&lmt=1714877357172339&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAItfaWkRs94vqyae7GR4M1xHoQO2lduvNRFugRSf0h-IAiA9fdLOJMwPI8vAO2C13igyv2qGSpOlKQptS4sN6p5Ffw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=934750&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=249&keepalive=yes&lmt=1714877357172339&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIhAItfaWkRs94vqyae7GR4M1xHoQO2lduvNRFugRSf0h-IAiA9fdLOJMwPI8vAO2C13igyv2qGSpOlKQptS4sN6p5Ffw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 249, bitrate: 53073, average_bitrate: 45860, @@ -436,7 +436,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=1245582&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=250&keepalive=yes&lmt=1714877466693058&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgdJ1SjWwaloQecEblSIMFp2qFmpG_kKYZP1vX_M55dE0CIQCDSfa_FsaiFRcNL-1LRTgCIRSO7dj5vrpKR1Ya-KbmMw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=1245582&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=250&keepalive=yes&lmt=1714877466693058&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgdJ1SjWwaloQecEblSIMFp2qFmpG_kKYZP1vX_M55dE0CIQCDSfa_FsaiFRcNL-1LRTgCIRSO7dj5vrpKR1Ya-KbmMw%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 250, bitrate: 71197, average_bitrate: 61109, @@ -460,7 +460,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2640283&dur=163.096&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=140&keepalive=yes&lmt=1705966477945761&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgSxdbLrbojMVJcyRzsI2TrzOf78LN28bWcsHpbs4QXDwCIHidfXoriWMHfuiktUCdzLuUmksU7r5vITdh6u0puNmx&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2640283&dur=163.096&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=140&keepalive=yes&lmt=1705966477945761&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fmp4&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRAIgSxdbLrbojMVJcyRzsI2TrzOf78LN28bWcsHpbs4QXDwCIHidfXoriWMHfuiktUCdzLuUmksU7r5vITdh6u0puNmx&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 140, bitrate: 130268, average_bitrate: 129508, @@ -484,7 +484,7 @@ VideoPlayer( drm_systems: [], ), AudioStream( - url: "https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2480393&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=251&keepalive=yes&lmt=1714877359450110&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgO0jG-x2l6AF7tjryIX_oM3np78WgNDiseezppLfbQrgCIQCVLdpDhclKc8vQgWGzKXcqsAxgNl5S3MlLT8u1Jeok2A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D", + url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?bui=AXc671IvQBUNCtxNiAkj0M-Bvcb-N5cUu1XFk68f4Cnj0sFLEy1sixyW5lThzLYJXioG8kVQ2xT9KNLS&c=TVHTML5&clen=2480393&dur=163.061&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&gir=yes&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&itag=251&keepalive=yes&lmt=1714877359450110&lmw=1&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mime=audio%2Fwebm&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=SWvqB0UTkUvifuM&ns=ZR8RwjQ3VJGDvQifdaM1IRMQ&pl=26&requiressl=yes&rqh=1&sefc=1&sig=AJfQdSswRQIgO0jG-x2l6AF7tjryIX_oM3np78WgNDiseezppLfbQrgCIQCVLdpDhclKc8vQgWGzKXcqsAxgNl5S3MlLT8u1Jeok2A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Csvpuc%2Cmime%2Cns%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&svpuc=1&txp=1308224&vprv=1&xpc=EgVo2aDSNQ%3D%3D"), itag: 251, bitrate: 140833, average_bitrate: 121691, @@ -520,6 +520,8 @@ VideoPlayer( valid_until: "[date]", hls_manifest_url: None, dash_manifest_url: None, + abr_streaming_url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=TVHTML5&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&keepalive=yes&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=eBXmY26Y0c3VPyt&ns=Kl83P0QZk1oI9742KUD7ly8Q&pl=26&requiressl=yes&rqh=1&sabr=1&sig=AJfQdSswRAIgJRK55pIkQ3Pak9jZ4fHPDsxXv0YgkxKE-FFdIN12ph8CIFHlFEvAoUOoX4Fd1RmyCJqgLZhDkSLwD6s-xVW25kYL&smc=1&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Csvpuc%2Cns%2Csabr%2Crqh&svpuc=1&xpc=EgVo2aDSNQ%3D%3D"), + abr_ustreamer_config: Some("CswJCpcHCAAlAACAPy1SuF4_NQAAwD9YAWABaAFyFgoSbWZzMl9jbWZzX3YzXzJfMTA5GAB4j06gAQGoAQCQAgG4AgDIAgHaAroBELDqARioRiCgnAEoiCcwmHVwiCeAAfQDuAEB4AEDkAIBmAIMoAIBwAIB0AIC4AIB6AIEgAMCiAOIJ5gDAagDA8ADAcgDAdADAfgDAYAEAYgEAZAEAZgEAaAEAagEAcgEAdAEAdgEAeAEAOgEAfgEB4AFfYgFAbAFAbgFAcAFAcgFAdAFAdgFAeAF0A_oBQH4BdAPgAYBuAYBwAYB0AYB2AYB6AYB8AYB-AYBkAcBqAcB2AcB-LWR5QwB-gKeAi0AAIJCNQAAlkJIAWUAAIBAaMBwqAHQhgOwAeADuAEBzQEAAIA_8AEB_QEAAIA_hQKamRk-jQIAAIA_lQIAAAJCmAIBtQIAAIA_wALgA9ICEbD__________wEePEZaXF1e2gIFMjA6MDDgAnjoAugC9QIK16M7_QLNzMw9gAMBkAMBnQMK1yM9oAMBuAMByAMB2AMB5QNiSkRA7QMyyvM-8AMB_QNmZoY_hQQAAIBAmAQB1QQAACBB6ATwEPAEAb0Fo0Afu8UF308tP8gFAeAFAZgGAaAGAagGAbUGvTeGNb0GMzODQJAHAcAHAcgHAdUHAICdQ-UHAIAJRKEIAAAAAAAA8L-pCAAAAAAAAPC_sAjwAbgIAdgI8AHoCAGCAwCQAwGoAwGwAwPQAwHYAwHgA5BOuAQBygQcChMIwKkHEJh1GOgHJQAAAAAoADAAEODUAxjQD9IEDQoICLAJELAJIAEgiCfaBAsKBgjwLhDwLiCIJ-gEAfgEAYAFAYgFAZAFAagFAbAFAdAFAdgFAegFAfAFAYgGAZgGAagGgIACwAYByAYB0gYUCOgHEGQaDQiIJxUAAAA_Hc3MTD-CBwoVAACAPxhkIJBOiAcBoAcBsAcBuAcBwAcB-AcBgAgBoAgBsAgBuAgB0ggGCAEQARgBmAkBqQkAAAAAAADwv7EJAAAAAAAA8L_ICQHaCSRFRzRmTDl1Sm9tL2NWdklmNjg4bnB6c2t4SVQrMXl0N09POHXgCQGwCgHYCgHwCgGICwGYCwG4CwHICwHQCwHYCwHqCwSLBowG8AsB-AsBkAwBoAwBqAyQAbAMAbgMAcAMAdAMAeAMAegMAYANAaANAdANAeANAYgOAZAOAbAOAYinocoLARgBIAEyDAirAhDNgPzUlvKDAzIMCK8CEP64moKV8oMDMgwIiAEQ7Mj0upfygwMyDAj3ARCNxJTwlPKDAzIMCKoCEIW7uNSW8oMDMgwIrgIQn5LUz5TygwMyDAiHARD5xP-ul_KDAzIMCPQBEOmKifSU8oMDMgwIhgEQk_6DsZfygwMyDAjzARCSyIT1lPKDAzIMCIUBEJWg47aX8oMDMgwI8gEQ3_PN8JTygwMyDAigARC-zf6xl_KDAzIMCJYCENPIofOU8oMDMgwIjAEQodeqr5TygwMyDAj5ARDzzNT9v_WFAzIMCPoBEMKb8bHA9YUDMgwI-wEQ_s_f_r_1hQM6AEgAUiYaAmVuKAAyGFVDYnh4RWktSW1QbGJMeDVGLWZIZXRFZzgAQABYAJDL048OARJNAKEYC4YwRgIhAIj4Ug4dw_gq15NXvgcfXpI1Fm_fhmwl-4ad-rX3Ffg_AiEAkZDsUgoAGLOXIvWZlNyuyfu8HLWt-snFl3gkTiPo2acaAmVp"), preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwGbA0g48quKqQOSA4gBAZUBAAAEQpgBMqABPKgBBLABELABDbABDLABELABFbABH7ABJrABLbABDrABDrABD7ABErABF7ABK7ABLLABKbABD7ABDrABELABFbABH7ABKrABMrABKbABD7ABEbABFLABGLABJrABPbABOLABLbABEbABFLABHrABKrABMbABS7ABR7ABNrABFbABHLABKbABLrABObABR7ABTbABP7ABJbABLrABN7ABPbABR7ABUrABUbABRbABM7ABQLABQrABQ7ABTLABRLABRrABQ7gBEbgBEbgBFbgBI7gBRLgBQ7gBQ7gBQ7gBEbgBE7gBFrgBL7gBQ7gBQ7gBQ7gBQ7gBFbgBFrgBKbgBQ7gBQ7gBQ7gBQ7gBQ7gBI7gBL7gBQ7gBQ7gBQ7gBQ7gBQ7gBQ7gBRLgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLCsCT8Lprh2S0ptmCRsWH7VtDl3YQ", diff --git a/src/model/mod.rs b/src/model/mod.rs index 1829adc..7f3b277 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -147,6 +147,10 @@ pub struct VideoPlayer { pub hls_manifest_url: Option, /// Dash manifest URL (for livestreams) pub dash_manifest_url: Option, + /// ABR (adaptive bitrate) streaming URL + pub abr_streaming_url: Option, + /// ABR streaming config + pub abr_ustreamer_config: Option, /// Video frames for seek preview pub preview_frames: Vec, /// Video player DRM config @@ -194,7 +198,7 @@ pub struct VideoPlayerDetails { #[non_exhaustive] pub struct VideoStream { /// Video stream URL - pub url: String, + pub url: Option, /// YouTube stream format identifier pub itag: u32, /// Stream bitrate (in bits/second) @@ -238,7 +242,7 @@ pub struct VideoStream { #[non_exhaustive] pub struct AudioStream { /// Audio stream URL - pub url: String, + pub url: Option, /// YouTube stream format identifier pub itag: u32, /// Stream bitrate (in bits/second) diff --git a/src/model/traits.rs b/src/model/traits.rs index d4f6253..43d4236 100644 --- a/src/model/traits.rs +++ b/src/model/traits.rs @@ -9,7 +9,7 @@ use super::*; /// Trait for YouTube streams (video and audio) pub trait YtStream { /// Stream URL - fn url(&self) -> &str; + fn url(&self) -> Option<&str>; /// YouTube stream format identifier fn itag(&self) -> u32; /// Stream bitrate (in bits/second) @@ -29,8 +29,8 @@ pub trait YtStream { } impl YtStream for VideoStream { - fn url(&self) -> &str { - &self.url + fn url(&self) -> Option<&str> { + self.url.as_deref() } fn itag(&self) -> u32 { @@ -67,8 +67,8 @@ impl YtStream for VideoStream { } impl YtStream for AudioStream { - fn url(&self) -> &str { - &self.url + fn url(&self) -> Option<&str> { + self.url.as_deref() } fn itag(&self) -> u32 { diff --git a/src/param/stream_filter.rs b/src/param/stream_filter.rs index b690bb0..99e9a31 100644 --- a/src/param/stream_filter.rs +++ b/src/param/stream_filter.rs @@ -23,6 +23,7 @@ pub struct StreamFilter { video_codecs: Option>, video_hdr: bool, video_none: bool, + abr_only: bool, drm_track_types: Vec, drm_system: Option, } @@ -176,6 +177,13 @@ impl StreamFilter { self } + /// Allow ABR-only streams without URL + #[must_use] + pub fn abr_only(mut self) -> Self { + self.abr_only = true; + self + } + fn check_drm(&self, track_type: Option, drm_systems: &[DrmSystem]) -> Option<()> { if let Some(track_type) = track_type { if !self.drm_track_types.contains(&track_type) { @@ -189,6 +197,10 @@ impl StreamFilter { } fn apply_audio(&self, stream: &AudioStream) -> AudioRes { + if stream.url.is_none() && !self.abr_only { + return None; + } + let bitrate = match self.audio_max_bitrate { Some(max) => { if stream.average_bitrate > max { @@ -272,6 +284,10 @@ impl StreamFilter { } fn apply_video(&self, stream: &VideoStream) -> VideoRes { + if stream.url.is_none() && !self.abr_only { + return None; + } + let vres = stream.height.min(stream.width); let res = match self.video_max_res { Some(max) => filter_max(vres, max), @@ -466,7 +482,7 @@ mod tests { let selection = player.select_audio_stream(&filter); match expect_url { - Some(expect_url) => assert_eq!(selection.unwrap().url, expect_url), + Some(expect_url) => assert_eq!(selection.unwrap().url.as_deref().unwrap(), expect_url), None => assert_eq!(selection, None), } } @@ -491,7 +507,7 @@ mod tests { let selection = player.select_video_only_stream(&filter); match expect_url { - Some(expect_url) => assert_eq!(selection.unwrap().url, expect_url), + Some(expect_url) => assert_eq!(selection.unwrap().url.as_deref().unwrap(), expect_url), None => assert_eq!(selection, None), } } @@ -526,12 +542,12 @@ mod tests { let (video, audio) = PLAYER_HDR.select_video_audio_stream(&filter); match expect_video_url { - Some(expect_url) => assert_eq!(video.unwrap().url, expect_url), + Some(expect_url) => assert_eq!(video.unwrap().url.as_deref().unwrap(), expect_url), None => assert_eq!(video, None), } match expect_audio_url { - Some(expect_url) => assert_eq!(audio.unwrap().url, expect_url), + Some(expect_url) => assert_eq!(audio.unwrap().url.as_deref().unwrap(), expect_url), None => assert_eq!(audio, None), } } diff --git a/tests/youtube.rs b/tests/youtube.rs index fb7f860..423cc65 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -149,7 +149,7 @@ async fn check_video_stream(s: impl YtStream) { let http = reqwest::Client::new(); let resp = http - .get(s.url()) + .get(s.url().expect("no url")) .send() .await .unwrap() From 3a41899ce7a88edb06845a2062e6dff15cd74c2b Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 17 Mar 2025 00:06:10 +0100 Subject: [PATCH 02/21] feat: add rustypipe-abr-proto crate --- Cargo.toml | 3 +- abr-proto/Cargo.toml | 16 +++++ abr-proto/LICENSE | 21 ++++++ abr-proto/README.md | 5 ++ abr-proto/build.rs | 64 ++++++++++++++++++ abr-proto/proto/misc/common.proto | 28 ++++++++ .../video_streaming/buffered_range.proto | 32 +++++++++ .../video_streaming/client_abr_state.proto | 43 ++++++++++++ .../proto/video_streaming/crypto_params.proto | 13 ++++ .../encrypted_player_request.proto | 18 +++++ .../format_initialization_metadata.proto | 17 +++++ .../proto/video_streaming/live_metadata.proto | 13 ++++ .../video_streaming/media_capabilities.proto | 24 +++++++ .../proto/video_streaming/media_header.proto | 30 +++++++++ .../video_streaming/next_request_policy.proto | 12 ++++ .../proto/video_streaming/onesie_header.proto | 27 ++++++++ .../video_streaming/onesie_header_type.proto | 31 +++++++++ .../onesie_player_request.proto | 12 ++++ .../onesie_player_response.proto | 28 ++++++++ .../video_streaming/onesie_request.proto | 19 ++++++ .../video_streaming/playback_cookie.proto | 11 ++++ .../playback_start_policy.proto | 12 ++++ .../proto/video_streaming/proxy_status.proto | 15 +++++ .../request_cancellation_policy.proto | 14 ++++ .../proto/video_streaming/sabr_error.proto | 7 ++ .../proto/video_streaming/sabr_redirect.proto | 6 ++ .../stream_protection_status.proto | 7 ++ .../video_streaming/streamer_context.proto | 66 +++++++++++++++++++ .../proto/video_streaming/time_range.proto | 8 +++ .../video_playback_abr_request.proto | 51 ++++++++++++++ abr-proto/src/lib.rs | 3 + 31 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 abr-proto/Cargo.toml create mode 100644 abr-proto/LICENSE create mode 100644 abr-proto/README.md create mode 100644 abr-proto/build.rs create mode 100644 abr-proto/proto/misc/common.proto create mode 100644 abr-proto/proto/video_streaming/buffered_range.proto create mode 100644 abr-proto/proto/video_streaming/client_abr_state.proto create mode 100644 abr-proto/proto/video_streaming/crypto_params.proto create mode 100644 abr-proto/proto/video_streaming/encrypted_player_request.proto create mode 100644 abr-proto/proto/video_streaming/format_initialization_metadata.proto create mode 100644 abr-proto/proto/video_streaming/live_metadata.proto create mode 100644 abr-proto/proto/video_streaming/media_capabilities.proto create mode 100644 abr-proto/proto/video_streaming/media_header.proto create mode 100644 abr-proto/proto/video_streaming/next_request_policy.proto create mode 100644 abr-proto/proto/video_streaming/onesie_header.proto create mode 100644 abr-proto/proto/video_streaming/onesie_header_type.proto create mode 100644 abr-proto/proto/video_streaming/onesie_player_request.proto create mode 100644 abr-proto/proto/video_streaming/onesie_player_response.proto create mode 100644 abr-proto/proto/video_streaming/onesie_request.proto create mode 100644 abr-proto/proto/video_streaming/playback_cookie.proto create mode 100644 abr-proto/proto/video_streaming/playback_start_policy.proto create mode 100644 abr-proto/proto/video_streaming/proxy_status.proto create mode 100644 abr-proto/proto/video_streaming/request_cancellation_policy.proto create mode 100644 abr-proto/proto/video_streaming/sabr_error.proto create mode 100644 abr-proto/proto/video_streaming/sabr_redirect.proto create mode 100644 abr-proto/proto/video_streaming/stream_protection_status.proto create mode 100644 abr-proto/proto/video_streaming/streamer_context.proto create mode 100644 abr-proto/proto/video_streaming/time_range.proto create mode 100644 abr-proto/proto/video_streaming/video_playback_abr_request.proto create mode 100644 abr-proto/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index ae8bbec..3b7c5c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ description = "Client for the public YouTube / YouTube Music API (Innertube), in include = ["/src", "README.md", "CHANGELOG.md", "LICENSE", "!snapshots"] [workspace] -members = [".", "codegen", "downloader", "cli"] +members = [".", "codegen", "downloader", "cli", "abr-proto"] [workspace.package] edition = "2021" @@ -56,6 +56,7 @@ urlencoding = "2.1.0" quick-xml = { version = "0.37.0", features = ["serialize"] } tracing = { version = "0.1.0", features = ["log"] } localzone = "0.3.1" +protobuf = "3.0.0" # CLI indicatif = "0.17.0" diff --git a/abr-proto/Cargo.toml b/abr-proto/Cargo.toml new file mode 100644 index 0000000..d5624f0 --- /dev/null +++ b/abr-proto/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustypipe-abr-proto" +version = "0.1.0" +edition.workspace = true +authors.workspace = true +license = "MIT" +repository.workspace = true +keywords.workspace = true +categories.workspace = true +description = "Protobuf definitions for YouTube adaptive bitrate streaming" + +[dependencies] +protobuf.workspace = true + +[build-dependencies] +protobuf-codegen = "3" diff --git a/abr-proto/LICENSE b/abr-proto/LICENSE new file mode 100644 index 0000000..dbb5408 --- /dev/null +++ b/abr-proto/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2025 ThetaDev + +MIT LICENSE +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/abr-proto/README.md b/abr-proto/README.md new file mode 100644 index 0000000..39e70f4 --- /dev/null +++ b/abr-proto/README.md @@ -0,0 +1,5 @@ +# ![RustyPipe](https://codeberg.org/ThetaDev/rustypipe/raw/branch/main/notes/logo.svg) abr-proto + +[![Current crates.io version](https://img.shields.io/crates/v/rustypipe-abr-proto.svg)](https://crates.io/crates/rustypipe-abr-proto) +[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT) +[![CI status](https://codeberg.org/ThetaDev/rustypipe/actions/workflows/ci.yaml/badge.svg?style=flat&label=CI)](https://codeberg.org/ThetaDev/rustypipe/actions/?workflow=ci.yaml) diff --git a/abr-proto/build.rs b/abr-proto/build.rs new file mode 100644 index 0000000..93174f1 --- /dev/null +++ b/abr-proto/build.rs @@ -0,0 +1,64 @@ +use std::{ + env, fs, + ops::Deref, + path::{Path, PathBuf}, +}; + +fn out_dir() -> PathBuf { + Path::new(&env::var("OUT_DIR").expect("env")).to_path_buf() +} + +fn cleanup() { + let _ = fs::remove_dir_all(out_dir()); +} + +fn compile() { + let proto_dir = Path::new(&env::var("CARGO_MANIFEST_DIR").expect("env")).join("proto"); + let vsdir = proto_dir.join("video_streaming"); + + let files = &[ + proto_dir.join("misc").join("common.proto"), + vsdir.join("buffered_range.proto"), + vsdir.join("client_abr_state.proto"), + vsdir.join("crypto_params.proto"), + vsdir.join("encrypted_player_request.proto"), + vsdir.join("format_initialization_metadata.proto"), + vsdir.join("live_metadata.proto"), + vsdir.join("media_capabilities.proto"), + vsdir.join("media_header.proto"), + vsdir.join("next_request_policy.proto"), + vsdir.join("onesie_header_type.proto"), + vsdir.join("onesie_header.proto"), + vsdir.join("onesie_player_request.proto"), + vsdir.join("onesie_player_response.proto"), + vsdir.join("onesie_request.proto"), + vsdir.join("playback_cookie.proto"), + vsdir.join("playback_start_policy.proto"), + vsdir.join("proxy_status.proto"), + vsdir.join("request_cancellation_policy.proto"), + vsdir.join("sabr_error.proto"), + vsdir.join("sabr_redirect.proto"), + vsdir.join("stream_protection_status.proto"), + vsdir.join("streamer_context.proto"), + vsdir.join("time_range.proto"), + vsdir.join("video_playback_abr_request.proto"), + ]; + + let slices = files.iter().map(Deref::deref).collect::>(); + + let out_dir = out_dir(); + fs::create_dir(&out_dir).expect("create_dir"); + + protobuf_codegen::Codegen::new() + .pure() + .out_dir(&out_dir) + .inputs(&slices) + .include(&proto_dir) + .run() + .expect("Codegen failed."); +} + +fn main() { + cleanup(); + compile(); +} diff --git a/abr-proto/proto/misc/common.proto b/abr-proto/proto/misc/common.proto new file mode 100644 index 0000000..e494b7f --- /dev/null +++ b/abr-proto/proto/misc/common.proto @@ -0,0 +1,28 @@ +syntax = "proto2"; +package misc; + +message HttpHeader { + optional string name = 1; + optional string value = 2; +} + +message FormatId { + optional int32 itag = 1; + optional uint64 last_modified = 2; + optional string xtags = 3; +} + +message InitRange { + optional int32 start = 1; + optional int32 end = 2; +} + +message IndexRange { + optional int32 start = 1; + optional int32 end = 2; +} + +message KeyValuePair { + optional string key = 1; + optional string value = 2; +} diff --git a/abr-proto/proto/video_streaming/buffered_range.proto b/abr-proto/proto/video_streaming/buffered_range.proto new file mode 100644 index 0000000..1cef4eb --- /dev/null +++ b/abr-proto/proto/video_streaming/buffered_range.proto @@ -0,0 +1,32 @@ + +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; +import "video_streaming/time_range.proto"; + +message BufferedRange { + required .misc.FormatId format_id = 1; + required int64 start_time_ms = 2; + required int64 duration_ms = 3; + required int32 start_segment_index = 4; + required int32 end_segment_index = 5; + optional TimeRange time_range = 6; + optional Kob field9 = 9; + optional YPa field11 = 11; + optional YPa field12 = 12; +} + +message Kob { + message Pa { + optional string video_id = 1; + optional uint64 lmt = 2; + } + repeated Pa EW = 1; +} + +message YPa { + optional int32 field1 = 1; + optional int32 field2 = 2; + optional int32 field3 = 3; +} diff --git a/abr-proto/proto/video_streaming/client_abr_state.proto b/abr-proto/proto/video_streaming/client_abr_state.proto new file mode 100644 index 0000000..3bd3cfb --- /dev/null +++ b/abr-proto/proto/video_streaming/client_abr_state.proto @@ -0,0 +1,43 @@ +syntax = "proto2"; +package video_streaming; + +message ClientAbrState { + optional int32 time_since_last_manual_format_selection_ms = 13; + optional int32 last_manual_direction = 14; + optional int32 last_manual_selected_resolution = 16; + optional int32 detailed_network_type = 17; + optional int32 client_viewport_width = 18; + optional int32 client_viewport_height = 19; + optional int64 client_bitrate_cap = 20; + optional int32 sticky_resolution = 21; + optional bool client_viewport_is_flexible = 22; + optional int32 bandwidth_estimate = 23; + optional int64 player_time_ms = 28; + optional int64 time_since_last_seek = 29; + optional bool data_saver_mode = 30; + optional int32 visibility = 34; + optional float playback_rate = 35; + optional int64 elapsed_wall_time_ms = 36; + optional bytes media_capabilities = 38; + optional int64 time_since_last_action_ms = 39; + optional int32 enabled_track_types_bitfield = 40; + optional int32 max_pacing_rate = 43; + optional int64 player_state = 44; + optional bool drc_enabled = 46; + optional int32 Jda = 48; + optional int32 qw = 50; + optional int32 Ky = 51; + optional int32 sabr_report_request_cancellation_info = 54; + optional bool l = 56; + optional int64 G7 = 57; + optional bool prefer_vp9 = 58; + optional int32 qj = 59; + optional int32 Hx = 60; + optional bool is_prefetch = 61; + optional int32 sabr_support_quality_constraints = 62; + optional bytes sabr_license_constraint = 63; + optional int32 allow_proxima_live_latency = 64; + optional int32 sabr_force_proxima = 66; + optional int32 Tqb = 67; + optional int64 sabr_force_max_network_interruption_duration_ms = 68; +} diff --git a/abr-proto/proto/video_streaming/crypto_params.proto b/abr-proto/proto/video_streaming/crypto_params.proto new file mode 100644 index 0000000..8c3b077 --- /dev/null +++ b/abr-proto/proto/video_streaming/crypto_params.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; +package video_streaming; + +message CryptoParams { + enum CompressionType { + VAL_0 = 0; + VAL_1 = 1; + VAL_2 = 2; + } + optional bytes hmac = 4; + optional bytes iv = 5; + optional CompressionType compression_type = 6; +} diff --git a/abr-proto/proto/video_streaming/encrypted_player_request.proto b/abr-proto/proto/video_streaming/encrypted_player_request.proto new file mode 100644 index 0000000..bc553e2 --- /dev/null +++ b/abr-proto/proto/video_streaming/encrypted_player_request.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; +package video_streaming; + +import "video_streaming/onesie_player_request.proto"; + +message EncryptedPlayerRequest { + optional bytes context = 1; // InnerTubeContext proto? + optional bytes encrypted_onesie_player_request = 2; + optional bytes encrypted_client_key = 5; + optional bytes iv = 6; + optional bytes hmac = 7; + optional string reverse_proxy_config = 9; + optional bool serialize_response_as_json = 10; + optional bool pM = 13; + optional bool enable_compression = 14; + optional bytes unencrypted_onesie_player_request = 16; + optional bool TQ = 17; +} diff --git a/abr-proto/proto/video_streaming/format_initialization_metadata.proto b/abr-proto/proto/video_streaming/format_initialization_metadata.proto new file mode 100644 index 0000000..b13fa6b --- /dev/null +++ b/abr-proto/proto/video_streaming/format_initialization_metadata.proto @@ -0,0 +1,17 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; + +message FormatInitializationMetadata { + optional string video_id = 1; + optional .misc.FormatId format_id = 2; + optional int32 end_time_ms = 3; + optional int32 field4 = 4; + optional string mime_type = 5; + optional .misc.InitRange init_range = 6; + optional .misc.IndexRange index_range = 7; + optional int32 field8 = 8; + optional int32 duration_ms = 9; + optional int32 field10 = 10; +} diff --git a/abr-proto/proto/video_streaming/live_metadata.proto b/abr-proto/proto/video_streaming/live_metadata.proto new file mode 100644 index 0000000..83c1540 --- /dev/null +++ b/abr-proto/proto/video_streaming/live_metadata.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; +package video_streaming; + +message LiveMetadata { + optional uint32 head_sequence_number = 3; + optional uint64 head_time_ms = 4; + optional uint64 wall_time_ms = 5; + optional uint64 field10 = 10; + optional uint64 field12 = 12; + optional uint64 field13 = 13; + optional uint64 head_time_usec = 14; + optional uint64 field15 = 15; +} diff --git a/abr-proto/proto/video_streaming/media_capabilities.proto b/abr-proto/proto/video_streaming/media_capabilities.proto new file mode 100644 index 0000000..78dfcec --- /dev/null +++ b/abr-proto/proto/video_streaming/media_capabilities.proto @@ -0,0 +1,24 @@ +syntax = "proto2"; +package video_streaming; + +message MediaCapabilities { + repeated VideoFormatCapability video_format_capabilities = 1; + repeated AudioFormatCapability audio_format_capabilities = 2; + optional int32 hdr_mode_bitmask = 5; + + message VideoFormatCapability { + optional int32 video_codec = 1; + optional int32 max_height = 3; + optional int32 max_width = 4; + optional int32 max_framerate = 11; + optional int32 max_bitrate_bps = 12; + optional bool is_10_bit_supported = 15; + } + + message AudioFormatCapability { + optional int32 audio_codec = 1; + optional int32 num_channels = 2; + optional int32 max_bitrate_bps = 3; + optional int32 spatial_capability_bitmask = 6; + } +} diff --git a/abr-proto/proto/video_streaming/media_header.proto b/abr-proto/proto/video_streaming/media_header.proto new file mode 100644 index 0000000..58aa007 --- /dev/null +++ b/abr-proto/proto/video_streaming/media_header.proto @@ -0,0 +1,30 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; +import "video_streaming/time_range.proto"; + +message MediaHeader { + optional uint32 header_id = 1; + optional string video_id = 2; + optional int32 itag = 3; + optional uint64 lmt = 4; + optional string xtags = 5; + optional int32 start_data_range = 6; + optional Compression compression = 7; + optional bool is_init_seg = 8; + optional int64 sequence_number = 9; + optional int64 field10 = 10; + optional int32 start_ms = 11; + optional int32 duration_ms = 12; + optional .misc.FormatId format_id = 13; + optional int64 content_length = 14; + optional TimeRange time_range = 15; + + enum Compression { + VAL0 = 0; + VAL1 = 1; + GZIP = 2; + } + +} diff --git a/abr-proto/proto/video_streaming/next_request_policy.proto b/abr-proto/proto/video_streaming/next_request_policy.proto new file mode 100644 index 0000000..6556912 --- /dev/null +++ b/abr-proto/proto/video_streaming/next_request_policy.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +package video_streaming; + +import "video_streaming/playback_cookie.proto"; + +message NextRequestPolicy { + optional int32 target_audio_readahead_ms = 1; + optional int32 target_video_readahead_ms = 2; + optional int32 backoff_time_ms = 4; + optional .video_streaming.PlaybackCookie playback_cookie = 7; + optional string video_id = 8; +} diff --git a/abr-proto/proto/video_streaming/onesie_header.proto b/abr-proto/proto/video_streaming/onesie_header.proto new file mode 100644 index 0000000..5cd8167 --- /dev/null +++ b/abr-proto/proto/video_streaming/onesie_header.proto @@ -0,0 +1,27 @@ +syntax = "proto2"; +package video_streaming; + +import "video_streaming/onesie_header_type.proto"; +import "video_streaming/crypto_params.proto"; + +message OnesieHeader { + message Field23 { + optional string video_id = 2; + } + + message Field34 { + repeated string itag_denylist = 1; + } + + optional OnesieHeaderType type = 1; + optional string video_id = 2; + optional string itag = 3; + optional CryptoParams crypto_params = 4; + optional uint64 last_modified = 5; + optional int64 media_size_bytes = 7; + repeated string restricted_formats = 11; + optional string xtags = 15; + optional int64 sequence_number = 18; + optional Field23 field23 = 23; + optional Field34 field34 = 34; +} diff --git a/abr-proto/proto/video_streaming/onesie_header_type.proto b/abr-proto/proto/video_streaming/onesie_header_type.proto new file mode 100644 index 0000000..021f01b --- /dev/null +++ b/abr-proto/proto/video_streaming/onesie_header_type.proto @@ -0,0 +1,31 @@ +syntax = "proto2"; +package video_streaming; + +enum OnesieHeaderType { + PLAYER_RESPONSE = 0; + HEADER_TYPE_1 = 1; + MEDIA_DECRYPTION_KEY = 2; + HEADER_TYPE_3 = 3; + HEADER_TYPE_4 = 4; + HEADER_TYPE_5 = 5; + NEW_HOST = 6; + HEADER_TYPE_7 = 7; + HEADER_TYPE_8 = 8; + HEADER_TYPE_9 = 9; + HEADER_TYPE_10 = 10; + HEADER_TYPE_11 = 11; + HEADER_TYPE_12 = 12; + HEADER_TYPE_13 = 13; + RESTRICTED_FORMATS_HINT = 14; + HEADER_TYPE_15 = 15; + STREAM_METADATA = 16; + HEADER_TYPE_17 = 17; + HEADER_TYPE_18 = 18; + HEADER_TYPE_19 = 19; + HEADER_TYPE_20 = 20; + HEADER_TYPE_21 = 21; + HEADER_TYPE_22 = 22; + HEADER_TYPE_23 = 23; + HEADER_TYPE_24 = 24; + ENCRYPTED_INNERTUBE_RESPONSE_PART = 25; +} diff --git a/abr-proto/proto/video_streaming/onesie_player_request.proto b/abr-proto/proto/video_streaming/onesie_player_request.proto new file mode 100644 index 0000000..844bd66 --- /dev/null +++ b/abr-proto/proto/video_streaming/onesie_player_request.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; + +message OnesiePlayerRequest { + optional string url = 1; + repeated misc.HttpHeader headers = 2; + optional string body = 3; + optional bool proxied_by_trusted_bandaid = 4; + optional bool skip_response_encryption = 6; +} diff --git a/abr-proto/proto/video_streaming/onesie_player_response.proto b/abr-proto/proto/video_streaming/onesie_player_response.proto new file mode 100644 index 0000000..41d97a4 --- /dev/null +++ b/abr-proto/proto/video_streaming/onesie_player_response.proto @@ -0,0 +1,28 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; + +enum OnesieProxyStatus { + ONESIE_PROXY_STATUS_UNKNOWN = 0; + ONESIE_PROXY_STATUS_OK = 1; + ONESIE_PROXY_STATUS_DECRYPTION_FAILED = 2; + ONESIE_PROXY_STATUS_PARSING_FAILED = 3; + ONESIE_PROXY_STATUS_MISSING_X_FORWARDED_FOR = 4; + ONESIE_PROXY_STATUS_INVALID_X_FORWARDED_FOR = 5; + ONESIE_PROXY_STATUS_INVALID_CONTENT_TYPE = 6; + ONESIE_PROXY_STATUS_BACKEND_ERROR = 7; + ONESIE_PROXY_STATUS_CLIENT_ERROR = 8; + ONESIE_PROXY_STATUS_MISSING_CRYPTER = 9; + ONESIE_PROXY_STATUS_RESPONSE_JSON_SERIALIZATION_FAILED = 10; + ONESIE_PROXY_STATUS_DECOMPRESSION_FAILED = 11; + ONESIE_PROXY_STATUS_JSON_PARSING_FAILED = 12; + ONESIE_PROXY_STATUS_UNKNOWN_COMPRESSION_TYPE = 13; +} + +message OnesiePlayerResponse { + optional OnesieProxyStatus onesie_proxy_status = 1; + optional int32 http_status = 2; + repeated .misc.HttpHeader headers = 3; + optional bytes body = 4; +} diff --git a/abr-proto/proto/video_streaming/onesie_request.proto b/abr-proto/proto/video_streaming/onesie_request.proto new file mode 100644 index 0000000..5dbf396 --- /dev/null +++ b/abr-proto/proto/video_streaming/onesie_request.proto @@ -0,0 +1,19 @@ +syntax = "proto2"; +package video_streaming; + +import "video_streaming/client_abr_state.proto"; +import "video_streaming/encrypted_player_request.proto"; +import "video_streaming/streamer_context.proto"; +import "video_streaming/buffered_range.proto"; + +message OnesieRequest { + repeated string urls = 1; + optional ClientAbrState client_abr_state = 2; + optional EncryptedPlayerRequest player_request = 3; + optional bytes onesie_ustreamer_config = 4; + optional int32 max_vp9_height = 5; + optional int32 client_display_height = 6; + optional StreamerContext streamer_context = 10; + optional int32 request_target = 13; // MLOnesieRequestTarget + repeated BufferedRange buffered_ranges = 14; +} diff --git a/abr-proto/proto/video_streaming/playback_cookie.proto b/abr-proto/proto/video_streaming/playback_cookie.proto new file mode 100644 index 0000000..eb8ca09 --- /dev/null +++ b/abr-proto/proto/video_streaming/playback_cookie.proto @@ -0,0 +1,11 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; + +message PlaybackCookie { + optional int32 field1 = 1; // Always 999999?? + optional int32 field2 = 2; + optional .misc.FormatId video_fmt = 7; + optional .misc.FormatId audio_fmt = 8; +} diff --git a/abr-proto/proto/video_streaming/playback_start_policy.proto b/abr-proto/proto/video_streaming/playback_start_policy.proto new file mode 100644 index 0000000..2b43367 --- /dev/null +++ b/abr-proto/proto/video_streaming/playback_start_policy.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +package video_streaming; + +message PlaybackStartPolicy { + message ReadaheadPolicy { + optional int32 min_readahead_ms = 2; + optional int32 min_bandwidth_bytes_per_sec = 1; + } + + optional ReadaheadPolicy start_min_readahead_policy = 1; + optional ReadaheadPolicy resume_min_readahead_policy = 2; +} diff --git a/abr-proto/proto/video_streaming/proxy_status.proto b/abr-proto/proto/video_streaming/proxy_status.proto new file mode 100644 index 0000000..18fe610 --- /dev/null +++ b/abr-proto/proto/video_streaming/proxy_status.proto @@ -0,0 +1,15 @@ +syntax = "proto2"; +package video_streaming; + +enum ProxyStatus { + VAL_0 = 0; + OK = 1; + VAL_2 = 2; + VAL_3 = 3; + VAL_4 = 4; + VAL_5 = 5; + VAL_6 = 6; + VAL_7 = 7; + VAL_8 = 8; + VAL_9 = 9; +} diff --git a/abr-proto/proto/video_streaming/request_cancellation_policy.proto b/abr-proto/proto/video_streaming/request_cancellation_policy.proto new file mode 100644 index 0000000..110c259 --- /dev/null +++ b/abr-proto/proto/video_streaming/request_cancellation_policy.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; +package video_streaming; + +message RequestCancellationPolicy { + message Item { + optional int32 fR = 1; + optional int32 NK = 2; + optional int32 minReadaheadMs = 3; + } + + optional int32 N0 = 1; + repeated Item items = 2; + optional int32 jq = 3; +} diff --git a/abr-proto/proto/video_streaming/sabr_error.proto b/abr-proto/proto/video_streaming/sabr_error.proto new file mode 100644 index 0000000..f05311b --- /dev/null +++ b/abr-proto/proto/video_streaming/sabr_error.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; +package video_streaming; + +message SabrError { + optional string type = 1; + optional int32 code = 2; +} diff --git a/abr-proto/proto/video_streaming/sabr_redirect.proto b/abr-proto/proto/video_streaming/sabr_redirect.proto new file mode 100644 index 0000000..e660ad3 --- /dev/null +++ b/abr-proto/proto/video_streaming/sabr_redirect.proto @@ -0,0 +1,6 @@ +syntax = "proto2"; +package video_streaming; + +message SabrRedirect { + optional string url = 1; +} diff --git a/abr-proto/proto/video_streaming/stream_protection_status.proto b/abr-proto/proto/video_streaming/stream_protection_status.proto new file mode 100644 index 0000000..2f2cba4 --- /dev/null +++ b/abr-proto/proto/video_streaming/stream_protection_status.proto @@ -0,0 +1,7 @@ +syntax = "proto2"; +package video_streaming; + +message StreamProtectionStatus { + optional int32 status = 1; + optional int32 field2 = 2; +} diff --git a/abr-proto/proto/video_streaming/streamer_context.proto b/abr-proto/proto/video_streaming/streamer_context.proto new file mode 100644 index 0000000..3a766c3 --- /dev/null +++ b/abr-proto/proto/video_streaming/streamer_context.proto @@ -0,0 +1,66 @@ +syntax = "proto2"; +package video_streaming; + +message StreamerContext { + message ClientInfo { + optional string device_make = 12; + optional string device_model = 13; + optional int32 client_name = 16; + optional string client_version = 17; + optional string os_name = 18; + optional string os_version = 19; + optional string accept_language = 21; + optional string accept_region = 22; + optional int32 screen_width_points = 37; + optional int32 screen_height_points = 38; + optional float screen_width_inches = 39; + optional float screen_height_inches = 40; + optional int32 screen_pixel_density = 41; + optional ClientFormFactor client_form_factor = 46; + optional int32 gmscore_version_code = 50; // e.g. 243731017 + optional int32 window_width_points = 55; + optional int32 window_height_points = 56; + optional int32 android_sdk_version = 64; + optional float screen_density_float = 65; + optional int64 utc_offset_minutes = 67; + optional string time_zone = 80; + optional string chipset = 92; // e.g. "qcom;taro" + optional GLDeviceInfo gl_device_info = 102; + } + + enum ClientFormFactor { + UNKNOWN_FORM_FACTOR = 0; + FORM_FACTOR_VAL1 = 1; + FORM_FACTOR_VAL2 = 2; + } + + message GLDeviceInfo { + optional string gl_renderer = 1; + optional int32 gl_es_version_major = 2; + optional int32 gl_es_version_minor = 3; + } + + message Fqa { + optional int32 type = 1; + optional bytes value = 2; + } + + message Gqa { + message Hqa { + optional int32 code = 1; + optional string message = 2; + } + + optional bytes field1 = 1; + optional Hqa field2 = 2; + } + + optional ClientInfo client_info = 1; + optional bytes po_token = 2; + optional bytes playback_cookie = 3; + optional bytes gp = 4; + repeated Fqa field5 = 5; + repeated int32 field6 = 6; + optional string field7 = 7; + optional Gqa field8 = 8; +} diff --git a/abr-proto/proto/video_streaming/time_range.proto b/abr-proto/proto/video_streaming/time_range.proto new file mode 100644 index 0000000..e85d2f3 --- /dev/null +++ b/abr-proto/proto/video_streaming/time_range.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; +package video_streaming; + +message TimeRange { + optional int64 start = 1; + optional int64 duration = 2; + optional int32 timescale = 3; +} diff --git a/abr-proto/proto/video_streaming/video_playback_abr_request.proto b/abr-proto/proto/video_streaming/video_playback_abr_request.proto new file mode 100644 index 0000000..cc16499 --- /dev/null +++ b/abr-proto/proto/video_streaming/video_playback_abr_request.proto @@ -0,0 +1,51 @@ +syntax = "proto2"; +package video_streaming; + +import "misc/common.proto"; +import "video_streaming/client_abr_state.proto"; +import "video_streaming/streamer_context.proto"; +import "video_streaming/buffered_range.proto"; + +message VideoPlaybackAbrRequest { + optional ClientAbrState client_abr_state = 1; + repeated .misc.FormatId selected_format_ids = 2; + repeated BufferedRange buffered_ranges = 3; + optional int64 player_time_ms = 4; + optional bytes video_playback_ustreamer_config = 5; + optional Lo lo = 6; + repeated .misc.FormatId selected_audio_format_ids = 16; + repeated .misc.FormatId selected_video_format_ids = 17; + optional StreamerContext streamer_context = 19; + optional OQa field21 = 21; + optional int32 field22 = 22; + optional int32 field23 = 23; + repeated Pqa field1000 = 1000; +} + +message Lo { + message Field4 { + optional int32 field1 = 1; + optional int32 field2 = 2; + optional int32 field3 = 3; + } + optional .misc.FormatId format_id = 1; + optional int32 Lj = 2; + optional int32 sequence_number = 3; + optional Field4 field4 = 4; + optional int32 MZ = 5; +} + +message OQa { + repeated string field1 = 1; + optional bytes field2 = 2; + optional string field3 = 3; + optional int32 field4 = 4; + optional int32 field5 = 5; + optional string field6 = 6; +} + +message Pqa { + repeated .misc.FormatId formats = 1; + repeated BufferedRange ud = 2; + optional string clip_id = 3; +} diff --git a/abr-proto/src/lib.rs b/abr-proto/src/lib.rs new file mode 100644 index 0000000..16a04e9 --- /dev/null +++ b/abr-proto/src/lib.rs @@ -0,0 +1,3 @@ +#![doc = include_str!("../README.md")] + +include!(concat!(env!("OUT_DIR"), "/mod.rs")); From f4f3e4f25671a241fbc153434b2aaa328d96fe77 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sat, 22 Mar 2025 21:46:05 +0100 Subject: [PATCH 03/21] wip: working prototype --- Cargo.toml | 1 + .../format_initialization_metadata.proto | 4 +- codegen/src/abtest.rs | 9 + downloader/Cargo.toml | 7 + downloader/src/abr.rs | 676 +++++++++++++++ downloader/src/abr2.rs | 799 ++++++++++++++++++ downloader/src/abr_model.rs | 87 ++ downloader/src/error.rs | 18 + downloader/src/lib.rs | 3 + downloader/src/util.rs | 145 ++++ notes/AB_Tests.md | 7 + src/client/player.rs | 12 +- src/client/response/player.rs | 7 +- src/model/mod.rs | 10 + src/model/traits.rs | 20 + src/param/stream_filter.rs | 13 +- 16 files changed, 1805 insertions(+), 13 deletions(-) create mode 100644 downloader/src/abr.rs create mode 100644 downloader/src/abr2.rs create mode 100644 downloader/src/abr_model.rs diff --git a/Cargo.toml b/Cargo.toml index 3b7c5c0..547b84e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ rustypipe-downloader = { path = "./downloader", version = "0.3.1", default-featu "indicatif", "audiotag", ] } +rustypipe-abr-proto = { path = "./abr-proto", version = "0.1.0" } [features] default = ["default-tls"] diff --git a/abr-proto/proto/video_streaming/format_initialization_metadata.proto b/abr-proto/proto/video_streaming/format_initialization_metadata.proto index b13fa6b..ce7e08e 100644 --- a/abr-proto/proto/video_streaming/format_initialization_metadata.proto +++ b/abr-proto/proto/video_streaming/format_initialization_metadata.proto @@ -7,11 +7,11 @@ message FormatInitializationMetadata { optional string video_id = 1; optional .misc.FormatId format_id = 2; optional int32 end_time_ms = 3; - optional int32 field4 = 4; + optional int32 sequence_count = 4; optional string mime_type = 5; optional .misc.InitRange init_range = 6; optional .misc.IndexRange index_range = 7; optional int32 field8 = 8; optional int32 duration_ms = 9; - optional int32 field10 = 10; + optional int32 field10 = 10; } diff --git a/codegen/src/abtest.rs b/codegen/src/abtest.rs index de8001a..0f90b13 100644 --- a/codegen/src/abtest.rs +++ b/codegen/src/abtest.rs @@ -42,6 +42,7 @@ pub enum ABTest { MusicContinuationItemRenderer = 20, AlbumRecommends = 21, CommandExecutorCommand = 22, + AbrStreamOnly = 23, } /// List of active A/B tests that are run when none is manually specified @@ -49,6 +50,7 @@ const TESTS_TO_RUN: &[ABTest] = &[ ABTest::MusicAlbumGroupsReordered, ABTest::AlbumRecommends, ABTest::CommandExecutorCommand, + ABTest::AbrStreamOnly, ]; #[derive(Debug, Serialize, Deserialize)] @@ -126,6 +128,7 @@ pub async fn run_test( } ABTest::AlbumRecommends => album_recommends(&query).await, ABTest::CommandExecutorCommand => command_executor_command(&query).await, + ABTest::AbrStreamOnly => abr_stream_only(&query).await, } .unwrap(); pb.inc(1); @@ -478,3 +481,9 @@ pub async fn command_executor_command(rp: &RustyPipeQuery) -> Result { .await?; Ok(res.contains("\"commandExecutorCommand\"")) } + +pub async fn abr_stream_only(rp: &RustyPipeQuery) -> Result { + let id = "pxY4OXVyMe4"; + let res = rp.player_from_client(id, ClientType::Desktop).await?; + Ok(res.video_streams.iter().all(|s| s.url.is_none())) +} diff --git a/downloader/Cargo.toml b/downloader/Cargo.toml index dba74ce..d5d1613 100644 --- a/downloader/Cargo.toml +++ b/downloader/Cargo.toml @@ -34,6 +34,7 @@ audiotag = ["dep:lofty", "dep:image", "dep:smartcrop2"] [dependencies] rustypipe.workspace = true +rustypipe-abr-proto.workspace = true once_cell.workspace = true regex.workspace = true thiserror.workspace = true @@ -52,10 +53,16 @@ image = { version = "0.25.0", optional = true, default-features = false, feature "webp", ] } smartcrop2 = { version = "0.4.0", optional = true } +data-encoding.workspace = true +protobuf.workspace = true +bytes = "1.0.0" +byteorder = "1.0.0" +async-stream = "0.3.6" [dev-dependencies] path_macro.workspace = true rstest.workspace = true +tracing-test.workspace = true serde_json.workspace = true temp_testdir = "0.2.3" diff --git a/downloader/src/abr.rs b/downloader/src/abr.rs new file mode 100644 index 0000000..350d9b0 --- /dev/null +++ b/downloader/src/abr.rs @@ -0,0 +1,676 @@ +#![allow(unused)] + +use std::collections::{HashMap, HashSet}; + +use bytes::Bytes; +use data_encoding::BASE64URL; +use protobuf::{Message, MessageField}; +use reqwest::Client; +use rustypipe::model::{AudioStream, VideoStream}; + +pub use rustypipe_abr_proto::client_abr_state::ClientAbrState; +use rustypipe_abr_proto::{ + buffered_range::BufferedRange, + common::FormatId, + format_initialization_metadata::FormatInitializationMetadata, + media_header::MediaHeader, + next_request_policy::NextRequestPolicy, + playback_cookie::PlaybackCookie, + sabr_error::SabrError, + sabr_redirect::SabrRedirect, + stream_protection_status::StreamProtectionStatus, + streamer_context::{streamer_context::ClientInfo, StreamerContext}, + time_range::TimeRange, + video_playback_abr_request::VideoPlaybackAbrRequest, +}; + +use crate::abr_model::PartType; +use crate::error::AbrError; + +pub struct AbrStream { + http: Client, + initial_url: String, + ustreamer_config: Vec, + po_token: Option>, +} + +#[derive(Debug)] +pub struct StreamingState { + abr_streaming_url: String, + abr_state: ClientAbrState, + playback_cookie: Option, + backoff_time_ms: i32, + formats_by_key: HashMap, + header_id_to_format_key_map: HashMap, + previous_sequences: HashMap>, +} + +struct InitializedFormat { + format_id: FormatId, + duration_ms: Option, + mime_type: Option, + sequence_count: Option, + sequence_list: Vec, + media_chunks: Vec, + state: BufferedRange, +} + +#[derive(Debug)] +struct Sequence { + itag: Option, + format_id: FormatId, + is_init_segment: bool, + duration_ms: Option, + start_ms: Option, + start_data_range: Option, + sequence_number: Option, + content_length: Option, + time_range: Option, +} + +struct UmpPart<'a> { + part_type: PartType, + size: u64, + data: &'a [u8], +} + +impl std::fmt::Debug for InitializedFormat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InitializedFormat") + .field("format_id", &self.format_id) + .field("duration_ms", &self.duration_ms) + .field("mime_type", &self.mime_type) + .field("sequence_count", &self.sequence_count) + .field("sequence_list", &self.sequence_list) + .field("media_chunks", &self.media_chunks.len()) + .field("state", &self.state) + .finish() + } +} + +impl std::fmt::Debug for UmpPart<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("UmpPart") + .field("part_type", &self.part_type) + .field("size", &self.size) + .field("data", &self.data.len()) + .finish() + } +} + +impl AbrStream { + pub fn new( + url: String, + ustreamer_config: &str, + po_token: Option<&str>, + http: Client, + ) -> Result { + let ustreamer_config = BASE64URL.decode(ustreamer_config.as_bytes()).map_err(|e| { + AbrError::Invalid(format!("could not parse ustreamer_config: {e}").into()) + })?; + let po_token = + match po_token { + Some(pot) => Some(BASE64URL.decode(pot.as_bytes()).map_err(|e| { + AbrError::Invalid(format!("could not parse po_token: {e}").into()) + })?), + None => None, + }; + Ok(Self { + http, + initial_url: url, + ustreamer_config, + po_token, + }) + } + + pub async fn init( + &self, + audio_streams: &[&AudioStream], + video_streams: &[&VideoStream], + mut abr_state: ClientAbrState, + ) -> Result { + if !abr_state.has_last_manual_direction() { + abr_state.set_last_manual_direction(0); + } + if !abr_state.has_time_since_last_manual_format_selection_ms() { + abr_state.set_time_since_last_manual_format_selection_ms(0); + } + if !abr_state.has_player_time_ms() { + abr_state.set_player_time_ms(0); + } + if !abr_state.has_visibility() { + abr_state.set_visibility(0); + } + if !abr_state.has_enabled_track_types_bitfield() { + abr_state.set_enabled_track_types_bitfield(i32::from(video_streams.is_empty())); + } + if let Some(v) = video_streams.first() { + if !abr_state.has_last_manual_selected_resolution() { + abr_state.set_last_manual_selected_resolution(v.height as i32); + } + if !abr_state.has_sticky_resolution() { + abr_state.set_sticky_resolution(v.height as i32); + } + } + + let audio_format_ids = audio_streams + .iter() + .map(|s| FormatId { + itag: Some(s.itag as i32), + last_modified: s.last_modified, + xtags: s.xtags.clone(), + ..Default::default() + }) + .collect::>(); + let video_format_ids = video_streams + .iter() + .map(|s| FormatId { + itag: Some(s.itag as i32), + last_modified: s.last_modified, + xtags: s.xtags.clone(), + ..Default::default() + }) + .collect::>(); + let mut state = StreamingState::new(self.initial_url.to_owned(), abr_state); + let mut ri = 0; + + loop { + let data = self + .fetch_media(audio_format_ids.clone(), video_format_ids.clone(), &state) + .await?; + tracing::debug!("request #{ri} fetched {} bytes", data.len()); + + let ump_parts = Self::parse_ump(&data); + if state.process_ump_parts(&ump_parts)? { + break; + } + ri += 1; + } + + Ok(state) + } + + async fn fetch_media( + &self, + audio_format_ids: Vec, + video_format_ids: Vec, + state: &StreamingState, + ) -> Result { + let body = VideoPlaybackAbrRequest { + client_abr_state: MessageField::some(state.abr_state.clone()), + selected_format_ids: state + .formats_by_key + .values() + .map(|f| f.format_id.clone()) + .collect(), + buffered_ranges: state + .formats_by_key + .values() + .map(|f| f.state.clone()) + .collect(), + // player_time_ms: todo!(), + video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), + selected_audio_format_ids: audio_format_ids, + selected_video_format_ids: video_format_ids, + streamer_context: MessageField::some(StreamerContext { + client_info: MessageField::some(ClientInfo { + client_name: Some(1), + client_version: Some("2.20250314.01.00".to_owned()), + ..Default::default() + }), + po_token: self.po_token.clone(), + playback_cookie: state + .playback_cookie + .as_ref() + .and_then(|c| c.write_to_bytes().ok()), + ..Default::default() + }), + ..Default::default() + }; + + let res = self + .http + .post(&state.abr_streaming_url) + .body(body.write_to_bytes()?) + .send() + .await? + .error_for_status()?; + + // let dstream = res.bytes_stream(); + let data = res.bytes().await?; + tracing::debug!("got {} bytes", data.len()); + + Ok(data) + } + + fn parse_ump(data: &[u8]) -> Vec> { + let mut parts = Vec::new(); + let mut offset = 0; + while offset < data.len() { + let (part_type, new_offset) = Self::read_varint(&data[offset..]); + if new_offset == 0 { + break; + } + offset += new_offset; + let (part_size, new_offset) = Self::read_varint(&data[offset..]); + if new_offset == 0 { + break; + } + offset += new_offset; + + let data_offset = offset + part_size as usize; + let part_data = &data[offset..data_offset.min(data.len())]; + offset = data_offset; + + parts.push(UmpPart { + part_type: part_type.into(), + size: part_size, + data: part_data, + }); + } + parts + } + + fn read_varint(data: &[u8]) -> (u64, usize) { + /* + fn varint_size(byte: u8) -> u8 { + let mut lo = 0; + for i in (4u8..8).rev() { + if byte & (1 << i) == 0 { + break; + } else { + lo += 1; + } + } + return (lo + 1).min(5); + } + + if data.is_empty() { + return (0, 0); + } + + let prefix = data[0]; + let size = varint_size(prefix); + + let mut result = 0u64; + let mut shift = 0; + + if size != 5 { + shift = 8 - size; + let mask = (1 << shift) - 1; + result |= u64::from(prefix) & mask; + } + + let total_size = usize::from(size) + 1; + for byte in &data[1..total_size] { + result |= u64::from(*byte) << shift; + shift += 8; + } + + (result, total_size) + */ + + // Determine the length of the val + + if data.is_empty() { + return (0, 0); + } + + let fb = data[0]; + let byte_length = if fb < 128 { + 1 + } else if fb < 192 { + 2 + } else if fb < 224 { + 3 + } else if fb < 240 { + 4 + } else { + 5 + }; + + if data.len() < byte_length { + return (0, 0); + } + + let n = match byte_length { + 1 => data[0].into(), + 2 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + (b1 & 0x3f) + 64 * b2 + } + 3 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + let b3 = u64::from(data[2]); + (b1 & 0x1f) + 32 * (b2 + 256 * b3) + } + 4 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + let b3 = u64::from(data[2]); + let b4 = u64::from(data[3]); + (b1 & 0x0f) + 16 * (b2 + 256 * (b3 + 256 * b4)) + } + _ => u32::from_be_bytes([data[1], data[2], data[3], data[4]]).into(), + }; + (n, byte_length) + } +} + +impl StreamingState { + fn new(url: String, abr_state: ClientAbrState) -> Self { + Self { + abr_streaming_url: url, + abr_state, + playback_cookie: None, + backoff_time_ms: 0, + formats_by_key: HashMap::new(), + header_id_to_format_key_map: HashMap::new(), + previous_sequences: HashMap::new(), + } + } + + fn process_ump_parts(&mut self, ump_parts: &[UmpPart]) -> Result { + for f in self.formats_by_key.values_mut() { + f.sequence_list.clear(); + } + + for part in ump_parts { + match part.part_type { + PartType::MEDIA_HEADER => { + self.process_media_header(part.data)?; + } + PartType::MEDIA => { + self.process_media_data(part.data)?; + } + PartType::MEDIA_END => { + self.process_media_end(part.data); + } + PartType::NEXT_REQUEST_POLICY => { + self.process_next_request_policy(part.data)?; + } + PartType::FORMAT_INITIALIZATION_METADATA => { + self.process_format_initialization(part.data)?; + } + PartType::SABR_ERROR => { + return Err(AbrError::Sabr(SabrError::parse_from_bytes(part.data)?)); + } + PartType::SABR_REDIRECT => { + self.process_sabr_redirect(part.data)?; + } + PartType::STREAM_PROTECTION_STATUS => { + let prot = StreamProtectionStatus::parse_from_bytes(part.data)?; + match prot.status() { + 1 => tracing::debug!("[StreamProtectionStatus]: Good"), + 2 => tracing::warn!("[StreamProtectionStatus]: Attestation pending"), + 3 => return Err(AbrError::Attestation), + _ => {} + } + } + _ => {} + } + } + + let main_format = self + .formats_by_key + .values() + .find(|fmt| { + fmt.mime_type + .as_deref() + .map(|t| t.contains("video")) + .unwrap_or_default() + }) + .or(self.formats_by_key.values().next()); + if let Some(main_format) = main_format { + self.abr_state.set_player_time_ms( + self.abr_state.player_time_ms() + + main_format.sequence_list.iter().fold(0, |acc, seq| { + acc + i64::from(seq.duration_ms.unwrap_or_default()) + }), + ); + + tracing::debug!( + "sequence_count={}, last={}", + main_format.sequence_count.unwrap_or_default(), + main_format + .sequence_list + .last() + .and_then(|x| x.sequence_number) + .unwrap_or_default() + ); + + let is_last = main_format + .sequence_count + .zip(main_format.sequence_list.last()) + .map(|(sc, last)| last.sequence_number == Some(sc.into())) + .unwrap_or_default(); + Ok(is_last) + } else { + Ok(true) + } + } + + fn process_media_header(&mut self, data: &[u8]) -> Result<(), AbrError> { + let mh = MediaHeader::parse_from_bytes(data)?; + + let format_id = mh + .format_id + .as_ref() + .ok_or(AbrError::Invalid("media header: no format_id".into()))?; + let header_id = mh + .header_id + .and_then(|hid| u8::try_from(hid).ok()) + .ok_or(AbrError::Invalid("media header: no header_id".into()))?; + + let format_key = get_format_key(format_id); + + if !self.formats_by_key.contains_key(&format_key) { + self.formats_by_key + .insert(format_key.to_owned(), InitializedFormat::try_from(&mh)?); + } + let current_format = self.formats_by_key.get_mut(&format_key).unwrap(); + + // This is a hacky workaround to prevent duplicate sequences from being added. This should be fixed in the future + // (preferably by figuring out how to make the server not send duplicates). + if let Some(sequence_number) = mh.sequence_number { + let pseq = self + .previous_sequences + .entry(format_key.to_owned()) + .or_default(); + if !pseq.insert(sequence_number) { + tracing::warn!("duplicate sequence {sequence_number}"); + return Ok(()); + } + } + + // Save the header's ID so we can identify its stream data later. + self.header_id_to_format_key_map + .entry(header_id) + .or_insert(format_key); + + if current_format + .sequence_list + .iter() + .all(|x| x.sequence_number != Some(mh.sequence_number())) + { + current_format.sequence_list.push(Sequence { + itag: mh.itag, + format_id: format_id.clone(), + is_init_segment: mh.is_init_seg(), + duration_ms: mh.duration_ms, + start_ms: mh.start_ms, + start_data_range: mh.start_data_range, + sequence_number: mh.sequence_number, + content_length: mh.content_length, + time_range: mh.time_range.as_ref().cloned(), + }); + + if mh.has_sequence_number() { + current_format.state.set_duration_ms( + current_format.state.duration_ms() + i64::from(mh.duration_ms()), + ); + current_format + .state + .set_end_segment_index(current_format.state.end_segment_index() + 1); + } + } + + Ok(()) + } + + fn process_media_data(&mut self, data: &[u8]) -> Result<(), AbrError> { + let header_id = data[0]; + let format_key = self + .header_id_to_format_key_map + .get(&header_id) + .ok_or_else(|| { + AbrError::Invalid(format!("media: unknown header id {header_id}").into()) + })?; + let current_format = self + .formats_by_key + .get_mut(format_key) + .ok_or(AbrError::Invalid("no current format".into()))?; + + current_format.media_chunks.extend_from_slice(&data[1..]); + Ok(()) + } + + fn process_media_end(&mut self, data: &[u8]) { + let header_id = data[0]; + self.header_id_to_format_key_map.remove(&header_id); + } + + fn process_next_request_policy(&mut self, data: &[u8]) -> Result<(), AbrError> { + let mut policy = NextRequestPolicy::parse_from_bytes(data)?; + self.playback_cookie = policy.playback_cookie.take(); + self.backoff_time_ms = policy.backoff_time_ms(); + Ok(()) + } + + fn process_format_initialization(&mut self, data: &[u8]) -> Result<(), AbrError> { + let init = FormatInitializationMetadata::parse_from_bytes(data)?; + let format = InitializedFormat::try_from(init)?; + let format_key = get_format_key(&format.format_id); + self.formats_by_key.insert(format_key, format); + Ok(()) + } + + fn process_sabr_redirect(&mut self, data: &[u8]) -> Result<(), AbrError> { + let redir = SabrRedirect::parse_from_bytes(data)?; + self.abr_streaming_url = redir + .url + .ok_or(AbrError::Invalid("sabr redirect: no URL".into()))?; + Ok(()) + } +} + +fn get_format_key(format_id: &FormatId) -> String { + format!("{};{};", format_id.itag(), format_id.last_modified()) +} + +impl TryFrom<&MediaHeader> for InitializedFormat { + type Error = AbrError; + + fn try_from(value: &MediaHeader) -> Result { + let format_id = value + .format_id + .as_ref() + .ok_or(AbrError::Invalid("media header: no format_id".into()))?; + Ok(InitializedFormat { + format_id: format_id.clone(), + duration_ms: value.duration_ms, + mime_type: None, + sequence_count: None, + sequence_list: Vec::new(), + media_chunks: Vec::new(), + state: BufferedRange { + format_id: MessageField::some(format_id.clone()), + start_time_ms: Some(0), + duration_ms: Some(0), + start_segment_index: Some(1), + end_segment_index: Some(0), + ..Default::default() + }, + }) + } +} + +impl TryFrom for InitializedFormat { + type Error = AbrError; + + fn try_from(value: FormatInitializationMetadata) -> Result { + let format_id = *value.format_id.0.ok_or(AbrError::Invalid( + "format initialization: no format_id".into(), + ))?; + Ok(InitializedFormat { + format_id: format_id.clone(), + duration_ms: value.duration_ms, + mime_type: value.mime_type.clone(), + sequence_count: value.sequence_count, + sequence_list: Vec::new(), + media_chunks: Vec::new(), + state: BufferedRange { + format_id: MessageField::some(format_id), + start_time_ms: Some(0), + duration_ms: Some(0), + start_segment_index: Some(1), + end_segment_index: Some(0), + ..Default::default() + }, + }) + } +} + +#[cfg(test)] +mod tests { + use rustypipe::{ + client::RustyPipe, + model::{AudioCodec, VideoFormat}, + param::StreamFilter, + }; + + use crate::abr::{AbrStream, StreamingState}; + + #[tokio::test] + #[tracing_test::traced_test] + async fn experiment() { + let rp = RustyPipe::new(); + let player = rp.query().player("UMm7Pq0BdRg").await.unwrap(); + let stream_filter = StreamFilter::new() + .allow_abr_only() + .video_max_res(360) + .video_formats([VideoFormat::Webm]) + .audio_codecs([AudioCodec::Opus]); + let (video, audio) = player.select_video_audio_stream(&stream_filter); + let _video = video.unwrap(); + let audio = audio.unwrap(); + + let http = reqwest::Client::new(); + let abr = AbrStream::new( + player.abr_streaming_url.clone().unwrap(), + player.abr_ustreamer_config.as_deref().unwrap(), + player.po_token.as_deref(), + http, + ) + .unwrap(); + let state = abr.init(&[audio], &[], Default::default()).await.unwrap(); + dbg!(&state); + + // let f = state.formats_by_key.values().next().unwrap(); + // std::fs::write("test.webm", &f.media_chunks); + } + + #[test] + #[tracing_test::traced_test] + fn parse_ump() { + let data = std::fs::read("abr.bin").unwrap(); + let ump_parts = AbrStream::parse_ump(&data); + dbg!(&ump_parts); + + let mut state = StreamingState::new(Default::default(), Default::default()); + assert!(!state.process_ump_parts(&ump_parts).unwrap()); + dbg!(&state); + } +} diff --git a/downloader/src/abr2.rs b/downloader/src/abr2.rs new file mode 100644 index 0000000..a6ebfef --- /dev/null +++ b/downloader/src/abr2.rs @@ -0,0 +1,799 @@ +#![allow(unused)] + +use std::{ + collections::{HashMap, HashSet}, + marker::PhantomData, + pin::Pin, + task::{ready, Poll}, +}; + +use async_stream::try_stream; +use bytes::{Buf, Bytes}; +use data_encoding::BASE64URL; +use futures_util::{stream::BoxStream, FutureExt, Stream, StreamExt, TryStreamExt}; +use protobuf::{Message, MessageField}; +use reqwest::Client; +use rustypipe::model::{AudioStream, VideoStream}; +use rustypipe_abr_proto::{ + buffered_range::BufferedRange, + client_abr_state::ClientAbrState, + common::FormatId, + format_initialization_metadata::FormatInitializationMetadata, + media_header::MediaHeader, + next_request_policy::NextRequestPolicy, + playback_cookie::PlaybackCookie, + sabr_error::SabrError, + sabr_redirect::SabrRedirect, + stream_protection_status::StreamProtectionStatus, + streamer_context::{streamer_context::ClientInfo, StreamerContext}, + time_range::TimeRange, + video_playback_abr_request::VideoPlaybackAbrRequest, +}; + +use crate::{abr_model::PartType, error::AbrError, util::BytesBuffer}; + +pub struct AbrStream { + http: Client, + url: String, + ustreamer_config: Vec, + po_token: Option>, + abr_state: ClientAbrState, + audio_format_ids: Vec, + video_format_ids: Vec, + playback_cookie: Option, + backoff_time_ms: i32, + formats_by_key: HashMap, + header_id_to_format_key_map: HashMap, + previous_sequences: HashMap>, + // http_stream: Option>>, + buffer: BytesBuffer, + last_header: Option, +} + +#[derive(Default, Clone)] +pub struct AbrStreamOptions<'a> { + http: Client, + url: String, + ustreamer_config: &'a str, + po_token: Option<&'a str>, + audio_streams: &'a [&'a AudioStream], + video_streams: &'a [&'a VideoStream], + abr_state: ClientAbrState, +} + +#[derive(Debug, Clone)] +pub struct AbrStreamItem { + format: FormatInfo, + data: Bytes, +} + +#[derive(Debug, Clone)] +pub struct FormatInfo { + itag: i32, + last_modified: u64, + xtags: Option, + mime_type: Option, +} + +#[derive(Debug)] +struct InitializedFormat { + format_id: FormatId, + duration_ms: Option, + mime_type: Option, + sequence_count: Option, + sequence_list: Vec, + state: BufferedRange, +} + +#[derive(Debug)] +struct Sequence { + itag: Option, + format_id: FormatId, + is_init_segment: bool, + duration_ms: Option, + start_ms: Option, + start_data_range: Option, + sequence_number: Option, + content_length: Option, + time_range: Option, +} + +#[derive(Debug, Clone)] +struct UmpHeader { + part_type: PartType, + size: u64, + header_id: Option, +} + +impl From<&InitializedFormat> for FormatInfo { + fn from(value: &InitializedFormat) -> Self { + Self { + itag: value.format_id.itag(), + last_modified: value.format_id.last_modified(), + xtags: value.format_id.xtags.clone(), + mime_type: value.mime_type.clone(), + } + } +} + +impl AbrStream { + pub fn new(options: AbrStreamOptions) -> Result { + let ustreamer_config = BASE64URL + .decode(options.ustreamer_config.as_bytes()) + .map_err(|e| { + AbrError::Invalid(format!("could not parse ustreamer_config: {e}").into()) + })?; + let po_token = + match options.po_token { + Some(pot) => Some(BASE64URL.decode(pot.as_bytes()).map_err(|e| { + AbrError::Invalid(format!("could not parse po_token: {e}").into()) + })?), + None => None, + }; + + let mut abr_state = options.abr_state; + if !abr_state.has_last_manual_direction() { + abr_state.set_last_manual_direction(0); + } + if !abr_state.has_time_since_last_manual_format_selection_ms() { + abr_state.set_time_since_last_manual_format_selection_ms(0); + } + if !abr_state.has_player_time_ms() { + abr_state.set_player_time_ms(0); + } + if !abr_state.has_visibility() { + abr_state.set_visibility(0); + } + if !abr_state.has_enabled_track_types_bitfield() { + abr_state.set_enabled_track_types_bitfield(i32::from(options.video_streams.is_empty())); + } + if let Some(v) = options.video_streams.first() { + if !abr_state.has_last_manual_selected_resolution() { + abr_state.set_last_manual_selected_resolution(v.height as i32); + } + if !abr_state.has_sticky_resolution() { + abr_state.set_sticky_resolution(v.height as i32); + } + } + + let audio_format_ids = options + .audio_streams + .iter() + .map(|s| FormatId { + itag: Some(s.itag as i32), + last_modified: s.last_modified, + xtags: s.xtags.clone(), + ..Default::default() + }) + .collect::>(); + let video_format_ids = options + .video_streams + .iter() + .map(|s| FormatId { + itag: Some(s.itag as i32), + last_modified: s.last_modified, + xtags: s.xtags.clone(), + ..Default::default() + }) + .collect::>(); + + Ok(Self { + http: options.http, + url: options.url, + ustreamer_config, + po_token, + abr_state, + audio_format_ids, + video_format_ids, + playback_cookie: None, + backoff_time_ms: 0, + formats_by_key: HashMap::new(), + header_id_to_format_key_map: HashMap::new(), + previous_sequences: HashMap::new(), + buffer: BytesBuffer::new(), + last_header: None, + }) + } + + fn read_varint(&mut self, offset: usize) -> (u64, usize) { + // Determine the length of the val + let buffer_len = self.buffer.remaining().saturating_sub(offset); + if buffer_len == 0 { + return (0, 0); + } + + let fb = self.buffer[offset]; + let byte_length = if fb < 128 { + 1 + } else if fb < 192 { + 2 + } else if fb < 224 { + 3 + } else if fb < 240 { + 4 + } else { + 5 + }; + + if buffer_len < byte_length { + return (0, 0); + } + + let n = match byte_length { + 1 => self.buffer[offset].into(), + 2 => { + let b1 = u64::from(self.buffer[offset]); + let b2 = u64::from(self.buffer[offset + 1]); + (b1 & 0x3f) + 64 * b2 + } + 3 => { + let b1 = u64::from(self.buffer[offset]); + let b2 = u64::from(self.buffer[offset + 1]); + let b3 = u64::from(self.buffer[offset + 2]); + (b1 & 0x1f) + 32 * (b2 + 256 * b3) + } + 4 => { + let b1 = u64::from(self.buffer[offset]); + let b2 = u64::from(self.buffer[offset + 1]); + let b3 = u64::from(self.buffer[offset + 2]); + let b4 = u64::from(self.buffer[offset + 3]); + (b1 & 0x0f) + 16 * (b2 + 256 * (b3 + 256 * b4)) + } + _ => u32::from_be_bytes([ + self.buffer[offset + 1], + self.buffer[offset + 2], + self.buffer[offset + 3], + self.buffer[offset + 4], + ]) + .into(), + }; + (n, offset + byte_length) + } + + fn parse_ump_header(&mut self) -> Option { + let (part_type, o1) = self.read_varint(0); + if o1 == 0 { + return None; + } + let (part_size, o2) = self.read_varint(o1); + if o2 == 0 { + return None; + } + self.buffer.advance(o2); + + Some(UmpHeader { + part_type: part_type.into(), + size: part_size, + header_id: None, + }) + } + + fn clear_sequence_list(&mut self) { + for f in self.formats_by_key.values_mut() { + f.sequence_list.clear(); + } + } + + fn process_ump_part(&mut self) -> Result<(Option, bool), AbrError> { + if let Some(last_header) = self.last_header.clone() { + let hsize = last_header.size as usize; + if last_header.part_type == PartType::MEDIA { + // Media data may be processed if the part is only partially downloaded + self.process_media_data().map(|x| (x, true)) + } else if self.buffer.remaining() < hsize { + // Wait for the entire part to be downloaded + Ok((None, true)) + } else { + let part_data = self.buffer.copy_to_bytes(hsize); + match last_header.part_type { + PartType::MEDIA_HEADER => self.process_media_header(&part_data)?, + PartType::MEDIA_END => self.process_media_end(&part_data), + PartType::NEXT_REQUEST_POLICY => { + self.process_next_request_policy(&part_data)? + } + PartType::FORMAT_INITIALIZATION_METADATA => { + self.process_format_initialization(&part_data)? + } + PartType::SABR_ERROR => { + return Err(AbrError::Sabr(SabrError::parse_from_bytes(&part_data)?)); + } + PartType::SABR_REDIRECT => self.process_sabr_redirect(&part_data)?, + PartType::STREAM_PROTECTION_STATUS => { + let prot = StreamProtectionStatus::parse_from_bytes(&part_data)?; + match prot.status() { + 1 => tracing::debug!("[StreamProtectionStatus]: Good"), + 2 => tracing::warn!("[StreamProtectionStatus]: Attestation pending"), + 3 => return Err(AbrError::Attestation), + _ => {} + } + } + _ => {} + }; + self.last_header = None; + Ok((None, false)) + } + } else { + Ok((None, true)) + } + } + + fn process_media_header(&mut self, data: &[u8]) -> Result<(), AbrError> { + let mh = MediaHeader::parse_from_bytes(data)?; + + let format_id = mh + .format_id + .as_ref() + .ok_or(AbrError::Invalid("media header: no format_id".into()))?; + let header_id = mh + .header_id + .and_then(|hid| u8::try_from(hid).ok()) + .ok_or(AbrError::Invalid("media header: no header_id".into()))?; + + let format_key = get_format_key(format_id); + + if !self.formats_by_key.contains_key(&format_key) { + self.formats_by_key + .insert(format_key.to_owned(), InitializedFormat::try_from(&mh)?); + } + let current_format = self.formats_by_key.get_mut(&format_key).unwrap(); + + // This is a hacky workaround to prevent duplicate sequences from being added. This should be fixed in the future + // (preferably by figuring out how to make the server not send duplicates). + if let Some(sequence_number) = mh.sequence_number { + let pseq = self + .previous_sequences + .entry(format_key.to_owned()) + .or_default(); + if !pseq.insert(sequence_number) { + tracing::warn!("duplicate sequence {sequence_number}"); + return Ok(()); + } + } + + // Save the header's ID so we can identify its stream data later. + self.header_id_to_format_key_map + .entry(header_id) + .or_insert(format_key); + + if current_format + .sequence_list + .iter() + .all(|x| x.sequence_number != Some(mh.sequence_number())) + { + current_format.sequence_list.push(Sequence { + itag: mh.itag, + format_id: format_id.clone(), + is_init_segment: mh.is_init_seg(), + duration_ms: mh.duration_ms, + start_ms: mh.start_ms, + start_data_range: mh.start_data_range, + sequence_number: mh.sequence_number, + content_length: mh.content_length, + time_range: mh.time_range.as_ref().cloned(), + }); + + if mh.has_sequence_number() { + current_format.state.set_duration_ms( + current_format.state.duration_ms() + i64::from(mh.duration_ms()), + ); + current_format + .state + .set_end_segment_index(current_format.state.end_segment_index() + 1); + } + } + + Ok(()) + } + + fn process_media_data(&mut self) -> Result, AbrError> { + if let Some(last_header) = &mut self.last_header { + if let Some(header_id) = last_header.header_id.or_else(|| { + let x = self.buffer.try_get_u8().ok(); + if x.is_some() { + last_header.header_id = x; + last_header.size -= 1; + } + x + }) { + let to_copy = self.buffer.remaining().min(last_header.size as usize); + if to_copy == 0 { + return Ok(None); + } + let format_key = self + .header_id_to_format_key_map + .get(&header_id) + .ok_or_else(|| { + AbrError::Invalid(format!("media: unknown header id {header_id}").into()) + })?; + let current_format = self + .formats_by_key + .get(format_key) + .ok_or(AbrError::Invalid("no current format".into()))?; + let format = FormatInfo::from(current_format); + let data = self.buffer.copy_to_bytes(to_copy); + last_header.size -= data.len() as u64; + if last_header.size == 0 { + self.last_header = None; + } + Ok(Some(AbrStreamItem { format, data })) + } else { + Ok(None) + } + } else { + Ok(None) + } + } + + fn process_media_end(&mut self, data: &[u8]) { + let header_id = data[0]; + self.header_id_to_format_key_map.remove(&header_id); + } + + fn process_next_request_policy(&mut self, data: &[u8]) -> Result<(), AbrError> { + let mut policy = NextRequestPolicy::parse_from_bytes(data)?; + self.playback_cookie = policy.playback_cookie.take(); + self.backoff_time_ms = policy.backoff_time_ms(); + Ok(()) + } + + fn process_format_initialization(&mut self, data: &[u8]) -> Result<(), AbrError> { + let init = FormatInitializationMetadata::parse_from_bytes(data)?; + let format = InitializedFormat::try_from(init)?; + let format_key = get_format_key(&format.format_id); + self.formats_by_key.insert(format_key, format); + Ok(()) + } + + fn process_sabr_redirect(&mut self, data: &[u8]) -> Result<(), AbrError> { + let redir = SabrRedirect::parse_from_bytes(data)?; + self.url = redir + .url + .ok_or(AbrError::Invalid("sabr redirect: no URL".into()))?; + Ok(()) + } + + fn main_format(&self) -> Option<&InitializedFormat> { + self.formats_by_key + .values() + .find(|fmt| { + fmt.mime_type + .as_deref() + .map(|t| t.contains("video")) + .unwrap_or_default() + }) + .or(self.formats_by_key.values().next()) + } + + pub fn stream(mut self) -> impl Stream> { + try_stream! { + let mut ri = 1; + loop { + let body = VideoPlaybackAbrRequest { + client_abr_state: MessageField::some(self.abr_state.clone()), + selected_format_ids: self + .formats_by_key + .values() + .map(|f| f.format_id.clone()) + .collect(), + buffered_ranges: self + .formats_by_key + .values() + .map(|f| f.state.clone()) + .collect(), + video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), + selected_audio_format_ids: self.audio_format_ids.clone(), + selected_video_format_ids: self.video_format_ids.clone(), + streamer_context: MessageField::some(StreamerContext { + client_info: MessageField::some(ClientInfo { + client_name: Some(1), + client_version: Some("2.20250314.01.00".to_owned()), + ..Default::default() + }), + po_token: self.po_token.clone(), + playback_cookie: self + .playback_cookie + .as_ref() + .and_then(|c| c.write_to_bytes().ok()), + ..Default::default() + }), + ..Default::default() + }; + + let resp = self + .http + .post(&self.url) + .body(body.write_to_bytes()?) + .send() + .await? + .error_for_status()?; + let mut data_stream = resp.bytes_stream(); + let mut page_len = 0; + self.clear_sequence_list(); + + while let Some(chunk) = data_stream.next().await { + let chunk = chunk?; + let clen = chunk.len(); + page_len += clen; + tracing::debug!("chunk {clen}"); + self.buffer.push(chunk); + + loop { + if self.last_header.is_none() { + self.last_header = self.parse_ump_header(); + } + tracing::debug!("loop {:?}", self.last_header); + if self.last_header.is_none() { + break; + } + let (x, y) = self.process_ump_part()?; + if let Some(item) = x { + yield item; + } + if y { + break; + } + } + } + tracing::debug!("request #{ri} fetched {page_len} bytes"); + + let main_format = self.main_format().ok_or(AbrError::Invalid("no main format".into()))?; + let player_time = self.abr_state.player_time_ms() + + main_format.sequence_list.iter().fold(0, |acc, seq| { + acc + i64::from(seq.duration_ms.unwrap_or_default()) + }); + let is_last = main_format + .sequence_count + .zip(main_format.sequence_list.last()) + .map(|(sc, last)| last.sequence_number == Some(sc.into())) + .unwrap_or_default(); + tracing::debug!("player time: {player_time}; sequence_count={}, last={}", main_format.sequence_count.unwrap_or_default(), main_format + .sequence_list + .last() + .and_then(|x| x.sequence_number).unwrap_or_default()); + self.abr_state.set_player_time_ms(player_time); + if is_last { + break; + } + + if self.backoff_time_ms > 0 { + tracing::debug!("backoff: {} ms", self.backoff_time_ms); + tokio::time::sleep(std::time::Duration::from_millis( + self.backoff_time_ms.try_into().unwrap_or_default(), + )).await; + self.backoff_time_ms = 0; + } + + ri += 1; + } + } + } +} + +/* +impl<'a> Stream for AbrStream { + type Item = Result; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + loop { + if self.http_stream.is_none() { + let body = VideoPlaybackAbrRequest { + client_abr_state: MessageField::some(self.abr_state.clone()), + selected_format_ids: self + .formats_by_key + .values() + .map(|f| f.format_id.clone()) + .collect(), + buffered_ranges: self + .formats_by_key + .values() + .map(|f| f.state.clone()) + .collect(), + video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), + selected_audio_format_ids: self.audio_format_ids.clone(), + selected_video_format_ids: self.video_format_ids.clone(), + streamer_context: MessageField::some(StreamerContext { + client_info: MessageField::some(ClientInfo { + client_name: Some(1), + client_version: Some("2.20250314.01.00".to_owned()), + ..Default::default() + }), + po_token: self.po_token.clone(), + playback_cookie: self + .playback_cookie + .as_ref() + .and_then(|c| c.write_to_bytes().ok()), + ..Default::default() + }), + ..Default::default() + }; + + match ready!(self + .http + .post(&self.url) + .body(body.write_to_bytes()?) + .send() + .poll_unpin(cx)) + { + Ok(resp) => { + let resp = resp.error_for_status()?; + let data_stream = resp.bytes_stream(); + self.http_stream = Some(Box::pin(data_stream)); + self.buffer = BytesBuffer::new() + } + Err(e) => return Poll::Ready(Some(Err(e.into()))), + } + } + + while let Some(http_stream) = &mut self.http_stream { + match ready!(http_stream.poll_next_unpin(cx)) { + Some(chunk) => { + let chunk = chunk?; + let clen = chunk.len(); + self.buffer.push(chunk); + if self.buffer.pos() == 0 { + self.last_header = self.parse_ump_header(); + } + if let Some(item) = self.process_ump_part()? { + return Poll::Ready(Some(Ok(item))); + } + } + None => { + self.http_stream = None; + } + } + } + + ready!( + Box::pin(tokio::time::sleep(std::time::Duration::from_millis( + self.backoff_time_ms.try_into().unwrap_or_default(), + ))) + .poll_unpin(cx) + ); + } + } +} +*/ + +fn read_varint(data: &[u8]) -> (u64, usize) { + // Determine the length of the val + if data.is_empty() { + return (0, 0); + } + + let fb = data[0]; + let byte_length = if fb < 128 { + 1 + } else if fb < 192 { + 2 + } else if fb < 224 { + 3 + } else if fb < 240 { + 4 + } else { + 5 + }; + + if data.len() < byte_length { + return (0, 0); + } + + let n = match byte_length { + 1 => data[0].into(), + 2 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + (b1 & 0x3f) + 64 * b2 + } + 3 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + let b3 = u64::from(data[2]); + (b1 & 0x1f) + 32 * (b2 + 256 * b3) + } + 4 => { + let b1 = u64::from(data[0]); + let b2 = u64::from(data[1]); + let b3 = u64::from(data[2]); + let b4 = u64::from(data[3]); + (b1 & 0x0f) + 16 * (b2 + 256 * (b3 + 256 * b4)) + } + _ => u32::from_be_bytes([data[1], data[2], data[3], data[4]]).into(), + }; + (n, byte_length) +} + +fn get_format_key(format_id: &FormatId) -> String { + format!("{};{};", format_id.itag(), format_id.last_modified()) +} + +impl TryFrom<&MediaHeader> for InitializedFormat { + type Error = AbrError; + + fn try_from(value: &MediaHeader) -> Result { + let format_id = value + .format_id + .as_ref() + .ok_or(AbrError::Invalid("media header: no format_id".into()))?; + Ok(InitializedFormat { + format_id: format_id.clone(), + duration_ms: value.duration_ms, + mime_type: None, + sequence_count: None, + sequence_list: Vec::new(), + state: BufferedRange { + format_id: MessageField::some(format_id.clone()), + start_time_ms: Some(0), + duration_ms: Some(0), + start_segment_index: Some(1), + end_segment_index: Some(0), + ..Default::default() + }, + }) + } +} + +impl TryFrom for InitializedFormat { + type Error = AbrError; + + fn try_from(value: FormatInitializationMetadata) -> Result { + let format_id = *value.format_id.0.ok_or(AbrError::Invalid( + "format initialization: no format_id".into(), + ))?; + Ok(InitializedFormat { + format_id: format_id.clone(), + duration_ms: value.duration_ms, + mime_type: value.mime_type.clone(), + sequence_count: value.sequence_count, + sequence_list: Vec::new(), + state: BufferedRange { + format_id: MessageField::some(format_id), + start_time_ms: Some(0), + duration_ms: Some(0), + start_segment_index: Some(1), + end_segment_index: Some(0), + ..Default::default() + }, + }) + } +} + +#[cfg(test)] +mod tests { + use rustypipe::{ + client::RustyPipe, + model::{AudioCodec, VideoFormat}, + param::StreamFilter, + }; + + use super::*; + + #[tokio::test] + #[tracing_test::traced_test] + async fn experiment() { + let rp = RustyPipe::new(); + let player = rp.query().player("UMm7Pq0BdRg").await.unwrap(); + let stream_filter = StreamFilter::new() + .allow_abr_only() + .video_max_res(360) + .video_formats([VideoFormat::Webm]) + .audio_codecs([AudioCodec::Opus]); + let (video, audio) = player.select_video_audio_stream(&stream_filter); + let _video = video.unwrap(); + let audio = audio.unwrap(); + + let mut abr = AbrStream::new(AbrStreamOptions { + url: player.abr_streaming_url.clone().unwrap(), + ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), + po_token: player.po_token.as_deref(), + audio_streams: &[audio], + video_streams: &[], + ..Default::default() + }) + .unwrap(); + let mut stream = abr.stream().try_collect::>().await.unwrap(); + // dbg!(&stream); + } +} diff --git a/downloader/src/abr_model.rs b/downloader/src/abr_model.rs new file mode 100644 index 0000000..35df60e --- /dev/null +++ b/downloader/src/abr_model.rs @@ -0,0 +1,87 @@ +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PartType { + ONESIE_HEADER = 10, + ONESIE_DATA = 11, + MEDIA_HEADER = 20, + MEDIA = 21, + MEDIA_END = 22, + LIVE_METADATA = 31, + HOSTNAME_CHANGE_HINT = 32, + LIVE_METADATA_PROMISE = 33, + LIVE_METADATA_PROMISE_CANCELLATION = 34, + NEXT_REQUEST_POLICY = 35, + USTREAMER_VIDEO_AND_FORMAT_DATA = 36, + FORMAT_SELECTION_CONFIG = 37, + USTREAMER_SELECTED_MEDIA_STREAM = 38, + FORMAT_INITIALIZATION_METADATA = 42, + SABR_REDIRECT = 43, + SABR_ERROR = 44, + SABR_SEEK = 45, + RELOAD_PLAYER_RESPONSE = 46, + PLAYBACK_START_POLICY = 47, + ALLOWED_CACHED_FORMATS = 48, + START_BW_SAMPLING_HINT = 49, + PAUSE_BW_SAMPLING_HINT = 50, + SELECTABLE_FORMATS = 51, + REQUEST_IDENTIFIER = 52, + REQUEST_CANCELLATION_POLICY = 53, + ONESIE_PREFETCH_REJECTION = 54, + TIMELINE_CONTEXT = 55, + REQUEST_PIPELINING = 56, + SABR_CONTEXT_UPDATE = 57, + STREAM_PROTECTION_STATUS = 58, + SABR_CONTEXT_SENDING_POLICY = 59, + LAWNMOWER_POLICY = 60, + SABR_ACK = 61, + END_OF_TRACK = 62, + CACHE_LOAD_POLICY = 63, + LAWNMOWER_MESSAGING_POLICY = 64, + PREWARM_CONNECTION = 65, + UNKNOWN, +} + +impl From for PartType { + fn from(value: u64) -> Self { + match value { + 10 => Self::ONESIE_HEADER, + 11 => Self::ONESIE_DATA, + 20 => Self::MEDIA_HEADER, + 21 => Self::MEDIA, + 22 => Self::MEDIA_END, + 31 => Self::LIVE_METADATA, + 32 => Self::HOSTNAME_CHANGE_HINT, + 33 => Self::LIVE_METADATA_PROMISE, + 34 => Self::LIVE_METADATA_PROMISE_CANCELLATION, + 35 => Self::NEXT_REQUEST_POLICY, + 36 => Self::USTREAMER_VIDEO_AND_FORMAT_DATA, + 37 => Self::FORMAT_SELECTION_CONFIG, + 38 => Self::USTREAMER_SELECTED_MEDIA_STREAM, + 42 => Self::FORMAT_INITIALIZATION_METADATA, + 43 => Self::SABR_REDIRECT, + 44 => Self::SABR_ERROR, + 45 => Self::SABR_SEEK, + 46 => Self::RELOAD_PLAYER_RESPONSE, + 47 => Self::PLAYBACK_START_POLICY, + 48 => Self::ALLOWED_CACHED_FORMATS, + 49 => Self::START_BW_SAMPLING_HINT, + 50 => Self::PAUSE_BW_SAMPLING_HINT, + 51 => Self::SELECTABLE_FORMATS, + 52 => Self::REQUEST_IDENTIFIER, + 53 => Self::REQUEST_CANCELLATION_POLICY, + 54 => Self::ONESIE_PREFETCH_REJECTION, + 55 => Self::TIMELINE_CONTEXT, + 56 => Self::REQUEST_PIPELINING, + 57 => Self::SABR_CONTEXT_UPDATE, + 58 => Self::STREAM_PROTECTION_STATUS, + 59 => Self::SABR_CONTEXT_SENDING_POLICY, + 60 => Self::LAWNMOWER_POLICY, + 61 => Self::SABR_ACK, + 62 => Self::END_OF_TRACK, + 63 => Self::CACHE_LOAD_POLICY, + 64 => Self::LAWNMOWER_MESSAGING_POLICY, + 65 => Self::PREWARM_CONNECTION, + _ => Self::UNKNOWN, + } + } +} diff --git a/downloader/src/error.rs b/downloader/src/error.rs index d45405d..cf56f25 100644 --- a/downloader/src/error.rs +++ b/downloader/src/error.rs @@ -1,6 +1,7 @@ use std::{borrow::Cow, path::PathBuf}; use rustypipe::client::ClientType; +use rustypipe_abr_proto::sabr_error::SabrError; /// Error from the video downloader #[derive(thiserror::Error, Debug)] @@ -57,3 +58,20 @@ impl From for DownloadError { Self::AudioTag(value.to_string().into()) } } + +#[derive(thiserror::Error, Debug)] +pub enum AbrError { + /// Error encoding/decoding protobuf + #[error("protobuf: {0}")] + Protobuf(#[from] protobuf::Error), + /// Error from the HTTP client + #[error("http error: {0}")] + Http(#[from] reqwest::Error), + /// Received invalid data + #[error("invalid data: {0}")] + Invalid(Cow<'static, str>), + #[error("sabr error {}: {}", .0.code(), .0.type_())] + Sabr(SabrError), + #[error("attestation required")] + Attestation, +} diff --git a/downloader/src/lib.rs b/downloader/src/lib.rs index 2ba3590..b326cfb 100644 --- a/downloader/src/lib.rs +++ b/downloader/src/lib.rs @@ -2,6 +2,9 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_docs, clippy::todo, clippy::dbg_macro)] +mod abr; +mod abr2; +mod abr_model; mod error; mod util; diff --git a/downloader/src/util.rs b/downloader/src/util.rs index 5f87339..9ce600a 100644 --- a/downloader/src/util.rs +++ b/downloader/src/util.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; +use bytes::{Buf, BufMut, Bytes, BytesMut}; use reqwest::Url; use crate::DownloadError; @@ -22,3 +23,147 @@ pub fn url_to_params(url: &str) -> Result<(Url, BTreeMap), Downl Ok((parsed_url, url_params)) } + +#[derive(Default, Debug, Clone)] +pub struct BytesBuffer { + b: Vec, + pos: usize, +} + +impl BytesBuffer { + pub fn new() -> Self { + Self::default() + } + + pub fn push(&mut self, bytes: Bytes) { + if !bytes.is_empty() { + self.b.push(bytes); + } + } + + fn get_ref(&self, index: usize) -> Option<&u8> { + let mut offset = 0; + for p in &self.b { + let pi = index - offset; + if pi < p.len() { + return Some(&p[pi]); + } + offset += p.len(); + } + None + } + + pub fn get(&self, index: usize) -> Option { + self.get_ref(index).cloned() + } + + pub fn pos(&self) -> usize { + self.pos + } +} + +impl std::ops::Index for BytesBuffer { + type Output = u8; + + fn index(&self, index: usize) -> &Self::Output { + self.get_ref(index).expect("index out of range") + } +} + +impl Buf for BytesBuffer { + fn remaining(&self) -> usize { + self.b + .iter() + .map(|b| b.remaining()) + .fold(0, |a, b| a.saturating_add(b)) + } + + fn chunk(&self) -> &[u8] { + for p in &self.b { + if p.has_remaining() { + return p.chunk(); + } + } + &[] + } + + fn advance(&mut self, mut cnt: usize) { + self.pos += cnt; + let mut to_trunc = 0; + for p in &mut self.b { + if cnt == 0 { + break; + } + + let to_adv = cnt.min(p.remaining()); + p.advance(to_adv); + cnt -= to_adv; + + if p.is_empty() { + to_trunc += 1; + } + } + + if to_trunc > 0 { + self.b.drain(0..to_trunc); + } + } + + fn chunks_vectored<'a>(&'a self, dst: &mut [std::io::IoSlice<'a>]) -> usize { + let mut n = 0; + for p in &self.b { + n += p.chunks_vectored(&mut dst[n..]); + } + n + } + + fn copy_to_bytes(&mut self, len: usize) -> bytes::Bytes { + self.pos += len; + if let Some(first) = self.b.first_mut() { + if first.remaining() >= len { + return first.copy_to_bytes(len); + } + } + + let rem = self.remaining(); + if rem < len { + assert!(len <= rem, "`len` greater than remaining"); + } + + let mut ret = BytesMut::with_capacity(len); + ret.put(self.take(len)); + ret.freeze() + } +} + +impl IntoIterator for BytesBuffer { + type Item = u8; + + type IntoIter = bytes::buf::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + bytes::buf::IntoIter::new(self) + } +} + +#[cfg(test)] +mod tests { + use bytes::{Buf, Bytes}; + + use super::BytesBuffer; + + #[test] + fn buffer() { + let mut buf = BytesBuffer::new(); + buf.push(Bytes::from_static(b"hello")); + buf.push(Bytes::from_static(b" ")); + buf.push(Bytes::from_static(b"world")); + + assert_eq!(buf[0], b'h'); + buf.advance(5); + let w1 = buf.copy_to_bytes(6); + assert_eq!(w1.as_ref(), b" world"); + assert!(buf.b.is_empty()); + assert_eq!(buf.pos(), 17); + } +} diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 8742ef6..763622b 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1101,3 +1101,10 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command } } ``` + +## [23] YouTube Desktop only returns ABR streams + +- **Encountered on:** 16.03.2025 +- **Impact:** 🔴 High +- **Endpoint:** player (YT) +- **Status:** Experimental (<1%) diff --git a/src/client/player.rs b/src/client/player.rs index 591d773..9128a54 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -548,6 +548,10 @@ impl MapResponse for response::Player { dash_manifest_url: streaming_data.dash_manifest_url, abr_streaming_url, abr_ustreamer_config, + po_token: ctx + .session_po_token + .as_ref() + .map(|pot| pot.po_token.to_owned()), preview_frames, drm, client_type: ctx.client_type, @@ -777,6 +781,7 @@ impl<'a> StreamsMapper<'a> { bitrate: f.bitrate, average_bitrate: f.average_bitrate.unwrap_or(f.bitrate), size: f.content_length, + last_modified: f.last_modified, index_range: f.index_range, init_range: f.init_range, duration_ms: f.approx_duration_ms, @@ -791,6 +796,7 @@ impl<'a> StreamsMapper<'a> { format, codec: get_video_codec(codecs), mime: f.mime_type, + xtags: map_res.xtags, drm_track_type: f.drm_track_type.map(|t| t.into()), drm_systems: f.drm_families.into_iter().map(|t| t.into()).collect(), }) @@ -821,6 +827,7 @@ impl<'a> StreamsMapper<'a> { format!("no audio content length. itag: {}", f.itag).into(), ) })?, + last_modified: f.last_modified, index_range: f.index_range, init_range: f.init_range, duration_ms: f.approx_duration_ms, @@ -831,7 +838,8 @@ impl<'a> StreamsMapper<'a> { loudness_db: f.loudness_db, track: f .audio_track - .map(|t| self.map_audio_track(t, map_res.xtags)), + .map(|t| self.map_audio_track(t, map_res.xtags.as_deref())), + xtags: map_res.xtags, drm_track_type: f.drm_track_type.map(|t| t.into()), drm_systems: f.drm_families.into_iter().map(|t| t.into()).collect(), }) @@ -840,7 +848,7 @@ impl<'a> StreamsMapper<'a> { fn map_audio_track( &mut self, track: response::player::AudioTrack, - xtags: Option, + xtags: Option<&str>, ) -> AudioTrack { let mut lang = None; let mut track_type = None; diff --git a/src/client/response/player.rs b/src/client/response/player.rs index 9654b21..2cb460f 100644 --- a/src/client/response/player.rs +++ b/src/client/response/player.rs @@ -110,6 +110,10 @@ pub(crate) struct Format { pub format_type: FormatType, pub mime_type: String, + #[serde_as(as = "Option")] + pub last_modified: Option, + #[serde_as(as = "Option")] + pub content_length: Option, pub bitrate: u32, @@ -123,9 +127,6 @@ pub(crate) struct Format { #[serde_as(as = "Option")] pub init_range: Option>, - #[serde_as(as = "Option")] - pub content_length: Option, - #[serde(default)] #[serde_as(deserialize_as = "DefaultOnError")] pub quality: Option, diff --git a/src/model/mod.rs b/src/model/mod.rs index 7f3b277..f97090c 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -151,6 +151,8 @@ pub struct VideoPlayer { pub abr_streaming_url: Option, /// ABR streaming config pub abr_ustreamer_config: Option, + /// PO token for fetching ABR stream + pub po_token: Option, /// Video frames for seek preview pub preview_frames: Vec, /// Video player DRM config @@ -207,6 +209,8 @@ pub struct VideoStream { pub average_bitrate: u32, /// Video file size in bytes pub size: Option, + /// Last modified timestamp + pub last_modified: Option, /// Index range (used for DASH streaming) pub index_range: Option>, /// Init range (used for DASH streaming) @@ -229,6 +233,8 @@ pub struct VideoStream { pub format: VideoFormat, /// Video codec pub codec: VideoCodec, + /// Stream tags + pub xtags: Option, /// DRM track type /// /// [`None`] if the track is not DRM-protected @@ -251,6 +257,8 @@ pub struct AudioStream { pub average_bitrate: u32, /// Audio file size in bytes pub size: u64, + /// Last modified timestamp + pub last_modified: Option, /// Index range (used for DASH streaming) pub index_range: Option>, /// Init range (used for DASH streaming) @@ -287,6 +295,8 @@ pub struct AudioStream { /// /// This is None if the video contains only 1 audio track. pub track: Option, + /// Stream tags (e.g. audio track language and type) + pub xtags: Option, /// DRM track type /// /// [`None`] if the track is not DRM-protected diff --git a/src/model/traits.rs b/src/model/traits.rs index 43d4236..e621199 100644 --- a/src/model/traits.rs +++ b/src/model/traits.rs @@ -18,6 +18,8 @@ pub trait YtStream { fn averate_bitrate(&self) -> u32; /// File size in bytes fn size(&self) -> Option; + /// Last modified timestamp + fn last_modified(&self) -> Option; /// Index range (used for DASH streaming) fn index_range(&self) -> Option>; /// Init range (used for DASH streaming) @@ -26,6 +28,8 @@ pub trait YtStream { fn duration_ms(&self) -> Option; /// MIME file type fn mime(&self) -> &str; + /// Stream tags (e.g. audio track language and type) + fn xtags(&self) -> Option<&str>; } impl YtStream for VideoStream { @@ -49,6 +53,10 @@ impl YtStream for VideoStream { self.size } + fn last_modified(&self) -> Option { + self.last_modified + } + fn index_range(&self) -> Option> { self.index_range.clone() } @@ -64,6 +72,10 @@ impl YtStream for VideoStream { fn mime(&self) -> &str { &self.mime } + + fn xtags(&self) -> Option<&str> { + self.xtags.as_deref() + } } impl YtStream for AudioStream { @@ -87,6 +99,10 @@ impl YtStream for AudioStream { Some(self.size) } + fn last_modified(&self) -> Option { + self.last_modified + } + fn index_range(&self) -> Option> { self.index_range.clone() } @@ -102,6 +118,10 @@ impl YtStream for AudioStream { fn mime(&self) -> &str { &self.mime } + + fn xtags(&self) -> Option<&str> { + self.xtags.as_deref() + } } /// Trait for file types diff --git a/src/param/stream_filter.rs b/src/param/stream_filter.rs index 99e9a31..537c490 100644 --- a/src/param/stream_filter.rs +++ b/src/param/stream_filter.rs @@ -179,7 +179,7 @@ impl StreamFilter { /// Allow ABR-only streams without URL #[must_use] - pub fn abr_only(mut self) -> Self { + pub fn allow_abr_only(mut self) -> Self { self.abr_only = true; self } @@ -283,8 +283,8 @@ impl StreamFilter { Some([language, track_type, channels.into(), bitrate]) } - fn apply_video(&self, stream: &VideoStream) -> VideoRes { - if stream.url.is_none() && !self.abr_only { + fn apply_video(&self, stream: &VideoStream, video_only: bool) -> VideoRes { + if stream.url.is_none() && !(self.abr_only && video_only) { return None; } @@ -363,6 +363,7 @@ impl VideoPlayer { fn _select_video_stream<'a>( streams: &'a [VideoStream], filter: &StreamFilter, + video_only: bool, ) -> Option<&'a VideoStream> { if filter.video_none { return None; @@ -370,19 +371,19 @@ impl VideoPlayer { streams .iter() - .filter_map(|s| filter.apply_video(s).map(|r| (s, r))) + .filter_map(|s| filter.apply_video(s, video_only).map(|r| (s, r))) .max_by_key(|(_, r)| *r) .map(|(s, _)| s) } /// Select the video stream which is the best match for the given [`StreamFilter`] pub fn select_video_stream(&self, filter: &StreamFilter) -> Option<&VideoStream> { - Self::_select_video_stream(&self.video_streams, filter) + Self::_select_video_stream(&self.video_streams, filter, false) } /// Select the video-only stream which is the best match for the given [`StreamFilter`] pub fn select_video_only_stream(&self, filter: &StreamFilter) -> Option<&VideoStream> { - Self::_select_video_stream(&self.video_only_streams, filter) + Self::_select_video_stream(&self.video_only_streams, filter, true) } /// Select a video and audio stream which is the best match for the given [`StreamFilter`] From e9fc556d899dc39cc7ee76518687f78d8b9e7ec9 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sat, 22 Mar 2025 23:23:48 +0100 Subject: [PATCH 04/21] wip: remove unused code --- downloader/src/abr2.rs | 170 +++++++---------------------------------- 1 file changed, 26 insertions(+), 144 deletions(-) diff --git a/downloader/src/abr2.rs b/downloader/src/abr2.rs index a6ebfef..d367d53 100644 --- a/downloader/src/abr2.rs +++ b/downloader/src/abr2.rs @@ -45,7 +45,6 @@ pub struct AbrStream { formats_by_key: HashMap, header_id_to_format_key_map: HashMap, previous_sequences: HashMap>, - // http_stream: Option>>, buffer: BytesBuffer, last_header: Option, } @@ -464,8 +463,8 @@ impl AbrStream { .or(self.formats_by_key.values().next()) } - pub fn stream(mut self) -> impl Stream> { - try_stream! { + fn stream(mut self) -> impl Stream> { + let stream = try_stream! { let mut ri = 1; loop { let body = VideoPlaybackAbrRequest { @@ -565,146 +564,11 @@ impl AbrStream { ri += 1; } - } + }; + Box::pin(stream) } } -/* -impl<'a> Stream for AbrStream { - type Item = Result; - - fn poll_next( - mut self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - loop { - if self.http_stream.is_none() { - let body = VideoPlaybackAbrRequest { - client_abr_state: MessageField::some(self.abr_state.clone()), - selected_format_ids: self - .formats_by_key - .values() - .map(|f| f.format_id.clone()) - .collect(), - buffered_ranges: self - .formats_by_key - .values() - .map(|f| f.state.clone()) - .collect(), - video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), - selected_audio_format_ids: self.audio_format_ids.clone(), - selected_video_format_ids: self.video_format_ids.clone(), - streamer_context: MessageField::some(StreamerContext { - client_info: MessageField::some(ClientInfo { - client_name: Some(1), - client_version: Some("2.20250314.01.00".to_owned()), - ..Default::default() - }), - po_token: self.po_token.clone(), - playback_cookie: self - .playback_cookie - .as_ref() - .and_then(|c| c.write_to_bytes().ok()), - ..Default::default() - }), - ..Default::default() - }; - - match ready!(self - .http - .post(&self.url) - .body(body.write_to_bytes()?) - .send() - .poll_unpin(cx)) - { - Ok(resp) => { - let resp = resp.error_for_status()?; - let data_stream = resp.bytes_stream(); - self.http_stream = Some(Box::pin(data_stream)); - self.buffer = BytesBuffer::new() - } - Err(e) => return Poll::Ready(Some(Err(e.into()))), - } - } - - while let Some(http_stream) = &mut self.http_stream { - match ready!(http_stream.poll_next_unpin(cx)) { - Some(chunk) => { - let chunk = chunk?; - let clen = chunk.len(); - self.buffer.push(chunk); - if self.buffer.pos() == 0 { - self.last_header = self.parse_ump_header(); - } - if let Some(item) = self.process_ump_part()? { - return Poll::Ready(Some(Ok(item))); - } - } - None => { - self.http_stream = None; - } - } - } - - ready!( - Box::pin(tokio::time::sleep(std::time::Duration::from_millis( - self.backoff_time_ms.try_into().unwrap_or_default(), - ))) - .poll_unpin(cx) - ); - } - } -} -*/ - -fn read_varint(data: &[u8]) -> (u64, usize) { - // Determine the length of the val - if data.is_empty() { - return (0, 0); - } - - let fb = data[0]; - let byte_length = if fb < 128 { - 1 - } else if fb < 192 { - 2 - } else if fb < 224 { - 3 - } else if fb < 240 { - 4 - } else { - 5 - }; - - if data.len() < byte_length { - return (0, 0); - } - - let n = match byte_length { - 1 => data[0].into(), - 2 => { - let b1 = u64::from(data[0]); - let b2 = u64::from(data[1]); - (b1 & 0x3f) + 64 * b2 - } - 3 => { - let b1 = u64::from(data[0]); - let b2 = u64::from(data[1]); - let b3 = u64::from(data[2]); - (b1 & 0x1f) + 32 * (b2 + 256 * b3) - } - 4 => { - let b1 = u64::from(data[0]); - let b2 = u64::from(data[1]); - let b3 = u64::from(data[2]); - let b4 = u64::from(data[3]); - (b1 & 0x0f) + 16 * (b2 + 256 * (b3 + 256 * b4)) - } - _ => u32::from_be_bytes([data[1], data[2], data[3], data[4]]).into(), - }; - (n, byte_length) -} - fn get_format_key(format_id: &FormatId) -> String { format!("{};{};", format_id.itag(), format_id.last_modified()) } @@ -762,6 +626,8 @@ impl TryFrom for InitializedFormat { #[cfg(test)] mod tests { + use std::io::Write; + use rustypipe::{ client::RustyPipe, model::{AudioCodec, VideoFormat}, @@ -781,7 +647,7 @@ mod tests { .video_formats([VideoFormat::Webm]) .audio_codecs([AudioCodec::Opus]); let (video, audio) = player.select_video_audio_stream(&stream_filter); - let _video = video.unwrap(); + let video = video.unwrap(); let audio = audio.unwrap(); let mut abr = AbrStream::new(AbrStreamOptions { @@ -789,11 +655,27 @@ mod tests { ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), po_token: player.po_token.as_deref(), audio_streams: &[audio], - video_streams: &[], + video_streams: &[video], ..Default::default() }) .unwrap(); - let mut stream = abr.stream().try_collect::>().await.unwrap(); - // dbg!(&stream); + + { + let mut stream = abr.stream(); + let mut files = HashMap::new(); + + while let Some(item) = stream.try_next().await.unwrap() { + let mut f = files.entry(item.format.itag).or_insert_with(|| { + std::fs::File::create(format!("test_{}.webm", item.format.itag)).unwrap() + }); + + f.write_all(&item.data).unwrap(); + } + } + + let audio_md = std::fs::metadata(format!("test_{}.webm", audio.itag)).unwrap(); + assert_eq!(audio_md.len(), audio.size); + let video_md = std::fs::metadata(format!("test_{}.webm", video.itag)).unwrap(); + assert_eq!(video_md.len(), video.size.unwrap()); } } From 1c2db9b88dfe21571fd1d7165f4f8dc42ce71b38 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 24 Mar 2025 01:33:42 +0100 Subject: [PATCH 05/21] Revert "fix: handle player returning no adaptive stream URLs" This reverts commit 07db7b1166e912e1554f98f2ae20c2c356fed38f. --- src/client/player.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/client/player.rs b/src/client/player.rs index 9128a54..70de86b 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -387,21 +387,6 @@ impl MapResponse for response::Player { video_details.video_id, ctx.id ))); } - // Sometimes YouTube Desktop does not output any URLs for adaptive streams. - // Since this is currently rare, it is best to retry the request in this case. - if !is_live - && !streaming_data.adaptive_formats.c.is_empty() - && streaming_data - .adaptive_formats - .c - .iter() - .all(|f| f.url.is_none() && f.signature_cipher.is_none()) - { - return Err(ExtractionError::Unavailable { - reason: UnavailabilityReason::TryAgain, - msg: "no adaptive stream URLs".to_owned(), - }); - } let video_info = VideoPlayerDetails { id: video_details.video_id, From cae99513f6f2da808abc544cf99c3cc8f8978334 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 24 Mar 2025 13:21:03 +0100 Subject: [PATCH 06/21] fix: A/B test 23 check --- codegen/src/abtest.rs | 2 +- notes/AB_Tests.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codegen/src/abtest.rs b/codegen/src/abtest.rs index 0f90b13..8c41913 100644 --- a/codegen/src/abtest.rs +++ b/codegen/src/abtest.rs @@ -485,5 +485,5 @@ pub async fn command_executor_command(rp: &RustyPipeQuery) -> Result { pub async fn abr_stream_only(rp: &RustyPipeQuery) -> Result { let id = "pxY4OXVyMe4"; let res = rp.player_from_client(id, ClientType::Desktop).await?; - Ok(res.video_streams.iter().all(|s| s.url.is_none())) + Ok(res.video_only_streams.iter().all(|s| s.url.is_none())) } diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 763622b..8f1edf9 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Experimental (<1%) +- **Status:** Common (5%) From 2f3c01cb286530b3b0d09f53a4c98abf325aa488 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 26 Mar 2025 00:27:39 +0100 Subject: [PATCH 07/21] wip --- downloader/Cargo.toml | 1 + downloader/src/abr2.rs | 135 +++++++++++++++++++++++------------ downloader/src/lib.rs | 1 + downloader/src/streamtest.rs | 25 +++++++ 4 files changed, 116 insertions(+), 46 deletions(-) create mode 100644 downloader/src/streamtest.rs diff --git a/downloader/Cargo.toml b/downloader/Cargo.toml index d5d1613..67c60eb 100644 --- a/downloader/Cargo.toml +++ b/downloader/Cargo.toml @@ -58,6 +58,7 @@ protobuf.workspace = true bytes = "1.0.0" byteorder = "1.0.0" async-stream = "0.3.6" +pin-project-lite = "0.2.11" [dev-dependencies] path_macro.workspace = true diff --git a/downloader/src/abr2.rs b/downloader/src/abr2.rs index d367d53..b543632 100644 --- a/downloader/src/abr2.rs +++ b/downloader/src/abr2.rs @@ -359,7 +359,7 @@ impl AbrStream { .iter() .all(|x| x.sequence_number != Some(mh.sequence_number())) { - current_format.sequence_list.push(Sequence { + let seq = Sequence { itag: mh.itag, format_id: format_id.clone(), is_init_segment: mh.is_init_seg(), @@ -369,7 +369,16 @@ impl AbrStream { sequence_number: mh.sequence_number, content_length: mh.content_length, time_range: mh.time_range.as_ref().cloned(), - }); + }; + dbg!(&seq); + if mh.itag == Some(251) { + tracing::debug!( + "audio #{}: {}", + seq.sequence_number.unwrap_or_default(), + seq.content_length.unwrap_or_default() + ); + } + current_format.sequence_list.push(seq); if mh.has_sequence_number() { current_format.state.set_duration_ms( @@ -463,48 +472,53 @@ impl AbrStream { .or(self.formats_by_key.values().next()) } + async fn fetch_stream_data(&self) -> Result { + let body = VideoPlaybackAbrRequest { + client_abr_state: MessageField::some(self.abr_state.clone()), + selected_format_ids: self + .formats_by_key + .values() + .map(|f| f.format_id.clone()) + .collect(), + buffered_ranges: self + .formats_by_key + .values() + .map(|f| f.state.clone()) + .collect(), + video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), + selected_audio_format_ids: self.audio_format_ids.clone(), + selected_video_format_ids: self.video_format_ids.clone(), + streamer_context: MessageField::some(StreamerContext { + client_info: MessageField::some(ClientInfo { + client_name: Some(1), + client_version: Some("2.20250314.01.00".to_owned()), + ..Default::default() + }), + po_token: self.po_token.clone(), + playback_cookie: self + .playback_cookie + .as_ref() + .and_then(|c| c.write_to_bytes().ok()), + ..Default::default() + }), + ..Default::default() + }; + + let resp = self + .http + .post(&self.url) + .body(body.write_to_bytes()?) + .send() + .await? + .error_for_status()?; + Ok(resp) + } + fn stream(mut self) -> impl Stream> { let stream = try_stream! { let mut ri = 1; loop { - let body = VideoPlaybackAbrRequest { - client_abr_state: MessageField::some(self.abr_state.clone()), - selected_format_ids: self - .formats_by_key - .values() - .map(|f| f.format_id.clone()) - .collect(), - buffered_ranges: self - .formats_by_key - .values() - .map(|f| f.state.clone()) - .collect(), - video_playback_ustreamer_config: Some(self.ustreamer_config.clone()), - selected_audio_format_ids: self.audio_format_ids.clone(), - selected_video_format_ids: self.video_format_ids.clone(), - streamer_context: MessageField::some(StreamerContext { - client_info: MessageField::some(ClientInfo { - client_name: Some(1), - client_version: Some("2.20250314.01.00".to_owned()), - ..Default::default() - }), - po_token: self.po_token.clone(), - playback_cookie: self - .playback_cookie - .as_ref() - .and_then(|c| c.write_to_bytes().ok()), - ..Default::default() - }), - ..Default::default() - }; - - let resp = self - .http - .post(&self.url) - .body(body.write_to_bytes()?) - .send() - .await? - .error_for_status()?; + let resp = self.fetch_stream_data().await?; let mut data_stream = resp.bytes_stream(); let mut page_len = 0; self.clear_sequence_list(); @@ -640,14 +654,14 @@ mod tests { #[tracing_test::traced_test] async fn experiment() { let rp = RustyPipe::new(); - let player = rp.query().player("UMm7Pq0BdRg").await.unwrap(); + let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); let stream_filter = StreamFilter::new() .allow_abr_only() - .video_max_res(360) + // .video_max_res(360) .video_formats([VideoFormat::Webm]) .audio_codecs([AudioCodec::Opus]); let (video, audio) = player.select_video_audio_stream(&stream_filter); - let video = video.unwrap(); + // let video = video.unwrap(); let audio = audio.unwrap(); let mut abr = AbrStream::new(AbrStreamOptions { @@ -655,7 +669,8 @@ mod tests { ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), po_token: player.po_token.as_deref(), audio_streams: &[audio], - video_streams: &[video], + // video_streams: &[video], + video_streams: &[], ..Default::default() }) .unwrap(); @@ -675,7 +690,35 @@ mod tests { let audio_md = std::fs::metadata(format!("test_{}.webm", audio.itag)).unwrap(); assert_eq!(audio_md.len(), audio.size); - let video_md = std::fs::metadata(format!("test_{}.webm", video.itag)).unwrap(); - assert_eq!(video_md.len(), video.size.unwrap()); + // let video_md = std::fs::metadata(format!("test_{}.webm", video.itag)).unwrap(); + // assert_eq!(video_md.len(), video.size.unwrap()); + } + + #[tokio::test] + #[tracing_test::traced_test] + async fn first_header() { + let rp = RustyPipe::new(); + let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); + let stream_filter = StreamFilter::new() + .allow_abr_only() + // .video_max_res(360) + .video_formats([VideoFormat::Webm]) + .audio_codecs([AudioCodec::Opus]); + let (video, audio) = player.select_video_audio_stream(&stream_filter); + // let video = video.unwrap(); + let audio = audio.unwrap(); + + let mut abr = AbrStream::new(AbrStreamOptions { + url: player.abr_streaming_url.clone().unwrap(), + ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), + po_token: player.po_token.as_deref(), + audio_streams: &[audio], + // video_streams: &[video], + video_streams: &[], + ..Default::default() + }) + .unwrap(); + + todo!() } } diff --git a/downloader/src/lib.rs b/downloader/src/lib.rs index b326cfb..f78df7d 100644 --- a/downloader/src/lib.rs +++ b/downloader/src/lib.rs @@ -6,6 +6,7 @@ mod abr; mod abr2; mod abr_model; mod error; +mod streamtest; mod util; use std::{ diff --git a/downloader/src/streamtest.rs b/downloader/src/streamtest.rs new file mode 100644 index 0000000..f9cd5b2 --- /dev/null +++ b/downloader/src/streamtest.rs @@ -0,0 +1,25 @@ +use async_stream::stream; +use futures_util::Stream; + +fn stream() -> impl Stream { + stream! { + let mut x = 0; + loop { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + yield x; + x += 1; + } + }; + + let (mut __yield_tx, __yield_rx) = unsafe { async_stream::__private::yielder::pair() }; + async_stream::__private::AsyncStream::new(__yield_rx, async move { + let mut x = 0; + loop { + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + { + __yield_tx.send(x).await + }; + x += 1; + } + }) +} From 69fb82e39f7faaedb5974d261dd943b473c53d7a Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 31 Mar 2025 18:00:28 +0200 Subject: [PATCH 08/21] test: update player data snapshots --- ...layer__tests__map_player_data_android.snap | 33 +++++++++++++++ ...layer__tests__map_player_data_desktop.snap | 41 +++++++++++++++++++ ...__tests__map_player_data_desktopmusic.snap | 29 +++++++++++++ ...t__player__tests__map_player_data_ios.snap | 9 ++++ ...nt__player__tests__map_player_data_tv.snap | 39 ++++++++++++++++++ 5 files changed, 151 insertions(+) diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap index 7d3fbe6..937d6b0 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_android.snap @@ -66,6 +66,7 @@ VideoPlayer( bitrate: 79452, average_bitrate: 79428, size: Some(1619781), + last_modified: Some(1580005480199246), index_range: None, init_range: None, duration_ms: Some(163143), @@ -77,6 +78,7 @@ VideoPlayer( mime: "video/3gpp; codecs=\"mp4v.20.3, mp4a.40.2\"", format: r#3gp, codec: mp4v, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -86,6 +88,7 @@ VideoPlayer( bitrate: 561339, average_bitrate: 561109, size: Some(11439331), + last_modified: Some(1580005476071743), index_range: None, init_range: None, duration_ms: Some(163096), @@ -97,6 +100,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -106,6 +110,7 @@ VideoPlayer( bitrate: 1574434, average_bitrate: 1574434, size: None, + last_modified: Some(1580005750956837), index_range: None, init_range: None, duration_ms: Some(163096), @@ -117,6 +122,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -128,6 +134,7 @@ VideoPlayer( bitrate: 67637, average_bitrate: 60063, size: Some(1224002), + last_modified: Some(1608045375671513), index_range: Some(Range( start: 700, end: 1115, @@ -145,6 +152,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.00M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -154,6 +162,7 @@ VideoPlayer( bitrate: 135747, average_bitrate: 109867, size: Some(2238952), + last_modified: Some(1608045728968690), index_range: Some(Range( start: 700, end: 1115, @@ -171,6 +180,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.00M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -180,6 +190,7 @@ VideoPlayer( bitrate: 538143, average_bitrate: 383195, size: Some(7808990), + last_modified: Some(1580005649163759), index_range: Some(Range( start: 740, end: 1155, @@ -197,6 +208,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401e\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -206,6 +218,7 @@ VideoPlayer( bitrate: 258097, average_bitrate: 202682, size: Some(4130385), + last_modified: Some(1608045761576250), index_range: Some(Range( start: 700, end: 1115, @@ -223,6 +236,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.01M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -232,6 +246,7 @@ VideoPlayer( bitrate: 436843, average_bitrate: 337281, size: Some(6873325), + last_modified: Some(1608045990917419), index_range: Some(Range( start: 700, end: 1115, @@ -249,6 +264,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.04M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -258,6 +274,7 @@ VideoPlayer( bitrate: 1348419, average_bitrate: 1097369, size: Some(22365208), + last_modified: Some(1608048380553749), index_range: Some(Range( start: 700, end: 1115, @@ -275,6 +292,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.08M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -284,6 +302,7 @@ VideoPlayer( bitrate: 4190323, average_bitrate: 3208919, size: Some(65400181), + last_modified: Some(1580005649161486), index_range: Some(Range( start: 740, end: 1155, @@ -301,6 +320,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64002a\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -310,6 +330,7 @@ VideoPlayer( bitrate: 2572342, average_bitrate: 2088624, size: Some(42567727), + last_modified: Some(1608052932785283), index_range: Some(Range( start: 700, end: 1115, @@ -327,6 +348,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.09M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -338,6 +360,7 @@ VideoPlayer( bitrate: 49724, average_bitrate: 48818, size: 995840, + last_modified: Some(1580005582214385), index_range: Some(Range( start: 641, end: 876, @@ -353,6 +376,7 @@ VideoPlayer( channels: Some(2), loudness_db: None, track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -362,6 +386,7 @@ VideoPlayer( bitrate: 53039, average_bitrate: 45845, size: 934449, + last_modified: Some(1608509101590706), index_range: Some(Range( start: 266, end: 551, @@ -377,6 +402,7 @@ VideoPlayer( channels: Some(2), loudness_db: None, track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -386,6 +412,7 @@ VideoPlayer( bitrate: 71268, average_bitrate: 61123, size: 1245866, + last_modified: Some(1608509101111096), index_range: Some(Range( start: 266, end: 551, @@ -401,6 +428,7 @@ VideoPlayer( channels: Some(2), loudness_db: None, track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -410,6 +438,7 @@ VideoPlayer( bitrate: 130268, average_bitrate: 129508, size: 2640283, + last_modified: Some(1580005579712232), index_range: Some(Range( start: 632, end: 867, @@ -425,6 +454,7 @@ VideoPlayer( channels: Some(2), loudness_db: None, track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -434,6 +464,7 @@ VideoPlayer( bitrate: 140633, average_bitrate: 121491, size: 2476314, + last_modified: Some(1608509101894140), index_range: Some(Range( start: 266, end: 551, @@ -449,6 +480,7 @@ VideoPlayer( channels: Some(2), loudness_db: None, track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -467,6 +499,7 @@ VideoPlayer( dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659481355/ei/q1jpYtOPEYSBgQeHmqbwAQ/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr5---sn-h0jeenek.googlevideo.com/mh/mQ/mm/31%2C29/mn/sn-h0jeenek%2Csn-h0jelnez/ms/au%2Crdu/mv/m/mvi/5/pl/37/hfr/1/as/fmp4_audio_clear%2Cfmp4_sd_hd_clear/initcwndbps/1527500/vprv/1/mt/1659459429/fvip/4/itag_bl/376%2C377%2C384%2C385%2C612%2C613%2C617%2C619%2C623%2C628%2C655%2C656%2C660%2C662%2C666%2C671/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cvprv%2Citag/sig/AOq0QJ8wRAIgMm4a_MIHA3YUszKeruSy3exs5JwNjJAyLAwxL0yPdNMCIANb9GDMSTp_NT-PPhbvYMwRULJ5a9BO6MYD9FuWprC1/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgETSOwhwWVMy7gmrFXZlJu655ToLzSwOEsT16oRyrWhACIQDkvOEw1fImz5omu4iVIRNFe-z-JC9v8WUyx281dW2NOw%3D%3D"), abr_streaming_url: None, abr_ustreamer_config: Some("Cs0CCAAlMZkqPi0AAIA_NT0Klz9YAXjoAoABAaABAbUB9ijcP-ABAegBA_ABAfkBAAAAAAAA0D-BAgAAAAAAABhAmALwAaAC6AK4AgDaAlUQsOoBGKhGIKCcASjYNjCYdXCIJ4AB9AO4AQHgAQGYAgyoAgGwAgG4AgHAAgHIAgHQAgLgAgHoAgLwAgGAAwaIA4gnmAMBqAMIsAMBuAMBwAMB2AMB-gIrCAwQGBgyIDItAABwQjUAAIxCQAFIAWUAAIBAaMBwzQEAAIA_8AEB6ALgA4IDAJADAaADAbADA-ADkE6wBAG4BAHKBFgKFQiA4gkQmHUYrAIlAAAAACgAMABAARDg1AMY0A8qNgoKdGJfY29zdF81MCAIKQAAAAAAAAAASAFQAV2amZk-ZQAAAD9tAAAAP3UAAAA_eMCpB5IBADAB6AQB8AQB-AQBkAUBGAEgATIMCKsCEI662NuboOcCMgwIjwMQg-na_r_Q7QIyDAiqAhCOutjbm6DnAjIMCI4DEJXUhISv0O0CMgwIhwEQjrrY25ug5wIyDAiNAxCr6siQptDtAjIMCIYBEO_L2NuboOcCMgwIjAMQuvqao6XQ7QIyDAiFARCOutjbm6DnAjIMCIsDEPLf1JOl0O0CMgwIoAEQjrrY25ug5wIyDAiKAxDZmZnro9DtAjIMCIsBEPGp4ruboOcCMgwIjAEQ6M3Jupug5wIyDAj5ARCykfms493tAjIMCPoBELju26zj3e0CMgwI-wEQ_NOLrePd7QI6AA=="), + po_token: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap index 3ceaadf..f2ded40 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktop.snap @@ -71,6 +71,7 @@ VideoPlayer( bitrate: 561339, average_bitrate: 561109, size: Some(11439331), + last_modified: Some(1580005476071743), index_range: None, init_range: None, duration_ms: Some(163096), @@ -82,6 +83,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -93,6 +95,7 @@ VideoPlayer( bitrate: 87458, average_bitrate: 72857, size: Some(1484736), + last_modified: Some(1608509388295661), index_range: Some(Range( start: 218, end: 751, @@ -110,6 +113,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -119,6 +123,7 @@ VideoPlayer( bitrate: 67637, average_bitrate: 60063, size: Some(1224002), + last_modified: Some(1608045375671513), index_range: Some(Range( start: 700, end: 1115, @@ -136,6 +141,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.00M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -145,6 +151,7 @@ VideoPlayer( bitrate: 184064, average_bitrate: 145902, size: Some(2973283), + last_modified: Some(1608509388282028), index_range: Some(Range( start: 219, end: 753, @@ -162,6 +169,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -171,6 +179,7 @@ VideoPlayer( bitrate: 135747, average_bitrate: 109867, size: Some(2238952), + last_modified: Some(1608045728968690), index_range: Some(Range( start: 700, end: 1115, @@ -188,6 +197,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.00M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -197,6 +207,7 @@ VideoPlayer( bitrate: 538143, average_bitrate: 383195, size: Some(7808990), + last_modified: Some(1580005649163759), index_range: Some(Range( start: 740, end: 1155, @@ -214,6 +225,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401e\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -223,6 +235,7 @@ VideoPlayer( bitrate: 319085, average_bitrate: 253673, size: Some(5169510), + last_modified: Some(1608509388282405), index_range: Some(Range( start: 220, end: 754, @@ -240,6 +253,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -249,6 +263,7 @@ VideoPlayer( bitrate: 258097, average_bitrate: 202682, size: Some(4130385), + last_modified: Some(1608045761576250), index_range: Some(Range( start: 700, end: 1115, @@ -266,6 +281,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.01M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -275,6 +291,7 @@ VideoPlayer( bitrate: 539056, average_bitrate: 436270, size: Some(8890590), + last_modified: Some(1608509388284632), index_range: Some(Range( start: 220, end: 754, @@ -292,6 +309,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -301,6 +319,7 @@ VideoPlayer( bitrate: 436843, average_bitrate: 337281, size: Some(6873325), + last_modified: Some(1608045990917419), index_range: Some(Range( start: 700, end: 1115, @@ -318,6 +337,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.04M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -327,6 +347,7 @@ VideoPlayer( bitrate: 982813, average_bitrate: 812006, size: Some(16547577), + last_modified: Some(1608509388326822), index_range: Some(Range( start: 220, end: 754, @@ -344,6 +365,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -353,6 +375,7 @@ VideoPlayer( bitrate: 2354009, average_bitrate: 1764202, size: Some(35955780), + last_modified: Some(1608509234088626), index_range: Some(Range( start: 219, end: 771, @@ -370,6 +393,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -379,6 +403,7 @@ VideoPlayer( bitrate: 1348419, average_bitrate: 1097369, size: Some(22365208), + last_modified: Some(1608048380553749), index_range: Some(Range( start: 700, end: 1115, @@ -396,6 +421,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.08M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -405,6 +431,7 @@ VideoPlayer( bitrate: 4190323, average_bitrate: 3208919, size: Some(65400181), + last_modified: Some(1580005649161486), index_range: Some(Range( start: 740, end: 1155, @@ -422,6 +449,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64002a\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -431,6 +459,7 @@ VideoPlayer( bitrate: 3832648, average_bitrate: 3090839, size: Some(62993617), + last_modified: Some(1608509371758331), index_range: Some(Range( start: 219, end: 776, @@ -448,6 +477,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -457,6 +487,7 @@ VideoPlayer( bitrate: 2572342, average_bitrate: 2088624, size: Some(42567727), + last_modified: Some(1608052932785283), index_range: Some(Range( start: 700, end: 1115, @@ -474,6 +505,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"av01.0.09M.08\"", format: mp4, codec: av01, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -485,6 +517,7 @@ VideoPlayer( bitrate: 53039, average_bitrate: 45845, size: 934449, + last_modified: Some(1608509101590706), index_range: Some(Range( start: 266, end: 551, @@ -500,6 +533,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2200003), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -509,6 +543,7 @@ VideoPlayer( bitrate: 71268, average_bitrate: 61123, size: 1245866, + last_modified: Some(1608509101111096), index_range: Some(Range( start: 266, end: 551, @@ -524,6 +559,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2200003), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -533,6 +569,7 @@ VideoPlayer( bitrate: 130268, average_bitrate: 129508, size: 2640283, + last_modified: Some(1580005579712232), index_range: Some(Range( start: 632, end: 867, @@ -548,6 +585,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2159004), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -557,6 +595,7 @@ VideoPlayer( bitrate: 140633, average_bitrate: 121491, size: 2476314, + last_modified: Some(1608509101894140), index_range: Some(Range( start: 266, end: 551, @@ -572,6 +611,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2200003), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -590,6 +630,7 @@ VideoPlayer( dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659481355/ei/q1jpYtq3BJCX1gKVyJGQDg/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr4---sn-h0jelnez.googlevideo.com/mh/mQ/mm/31%2C26/mn/sn-h0jelnez%2Csn-4g5edn6k/ms/au%2Conr/mv/m/mvi/4/pl/37/hfr/all/as/fmp4_audio_clear%2Cwebm_audio_clear%2Cwebm2_audio_clear%2Cfmp4_sd_hd_clear%2Cwebm2_sd_hd_clear/initcwndbps/1513750/spc/lT-KhrZGE2opztWyVdAtyUNlb8dXPDs/vprv/1/mt/1659459429/fvip/4/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cspc%2Cvprv%2Citag/sig/AOq0QJ8wRgIhAPEjHK19PKVHqQeia6WF4qubuMYk74LGi8F8lk5ZMPkFAiEAsaB2pKQWBvuPnNUnbdQXHc-izgsHJUP793woC2xNJlg%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgOY4xu4H9wqPVZ7vF2i0hFcOnqrur1XGoA43a7ZEuuSUCIQCyPxBKXUQrKFmknNEGpX5GSWySKgMw_xHBikWpKpKwvg%3D%3D"), abr_streaming_url: None, abr_ustreamer_config: None, + po_token: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap index a6c2df6..7308a6e 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_desktopmusic.snap @@ -39,6 +39,7 @@ VideoPlayer( bitrate: 561339, average_bitrate: 561109, size: Some(11439331), + last_modified: Some(1580005476071743), index_range: None, init_range: None, duration_ms: Some(163096), @@ -50,6 +51,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -61,6 +63,7 @@ VideoPlayer( bitrate: 87458, average_bitrate: 72857, size: Some(1484736), + last_modified: Some(1608509388295661), index_range: Some(Range( start: 218, end: 751, @@ -78,6 +81,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -87,6 +91,7 @@ VideoPlayer( bitrate: 184064, average_bitrate: 145902, size: Some(2973283), + last_modified: Some(1608509388282028), index_range: Some(Range( start: 219, end: 753, @@ -104,6 +109,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -113,6 +119,7 @@ VideoPlayer( bitrate: 538143, average_bitrate: 383195, size: Some(7808990), + last_modified: Some(1580005649163759), index_range: Some(Range( start: 740, end: 1155, @@ -130,6 +137,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401e\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -139,6 +147,7 @@ VideoPlayer( bitrate: 319085, average_bitrate: 253673, size: Some(5169510), + last_modified: Some(1608509388282405), index_range: Some(Range( start: 220, end: 754, @@ -156,6 +165,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -165,6 +175,7 @@ VideoPlayer( bitrate: 539056, average_bitrate: 436270, size: Some(8890590), + last_modified: Some(1608509388284632), index_range: Some(Range( start: 220, end: 754, @@ -182,6 +193,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -191,6 +203,7 @@ VideoPlayer( bitrate: 982813, average_bitrate: 812006, size: Some(16547577), + last_modified: Some(1608509388326822), index_range: Some(Range( start: 220, end: 754, @@ -208,6 +221,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -217,6 +231,7 @@ VideoPlayer( bitrate: 2354009, average_bitrate: 1764202, size: Some(35955780), + last_modified: Some(1608509234088626), index_range: Some(Range( start: 219, end: 771, @@ -234,6 +249,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -243,6 +259,7 @@ VideoPlayer( bitrate: 4190323, average_bitrate: 3208919, size: Some(65400181), + last_modified: Some(1580005649161486), index_range: Some(Range( start: 740, end: 1155, @@ -260,6 +277,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64002a\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -269,6 +287,7 @@ VideoPlayer( bitrate: 3832648, average_bitrate: 3090839, size: Some(62993617), + last_modified: Some(1608509371758331), index_range: Some(Range( start: 219, end: 776, @@ -286,6 +305,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -297,6 +317,7 @@ VideoPlayer( bitrate: 53039, average_bitrate: 45845, size: 934449, + last_modified: Some(1608509101590706), index_range: Some(Range( start: 266, end: 551, @@ -312,6 +333,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(0.0006532669), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -321,6 +343,7 @@ VideoPlayer( bitrate: 71268, average_bitrate: 61123, size: 1245866, + last_modified: Some(1608509101111096), index_range: Some(Range( start: 266, end: 551, @@ -336,6 +359,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(0.0006532669), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -345,6 +369,7 @@ VideoPlayer( bitrate: 130268, average_bitrate: 129508, size: 2640283, + last_modified: Some(1580005579712232), index_range: Some(Range( start: 632, end: 867, @@ -360,6 +385,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(-0.003446579), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -369,6 +395,7 @@ VideoPlayer( bitrate: 140633, average_bitrate: 121491, size: 2476314, + last_modified: Some(1608509101894140), index_range: Some(Range( start: 266, end: 551, @@ -384,6 +411,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(0.0006532669), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -402,6 +430,7 @@ VideoPlayer( dash_manifest_url: Some("https://manifest.googlevideo.com/api/manifest/dash/expire/1659487474/ei/knDpYub6BojEgAf6jbLgDw/ip/2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e/id/a4fbddf14c6649b4/source/youtube/requiressl/yes/playback_host/rr5---sn-h0jeenek.googlevideo.com/mh/mQ/mm/31%2C29/mn/sn-h0jeenek%2Csn-h0jelnez/ms/au%2Crdu/mv/m/mvi/5/pl/37/hfr/all/as/fmp4_audio_clear%2Cwebm_audio_clear%2Cwebm2_audio_clear%2Cfmp4_sd_hd_clear%2Cwebm2_sd_hd_clear/initcwndbps/1418750/spc/lT-Khox4YuJQ2wmH79zYALRvsWTPCUc/vprv/1/mt/1659465669/fvip/4/keepalive/yes/fexp/24001373%2C24007246/itag/0/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Chfr%2Cas%2Cspc%2Cvprv%2Citag/sig/AOq0QJ8wRAIgErABhAEaoKHUDu9dDbpxE_8gR4b8WWAi61fnu8UKnuICIEYrEKcHvqHdO4V3R7cvSGwi_HGH34IlQsKbziOfMBov/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AG3C_xAwRQIgJxHmH0Sxo3cY_pW_ZzQ3hW9-7oz6K_pZWcUdrDDQ2sQCIQDJYNINQwLgKelgbO3CZYx7sMxdUAFpWdokmRBQ77vwvw%3D%3D"), abr_streaming_url: None, abr_ustreamer_config: None, + po_token: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLAXobPyrylgm8IEvjlZzqYTiPe1Ow", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap index 72669c4..7914ab5 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_ios.snap @@ -62,6 +62,7 @@ VideoPlayer( bitrate: 538143, average_bitrate: 383195, size: Some(7808990), + last_modified: Some(1580005649163759), index_range: Some(Range( start: 740, end: 1155, @@ -79,6 +80,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4D401E\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -88,6 +90,7 @@ VideoPlayer( bitrate: 4190323, average_bitrate: 3208919, size: Some(65400181), + last_modified: Some(1580005649161486), index_range: Some(Range( start: 740, end: 1155, @@ -105,6 +108,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64002A\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -116,6 +120,7 @@ VideoPlayer( bitrate: 49724, average_bitrate: 48818, size: 995840, + last_modified: Some(1580005582214385), index_range: Some(Range( start: 641, end: 876, @@ -131,6 +136,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2159004), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -140,6 +146,7 @@ VideoPlayer( bitrate: 130268, average_bitrate: 129508, size: 2640283, + last_modified: Some(1580005579712232), index_range: Some(Range( start: 632, end: 867, @@ -155,6 +162,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2159004), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -173,6 +181,7 @@ VideoPlayer( dash_manifest_url: None, abr_streaming_url: Some("https://rr4---sn-h0jelnez.googlevideo.com/videoplayback?c=IOS&ei=q1jpYq-xHs7NgQev0bfwAQ&expire=1659481355&fexp=24001373%2C24007246&fvip=5&id=o-ANNg3iPHI56jhLSlPQk4pi4mdub5iAby0hmJBVrtiJgY&initcwndbps=1513750&ip=2003%3Ade%3Aaf0e%3A2f00%3Ade47%3A297%3Aa6db%3A774e&keepalive=yes&lsig=AG3C_xAwRgIhAK6T5ehnFBsc0FOurPHH1ME_vGcVysI-g5jrtEsvX64sAiEArY-iAvQCsc4R8yg8dvMdpnuHPIcPMCnRgyh8E527HF0%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mm=31%2C29&mn=sn-h0jelnez%2Csn-h0jeenek&ms=au%2Crdu&mt=1659459429&mv=m&mvi=4&pl=37&rbqsm=fr&requiressl=yes&sabr=1&sig=AOq0QJ8wRgIhAJCJpb5gE12jQc2qOUy-Y61vEHeiAP_F78weNCzj8VklAiEAwR2PK52CmwsVHfRVk75OOYOxwYKNW2g1eDBw3COBP9w%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Csvpuc%2Csabr&svpuc=1"), abr_ustreamer_config: Some("CpYECp0DCAAQgAUY6AIl-n6qPi0AAIA_NT0Klz9oAXI6ChJtZnMyX2NtZnNfdjNfMV8wNDMSIAoeCgxkZXZpY2VfbW9kZWwSDgoMCgppcGhvbmUxNCw1GAAgAXIWChJtZnMyX2NtZnNfdjNfMV8wNDMYAHjoAoABAagBAbUB9ijcP6AC6AK4AgDaAmEQsOoBGKhGIKCcASjYNjCYdXCIJ4AB9AO4AQHgAQP4AQGQAgGYAgygAgGoAgGwAgG4AgHAAgHIAgHQAgLgAgHoAgLwAgGAAwKIA4gnmAMBqAMIwAMByAMB2AMB-LWR5QwB-gIvCAwQGBgyIDItAABwQjUAAIxCQAFIAVAKWAplAACAQGjAcM0BAACAP_ABAegC0AWCAwCQAwGgAwGoAwGwAwPQAwHYAwHgA5BOuAQBygRWChUI4NQDEJh1GOgHJQAAAAAoADAAQAEQ4NQDGNAPKjYKCnRiX2Nvc3RfNTAgDykAAAAAAAAAAEgBUAFdZmbmPmXNzEw-bZqZGT91mpkZP3jAqQeSAQDoBAHwBAH4BAGQBQGgBQEYASABMgwIqwIQjrrY25ug5wIyDAiqAhCOutjbm6DnAjIMCIcBEI662NuboOcCMgwIhgEQ78vY25ug5wIyDAiFARCOutjbm6DnAjIMCKABEI662NuboOcCMgwIiwEQ8aniu5ug5wIyDAiMARDozcm6m6DnAjoAEkwA8tjvwTBFAiAyo6mtW-M8Y8noBO_6Y3RmNo5U2LntCwiKcI2yye_zRgIhAK27d1UbqzhtkQhminIBAajD70ONeAQNwjt7VRpJRDimGgJlaQ=="), + po_token: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwGbA0g48quKqQOSA4gBAZUBAAAEQpgBMqABPKgBBLABELABDbABDLABELABFbABH7ABJrABLbABDrABDrABD7ABErABF7ABK7ABLLABKbABD7ABDrABELABFbABH7ABKrABMrABKbABD7ABEbABFLABGLABJrABPbABOLABLbABEbABFLABHrABKrABMbABS7ABR7ABNrABFbABHLABKbABLrABObABR7ABTbABP7ABJbABLrABN7ABPbABR7ABUrABUbABRbABM7ABQLABQrABQ7ABTLABRLABRrABQ7gBEbgBEbgBFbgBI7gBRLgBQ7gBQ7gBQ7gBEbgBE7gBFrgBL7gBQ7gBQ7gBQ7gBQ7gBFbgBFrgBKbgBQ7gBQ7gBQ7gBQ7gBQ7gBI7gBL7gBQ7gBQ7gBQ7gBQ7gBQ7gBQ7gBRLgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLCsCT8Lprh2S0ptmCRsWH7VtDl3YQ", diff --git a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap index 32ba960..bada27e 100644 --- a/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap +++ b/src/client/snapshots/rustypipe__client__player__tests__map_player_data_tv.snap @@ -29,6 +29,7 @@ VideoPlayer( bitrate: 503574, average_bitrate: 503367, size: Some(10262148), + last_modified: Some(1700885551970466), index_range: None, init_range: None, duration_ms: Some(163096), @@ -40,6 +41,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -51,6 +53,7 @@ VideoPlayer( bitrate: 114816, average_bitrate: 111551, size: Some(2273274), + last_modified: Some(1705967288821438), index_range: Some(Range( start: 738, end: 1165, @@ -68,6 +71,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d400c\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -77,6 +81,7 @@ VideoPlayer( bitrate: 70630, average_bitrate: 56524, size: Some(1151892), + last_modified: Some(1705966620402771), index_range: Some(Range( start: 218, end: 767, @@ -94,6 +99,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -103,6 +109,7 @@ VideoPlayer( bitrate: 257417, average_bitrate: 246656, size: Some(5026513), + last_modified: Some(1705967298859029), index_range: Some(Range( start: 739, end: 1166, @@ -120,6 +127,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d4015\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -129,6 +137,7 @@ VideoPlayer( bitrate: 149589, average_bitrate: 124706, size: Some(2541351), + last_modified: Some(1705966614837727), index_range: Some(Range( start: 219, end: 768, @@ -146,6 +155,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -155,6 +165,7 @@ VideoPlayer( bitrate: 537902, average_bitrate: 383290, size: Some(7810925), + last_modified: Some(1705967286812435), index_range: Some(Range( start: 740, end: 1167, @@ -172,6 +183,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401e\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -181,6 +193,7 @@ VideoPlayer( bitrate: 248858, average_bitrate: 205556, size: Some(4188954), + last_modified: Some(1705966624121874), index_range: Some(Range( start: 220, end: 770, @@ -198,6 +211,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -207,6 +221,7 @@ VideoPlayer( bitrate: 978945, average_bitrate: 722499, size: Some(14723538), + last_modified: Some(1705967282545273), index_range: Some(Range( start: 740, end: 1167, @@ -224,6 +239,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401f\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -233,6 +249,7 @@ VideoPlayer( bitrate: 467884, average_bitrate: 382209, size: Some(7788899), + last_modified: Some(1705966622098793), index_range: Some(Range( start: 220, end: 770, @@ -250,6 +267,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -259,6 +277,7 @@ VideoPlayer( bitrate: 1560439, average_bitrate: 1207947, size: Some(24616305), + last_modified: Some(1705967307531372), index_range: Some(Range( start: 739, end: 1166, @@ -276,6 +295,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d401f\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -285,6 +305,7 @@ VideoPlayer( bitrate: 929607, average_bitrate: 722521, size: Some(14723992), + last_modified: Some(1705966613897741), index_range: Some(Range( start: 220, end: 770, @@ -302,6 +323,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -311,6 +333,7 @@ VideoPlayer( bitrate: 2188961, average_bitrate: 1694973, size: Some(34544823), + last_modified: Some(1705967092637061), index_range: Some(Range( start: 739, end: 1166, @@ -328,6 +351,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.4d4020\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -337,6 +361,7 @@ VideoPlayer( bitrate: 2250391, average_bitrate: 1482051, size: Some(30205331), + last_modified: Some(1705966545733919), index_range: Some(Range( start: 219, end: 786, @@ -354,6 +379,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -363,6 +389,7 @@ VideoPlayer( bitrate: 3926810, average_bitrate: 3044926, size: Some(62057888), + last_modified: Some(1705967093743693), index_range: Some(Range( start: 740, end: 1167, @@ -380,6 +407,7 @@ VideoPlayer( mime: "video/mp4; codecs=\"avc1.64002a\"", format: mp4, codec: avc1, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -389,6 +417,7 @@ VideoPlayer( bitrate: 3473307, average_bitrate: 2713348, size: Some(55300085), + last_modified: Some(1705966651743358), index_range: Some(Range( start: 219, end: 792, @@ -406,6 +435,7 @@ VideoPlayer( mime: "video/webm; codecs=\"vp9\"", format: webm, codec: vp9, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -417,6 +447,7 @@ VideoPlayer( bitrate: 53073, average_bitrate: 45860, size: 934750, + last_modified: Some(1714877357172339), index_range: Some(Range( start: 266, end: 551, @@ -432,6 +463,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.21), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -441,6 +473,7 @@ VideoPlayer( bitrate: 71197, average_bitrate: 61109, size: 1245582, + last_modified: Some(1714877466693058), index_range: Some(Range( start: 266, end: 551, @@ -456,6 +489,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.21), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -465,6 +499,7 @@ VideoPlayer( bitrate: 130268, average_bitrate: 129508, size: 2640283, + last_modified: Some(1705966477945761), index_range: Some(Range( start: 632, end: 867, @@ -480,6 +515,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.2200003), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -489,6 +525,7 @@ VideoPlayer( bitrate: 140833, average_bitrate: 121691, size: 2480393, + last_modified: Some(1714877359450110), index_range: Some(Range( start: 266, end: 551, @@ -504,6 +541,7 @@ VideoPlayer( channels: Some(2), loudness_db: Some(5.21), track: None, + xtags: None, drm_track_type: None, drm_systems: [], ), @@ -522,6 +560,7 @@ VideoPlayer( dash_manifest_url: None, abr_streaming_url: Some("https://rr5---sn-h0jeenek.googlevideo.com/videoplayback?c=TVHTML5&ei=viioZtTdKteHi9oPl42KsAg&expire=1722318110&fvip=4&id=o-AC7iotZ_nCvg7C6fK7ofX174GXVOdwW68lsyXLLmCs0h&initcwndbps=1957500&ip=93.235.183.158&keepalive=yes&lsig=AGtxev0wRgIhANyFV4Ji7jlkXvfkb_czMQDZCiu6AbJ3Kzyv_s9V9WyvAiEA0o8XuM9kyh98hG1yg7h44L3I5OAUXuTpQdjxUaZ1V4A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=mQ&mm=31%2C29&mn=sn-h0jeenek%2Csn-h0jelnez&ms=au%2Crdu&mt=1722295996&mv=m&mvi=5&n=eBXmY26Y0c3VPyt&ns=Kl83P0QZk1oI9742KUD7ly8Q&pl=26&requiressl=yes&rqh=1&sabr=1&sig=AJfQdSswRAIgJRK55pIkQ3Pak9jZ4fHPDsxXv0YgkxKE-FFdIN12ph8CIFHlFEvAoUOoX4Fd1RmyCJqgLZhDkSLwD6s-xVW25kYL&smc=1&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Csvpuc%2Cns%2Csabr%2Crqh&svpuc=1&xpc=EgVo2aDSNQ%3D%3D"), abr_ustreamer_config: Some("CswJCpcHCAAlAACAPy1SuF4_NQAAwD9YAWABaAFyFgoSbWZzMl9jbWZzX3YzXzJfMTA5GAB4j06gAQGoAQCQAgG4AgDIAgHaAroBELDqARioRiCgnAEoiCcwmHVwiCeAAfQDuAEB4AEDkAIBmAIMoAIBwAIB0AIC4AIB6AIEgAMCiAOIJ5gDAagDA8ADAcgDAdADAfgDAYAEAYgEAZAEAZgEAaAEAagEAcgEAdAEAdgEAeAEAOgEAfgEB4AFfYgFAbAFAbgFAcAFAcgFAdAFAdgFAeAF0A_oBQH4BdAPgAYBuAYBwAYB0AYB2AYB6AYB8AYB-AYBkAcBqAcB2AcB-LWR5QwB-gKeAi0AAIJCNQAAlkJIAWUAAIBAaMBwqAHQhgOwAeADuAEBzQEAAIA_8AEB_QEAAIA_hQKamRk-jQIAAIA_lQIAAAJCmAIBtQIAAIA_wALgA9ICEbD__________wEePEZaXF1e2gIFMjA6MDDgAnjoAugC9QIK16M7_QLNzMw9gAMBkAMBnQMK1yM9oAMBuAMByAMB2AMB5QNiSkRA7QMyyvM-8AMB_QNmZoY_hQQAAIBAmAQB1QQAACBB6ATwEPAEAb0Fo0Afu8UF308tP8gFAeAFAZgGAaAGAagGAbUGvTeGNb0GMzODQJAHAcAHAcgHAdUHAICdQ-UHAIAJRKEIAAAAAAAA8L-pCAAAAAAAAPC_sAjwAbgIAdgI8AHoCAGCAwCQAwGoAwGwAwPQAwHYAwHgA5BOuAQBygQcChMIwKkHEJh1GOgHJQAAAAAoADAAEODUAxjQD9IEDQoICLAJELAJIAEgiCfaBAsKBgjwLhDwLiCIJ-gEAfgEAYAFAYgFAZAFAagFAbAFAdAFAdgFAegFAfAFAYgGAZgGAagGgIACwAYByAYB0gYUCOgHEGQaDQiIJxUAAAA_Hc3MTD-CBwoVAACAPxhkIJBOiAcBoAcBsAcBuAcBwAcB-AcBgAgBoAgBsAgBuAgB0ggGCAEQARgBmAkBqQkAAAAAAADwv7EJAAAAAAAA8L_ICQHaCSRFRzRmTDl1Sm9tL2NWdklmNjg4bnB6c2t4SVQrMXl0N09POHXgCQGwCgHYCgHwCgGICwGYCwG4CwHICwHQCwHYCwHqCwSLBowG8AsB-AsBkAwBoAwBqAyQAbAMAbgMAcAMAdAMAeAMAegMAYANAaANAdANAeANAYgOAZAOAbAOAYinocoLARgBIAEyDAirAhDNgPzUlvKDAzIMCK8CEP64moKV8oMDMgwIiAEQ7Mj0upfygwMyDAj3ARCNxJTwlPKDAzIMCKoCEIW7uNSW8oMDMgwIrgIQn5LUz5TygwMyDAiHARD5xP-ul_KDAzIMCPQBEOmKifSU8oMDMgwIhgEQk_6DsZfygwMyDAjzARCSyIT1lPKDAzIMCIUBEJWg47aX8oMDMgwI8gEQ3_PN8JTygwMyDAigARC-zf6xl_KDAzIMCJYCENPIofOU8oMDMgwIjAEQodeqr5TygwMyDAj5ARDzzNT9v_WFAzIMCPoBEMKb8bHA9YUDMgwI-wEQ_s_f_r_1hQM6AEgAUiYaAmVuKAAyGFVDYnh4RWktSW1QbGJMeDVGLWZIZXRFZzgAQABYAJDL048OARJNAKEYC4YwRgIhAIj4Ug4dw_gq15NXvgcfXpI1Fm_fhmwl-4ad-rX3Ffg_AiEAkZDsUgoAGLOXIvWZlNyuyfu8HLWt-snFl3gkTiPo2acaAmVp"), + po_token: None, preview_frames: [ Frameset( url_template: "https://i.ytimg.com/sb/pPvd8UxmSbQ/storyboard3_L0/default.jpg?sqp=-oaymwGbA0g48quKqQOSA4gBAZUBAAAEQpgBMqABPKgBBLABELABDbABDLABELABFbABH7ABJrABLbABDrABDrABD7ABErABF7ABK7ABLLABKbABD7ABDrABELABFbABH7ABKrABMrABKbABD7ABEbABFLABGLABJrABPbABOLABLbABEbABFLABHrABKrABMbABS7ABR7ABNrABFbABHLABKbABLrABObABR7ABTbABP7ABJbABLrABN7ABPbABR7ABUrABUbABRbABM7ABQLABQrABQ7ABTLABRLABRrABQ7gBEbgBEbgBFbgBI7gBRLgBQ7gBQ7gBQ7gBEbgBE7gBFrgBL7gBQ7gBQ7gBQ7gBQ7gBFbgBFrgBKbgBQ7gBQ7gBQ7gBQ7gBQ7gBI7gBL7gBQ7gBQ7gBQ7gBQ7gBQ7gBQ7gBRLgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQ7gBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQ7gBQ7gBQ7gBQrgBQrgBQrgBQrgBQqLzl_8DBgjf8LPxBQ==&sigh=rs$AOn4CLCsCT8Lprh2S0ptmCRsWH7VtDl3YQ", From a389648a4b01135c95535347b541a197794aa31d Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Thu, 3 Apr 2025 12:57:11 +0200 Subject: [PATCH 09/21] docs: abr streams now returned with 10% probability --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 8f1edf9..127721a 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Common (5%) +- **Status:** Common (10%) From e759738c00c604c8b6ef61d718425f0e86ebd4aa Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Fri, 4 Apr 2025 15:00:38 +0200 Subject: [PATCH 10/21] feat: add allow_abr_only option --- src/client/mod.rs | 35 +++++++++++++++++++++++++++++++++++ src/client/player.rs | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/client/mod.rs b/src/client/mod.rs index 06386bc..4f0d792 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -400,6 +400,7 @@ struct RustyPipeOpts { utc_offset_minutes: i16, report: bool, strict: bool, + allow_abr_only: bool, auth: Option, visitor_data: Option, } @@ -556,6 +557,7 @@ impl Default for RustyPipeOpts { utc_offset_minutes: 0, report: false, strict: false, + allow_abr_only: false, auth: None, visitor_data: None, } @@ -962,6 +964,22 @@ impl RustyPipeBuilder { self } + /// Allow fetching player data containing only the ABR (Adaptive bitrate) stream URL. + /// + /// YouTube may return only the ABR stream URL and no URLs for individual streams + /// when using desktop client. To access the streams, your application needs to support + /// the ABR streaming protocol. + /// + /// You also need to set the `allow_abr_only` option for the [`crate::param::StreamFilter`] + /// to select streams without an URL. + /// + /// **Info**: you can set this option for individual queries, too + #[must_use] + pub fn allow_abr_only(mut self) -> Self { + self.default_opts.allow_abr_only = true; + self + } + /// Enable authentication for all requests /// /// Depending on the client type RustyPipe uses either the authentication cookie or the @@ -1780,6 +1798,20 @@ impl RustyPipeQuery { self } + /// Allow fetching player data containing only the ABR (Adaptive bitrate) stream URL. + /// + /// YouTube may return only the ABR stream URL and no URLs for individual streams + /// when using desktop client. To access the streams, your application needs to support + /// the ABR streaming protocol. + /// + /// You also need to set the `allow_abr_only` option for the [`crate::param::StreamFilter`] + /// to select streams without an URL. + #[must_use] + pub fn allow_abr_only(mut self) -> Self { + self.opts.allow_abr_only = true; + self + } + /// Enable authentication for this request /// /// Depending on the client type RustyPipe uses either the authentication cookie or the @@ -2356,6 +2388,7 @@ impl RustyPipeQuery { artist: ctx_src.artist.clone(), authenticated: self.opts.auth.unwrap_or_default(), session_po_token: ctx_src.session_po_token.clone(), + allow_abr_only: self.opts.allow_abr_only, }; let request = self @@ -2647,6 +2680,7 @@ struct MapRespCtx<'a> { artist: Option, authenticated: bool, session_po_token: Option, + allow_abr_only: bool, } /// Options to give to the mapper when making requests; @@ -2675,6 +2709,7 @@ impl<'a> MapRespCtx<'a> { artist: None, authenticated: false, session_po_token: None, + allow_abr_only: false, } } } diff --git a/src/client/player.rs b/src/client/player.rs index 70de86b..a7eb325 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -388,6 +388,24 @@ impl MapResponse for response::Player { ))); } + // Sometimes YouTube Desktop does not output any URLs for adaptive streams. + // Since this is currently rare, it is best to retry the request in this case + // unless ABR streaming is explicitly requested. + if !ctx.allow_abr_only + && !is_live + && !streaming_data.adaptive_formats.c.is_empty() + && streaming_data + .adaptive_formats + .c + .iter() + .all(|f| f.url.is_none() && f.signature_cipher.is_none()) + { + return Err(ExtractionError::Unavailable { + reason: UnavailabilityReason::TryAgain, + msg: "no adaptive stream URLs".to_owned(), + }); + } + let video_info = VideoPlayerDetails { id: video_details.video_id, name: video_details.title, @@ -1013,6 +1031,7 @@ mod tests { artist: None, authenticated: false, session_po_token: None, + allow_abr_only: false, }) .unwrap(); From 43b4f71a1b366e314964a3710fdf743e9cb846ca Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sun, 6 Apr 2025 23:06:57 +0200 Subject: [PATCH 11/21] docs: abr streams now returned with 2% probability --- codegen/src/abtest.rs | 6 +++++- downloader/src/abr2.rs | 4 ++-- notes/AB_Tests.md | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/codegen/src/abtest.rs b/codegen/src/abtest.rs index 8c41913..8c5bd86 100644 --- a/codegen/src/abtest.rs +++ b/codegen/src/abtest.rs @@ -484,6 +484,10 @@ pub async fn command_executor_command(rp: &RustyPipeQuery) -> Result { pub async fn abr_stream_only(rp: &RustyPipeQuery) -> Result { let id = "pxY4OXVyMe4"; - let res = rp.player_from_client(id, ClientType::Desktop).await?; + let res = rp + .clone() + .allow_abr_only() + .player_from_client(id, ClientType::Desktop) + .await?; Ok(res.video_only_streams.iter().all(|s| s.url.is_none())) } diff --git a/downloader/src/abr2.rs b/downloader/src/abr2.rs index b543632..e8a7ba1 100644 --- a/downloader/src/abr2.rs +++ b/downloader/src/abr2.rs @@ -653,7 +653,7 @@ mod tests { #[tokio::test] #[tracing_test::traced_test] async fn experiment() { - let rp = RustyPipe::new(); + let rp = RustyPipe::builder().allow_abr_only().build().unwrap(); let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); let stream_filter = StreamFilter::new() .allow_abr_only() @@ -697,7 +697,7 @@ mod tests { #[tokio::test] #[tracing_test::traced_test] async fn first_header() { - let rp = RustyPipe::new(); + let rp = RustyPipe::builder().allow_abr_only().build().unwrap(); let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); let stream_filter = StreamFilter::new() .allow_abr_only() diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 127721a..59b32bf 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Common (10%) +- **Status:** Experimental (2%) From 86c5bf8ef5896ee8294303e7dc26e64f8629081d Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Fri, 11 Apr 2025 11:52:35 +0200 Subject: [PATCH 12/21] docs: abr streams discontinued --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 59b32bf..e3193d9 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Experimental (2%) +- **Status:** Discontinued (0%) From 5b183f2b74f85caa9d2251b1aa2e05903d4e0c29 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Tue, 15 Apr 2025 19:14:29 +0200 Subject: [PATCH 13/21] docs: abr streams with 8% probability --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index e3193d9..79733e8 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Discontinued (0%) +- **Status:** Common (8%) From 043dc006baba78765a74e13ab459b183a1f4518b Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sat, 26 Apr 2025 00:36:18 +0200 Subject: [PATCH 14/21] docs: abr streams with 25% probability --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 79733e8..5c20ad6 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Common (8%) +- **Status:** Common (25%) From 04a89c815990f26aef9b3d576abfd79e69d321ec Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 28 Apr 2025 14:54:06 +0200 Subject: [PATCH 15/21] docs: abr streams with 12% probability --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index 5c20ad6..f4ac52d 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Common (25%) +- **Status:** Common (12%) From ad75c7172787c814bd06f85ec90069a73835e127 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Tue, 29 Apr 2025 12:46:53 +0200 Subject: [PATCH 16/21] docs: abr streams stabilized --- notes/AB_Tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/AB_Tests.md b/notes/AB_Tests.md index f4ac52d..dd341fa 100644 --- a/notes/AB_Tests.md +++ b/notes/AB_Tests.md @@ -1107,4 +1107,4 @@ YouTube playlists may use a commandExecutorCommand which holds a list of command - **Encountered on:** 16.03.2025 - **Impact:** 🔴 High - **Endpoint:** player (YT) -- **Status:** Common (12%) +- **Status:** Stabilized From c25fa21619fc4c594fe08260aa9526a503bbaa55 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Sat, 17 May 2025 13:05:18 +0200 Subject: [PATCH 17/21] wip --- .gitignore | 4 + abr-proto/build.rs | 1 + .../video_streaming/client_abr_state.proto | 1 + .../reload_player_response.proto | 10 + downloader/Cargo.toml | 6 +- downloader/src/abr2.rs | 190 ++++++++++++------ downloader/src/bin/abrmap.rs | 52 +++++ downloader/src/lib.rs | 3 +- downloader/src/range_predict.rs | 110 ++++++++++ src/client/mod.rs | 35 ---- src/client/player.rs | 131 ++++++------ src/client/response/player.rs | 4 +- src/model/mod.rs | 5 + src/model/ordering.rs | 1 + src/param/stream_filter.rs | 17 +- src/util/mod.rs | 14 +- src/util/protobuf.rs | 89 +++++++- 17 files changed, 506 insertions(+), 167 deletions(-) create mode 100644 abr-proto/proto/video_streaming/reload_player_response.proto create mode 100644 downloader/src/bin/abrmap.rs create mode 100644 downloader/src/range_predict.rs diff --git a/.gitignore b/.gitignore index 3e0f26a..ad20047 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ rustypipe_reports rustypipe_cache*.json bg_snapshot.bin + +*.webm +*.mp4 +*.m4a diff --git a/abr-proto/build.rs b/abr-proto/build.rs index 93174f1..e8f4db2 100644 --- a/abr-proto/build.rs +++ b/abr-proto/build.rs @@ -35,6 +35,7 @@ fn compile() { vsdir.join("playback_cookie.proto"), vsdir.join("playback_start_policy.proto"), vsdir.join("proxy_status.proto"), + vsdir.join("reload_player_response.proto"), vsdir.join("request_cancellation_policy.proto"), vsdir.join("sabr_error.proto"), vsdir.join("sabr_redirect.proto"), diff --git a/abr-proto/proto/video_streaming/client_abr_state.proto b/abr-proto/proto/video_streaming/client_abr_state.proto index 3bd3cfb..dc39dba 100644 --- a/abr-proto/proto/video_streaming/client_abr_state.proto +++ b/abr-proto/proto/video_streaming/client_abr_state.proto @@ -40,4 +40,5 @@ message ClientAbrState { optional int32 sabr_force_proxima = 66; optional int32 Tqb = 67; optional int64 sabr_force_max_network_interruption_duration_ms = 68; + optional string audio_track_id = 69; } diff --git a/abr-proto/proto/video_streaming/reload_player_response.proto b/abr-proto/proto/video_streaming/reload_player_response.proto new file mode 100644 index 0000000..27937c7 --- /dev/null +++ b/abr-proto/proto/video_streaming/reload_player_response.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +package video_streaming; + +message ReloadPlaybackParams { + optional string token = 1; +} + +message ReloadPlayerResponse { + optional ReloadPlaybackParams reload_playback_params = 1; +} diff --git a/downloader/Cargo.toml b/downloader/Cargo.toml index 67c60eb..bd0b0f7 100644 --- a/downloader/Cargo.toml +++ b/downloader/Cargo.toml @@ -41,7 +41,7 @@ thiserror.workspace = true futures-util.workspace = true reqwest = { workspace = true, features = ["stream"] } rand.workspace = true -tokio = { workspace = true, features = ["macros", "fs", "process"] } +tokio = { workspace = true, features = ["macros", "fs", "process", "rt-multi-thread"] } indicatif = { workspace = true, optional = true } filenamify.workspace = true tracing.workspace = true @@ -60,6 +60,10 @@ byteorder = "1.0.0" async-stream = "0.3.6" pin-project-lite = "0.2.11" +serde.workspace = true +serde_json.workspace = true +tracing-subscriber.workspace = true + [dev-dependencies] path_macro.workspace = true rstest.workspace = true diff --git a/downloader/src/abr2.rs b/downloader/src/abr2.rs index e8a7ba1..0c78c4c 100644 --- a/downloader/src/abr2.rs +++ b/downloader/src/abr2.rs @@ -1,7 +1,9 @@ -#![allow(unused)] +#![allow(unused, missing_docs)] use std::{ collections::{HashMap, HashSet}, + fs::File, + io::Write, marker::PhantomData, pin::Pin, task::{ready, Poll}, @@ -22,13 +24,14 @@ use rustypipe_abr_proto::{ media_header::MediaHeader, next_request_policy::NextRequestPolicy, playback_cookie::PlaybackCookie, + reload_player_response::ReloadPlayerResponse, sabr_error::SabrError, sabr_redirect::SabrRedirect, stream_protection_status::StreamProtectionStatus, streamer_context::{streamer_context::ClientInfo, StreamerContext}, - time_range::TimeRange, video_playback_abr_request::VideoPlaybackAbrRequest, }; +use serde::{Deserialize, Serialize}; use crate::{abr_model::PartType, error::AbrError, util::BytesBuffer}; @@ -51,27 +54,28 @@ pub struct AbrStream { #[derive(Default, Clone)] pub struct AbrStreamOptions<'a> { - http: Client, - url: String, - ustreamer_config: &'a str, - po_token: Option<&'a str>, - audio_streams: &'a [&'a AudioStream], - video_streams: &'a [&'a VideoStream], - abr_state: ClientAbrState, + pub http: Client, + pub url: String, + pub ustreamer_config: &'a str, + pub po_token: Option<&'a str>, + pub audio_streams: &'a [&'a AudioStream], + pub video_streams: &'a [&'a VideoStream], + pub player_time: i64, + pub abr_state: ClientAbrState, } #[derive(Debug, Clone)] pub struct AbrStreamItem { - format: FormatInfo, - data: Bytes, + pub format: FormatInfo, + pub data: Bytes, } #[derive(Debug, Clone)] pub struct FormatInfo { - itag: i32, - last_modified: u64, - xtags: Option, - mime_type: Option, + pub itag: i32, + pub last_modified: u64, + pub xtags: Option, + pub mime_type: Option, } #[derive(Debug)] @@ -81,20 +85,29 @@ struct InitializedFormat { mime_type: Option, sequence_count: Option, sequence_list: Vec, + sequence_list2: Vec, state: BufferedRange, } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize)] struct Sequence { - itag: Option, - format_id: FormatId, - is_init_segment: bool, - duration_ms: Option, - start_ms: Option, - start_data_range: Option, - sequence_number: Option, - content_length: Option, - time_range: Option, + pub itag: Option, + #[serde(skip)] + pub format_id: FormatId, + pub is_init_segment: bool, + pub duration_ms: Option, + pub start_ms: Option, + pub start_data_range: Option, + pub sequence_number: Option, + pub content_length: Option, + pub time_range: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct TimeRange { + pub start: i64, + pub duration: i64, + pub timescale: i32, } #[derive(Debug, Clone)] @@ -138,7 +151,7 @@ impl AbrStream { abr_state.set_time_since_last_manual_format_selection_ms(0); } if !abr_state.has_player_time_ms() { - abr_state.set_player_time_ms(0); + abr_state.set_player_time_ms(options.player_time); } if !abr_state.has_visibility() { abr_state.set_visibility(0); @@ -146,6 +159,12 @@ impl AbrStream { if !abr_state.has_enabled_track_types_bitfield() { abr_state.set_enabled_track_types_bitfield(i32::from(options.video_streams.is_empty())); } + if !abr_state.has_audio_track_id() { + if let Some(audio_track) = options.audio_streams.first().and_then(|s| s.track.as_ref()) + { + abr_state.set_audio_track_id(audio_track.id.to_owned()); + } + } if let Some(v) = options.video_streams.first() { if !abr_state.has_last_manual_selected_resolution() { abr_state.set_last_manual_selected_resolution(v.height as i32); @@ -154,6 +173,11 @@ impl AbrStream { abr_state.set_sticky_resolution(v.height as i32); } } + if !abr_state.has_drc_enabled() { + if let Some(audio) = options.audio_streams.first() { + abr_state.set_drc_enabled(audio.is_drc); + } + } let audio_format_ids = options .audio_streams @@ -281,6 +305,7 @@ impl AbrStream { self.process_media_data().map(|x| (x, true)) } else if self.buffer.remaining() < hsize { // Wait for the entire part to be downloaded + tracing::info!("waiting for entire part"); Ok((None, true)) } else { let part_data = self.buffer.copy_to_bytes(hsize); @@ -290,6 +315,7 @@ impl AbrStream { PartType::NEXT_REQUEST_POLICY => { self.process_next_request_policy(&part_data)? } + PartType::RELOAD_PLAYER_RESPONSE => self.process_reload_player(&part_data)?, PartType::FORMAT_INITIALIZATION_METADATA => { self.process_format_initialization(&part_data)? } @@ -359,6 +385,7 @@ impl AbrStream { .iter() .all(|x| x.sequence_number != Some(mh.sequence_number())) { + let tr = mh.time_range.as_ref(); let seq = Sequence { itag: mh.itag, format_id: format_id.clone(), @@ -368,16 +395,36 @@ impl AbrStream { start_data_range: mh.start_data_range, sequence_number: mh.sequence_number, content_length: mh.content_length, - time_range: mh.time_range.as_ref().cloned(), + time_range: tr.and_then(|tr| { + tr.start.zip(tr.duration).zip(tr.timescale).map( + |((start, duration), timescale)| TimeRange { + start, + duration, + timescale, + }, + ) + }), }; - dbg!(&seq); - if mh.itag == Some(251) { - tracing::debug!( - "audio #{}: {}", - seq.sequence_number.unwrap_or_default(), - seq.content_length.unwrap_or_default() - ); - } + + // TODO: testing + let sname = if mh.itag == Some(251) { + "audio" + } else { + "video" + }; + tracing::debug!( + "{sname} #{}: content_length={} start_data_range={} time_start={} time_duration={}", + seq.sequence_number.unwrap_or_default(), + seq.content_length.unwrap_or_default(), + seq.start_data_range.unwrap_or_default(), + seq.time_range.as_ref().map(|t| t.start).unwrap_or_default(), + seq.time_range + .as_ref() + .map(|t| t.duration) + .unwrap_or_default(), + ); + + current_format.sequence_list2.push(seq.clone()); current_format.sequence_list.push(seq); if mh.has_sequence_number() { @@ -439,11 +486,18 @@ impl AbrStream { fn process_next_request_policy(&mut self, data: &[u8]) -> Result<(), AbrError> { let mut policy = NextRequestPolicy::parse_from_bytes(data)?; + tracing::debug!("NextRequestPolicy {policy:?}"); self.playback_cookie = policy.playback_cookie.take(); self.backoff_time_ms = policy.backoff_time_ms(); Ok(()) } + fn process_reload_player(&mut self, data: &[u8]) -> Result<(), AbrError> { + let mut reload = ReloadPlayerResponse::parse_from_bytes(data)?; + tracing::debug!("ReloadPlayerResponse {reload:?}"); + Ok(()) + } + fn process_format_initialization(&mut self, data: &[u8]) -> Result<(), AbrError> { let init = FormatInitializationMetadata::parse_from_bytes(data)?; let format = InitializedFormat::try_from(init)?; @@ -472,7 +526,22 @@ impl AbrStream { .or(self.formats_by_key.values().next()) } + /// A stream is done if all sequences from all formats were received or the last request did not contain any sequences + fn is_done(&self) -> bool { + self.formats_by_key.values().all(|f| { + f.sequence_list.is_empty() + || f.sequence_count + .zip(f.sequence_list.last()) + .map(|(sc, last)| last.sequence_number == Some(sc.into())) + .unwrap_or_default() + }) + } + async fn fetch_stream_data(&self) -> Result { + tracing::debug!( + "fetching stream data: {}ms", + self.abr_state.player_time_ms() + ); let body = VideoPlaybackAbrRequest { client_abr_state: MessageField::some(self.abr_state.clone()), selected_format_ids: self @@ -514,7 +583,7 @@ impl AbrStream { Ok(resp) } - fn stream(mut self) -> impl Stream> { + pub fn stream(mut self) -> impl Stream> { let stream = try_stream! { let mut ri = 1; loop { @@ -549,25 +618,23 @@ impl AbrStream { } tracing::debug!("request #{ri} fetched {page_len} bytes"); - let main_format = self.main_format().ok_or(AbrError::Invalid("no main format".into()))?; + let main_format = self.main_format().ok_or(AbrError::Invalid(format!("no main format: {:?}", self.formats_by_key.values()).into()))?; let player_time = self.abr_state.player_time_ms() + main_format.sequence_list.iter().fold(0, |acc, seq| { acc + i64::from(seq.duration_ms.unwrap_or_default()) }); - let is_last = main_format - .sequence_count - .zip(main_format.sequence_list.last()) - .map(|(sc, last)| last.sequence_number == Some(sc.into())) - .unwrap_or_default(); - tracing::debug!("player time: {player_time}; sequence_count={}, last={}", main_format.sequence_count.unwrap_or_default(), main_format - .sequence_list - .last() - .and_then(|x| x.sequence_number).unwrap_or_default()); - self.abr_state.set_player_time_ms(player_time); - if is_last { + + tracing::debug!( + "player time: {player_time}; sequence_count={}, last={:?}", + main_format.sequence_count.unwrap_or_default(), + main_format.sequence_list.last().and_then(|x| x.sequence_number), + ); + if self.is_done() { break; } + self.abr_state.set_player_time_ms(player_time); + if self.backoff_time_ms > 0 { tracing::debug!("backoff: {} ms", self.backoff_time_ms); tokio::time::sleep(std::time::Duration::from_millis( @@ -578,6 +645,12 @@ impl AbrStream { ri += 1; } + + // DEBUG: + // for f in self.formats_by_key.values() { + // let mut of = File::create(format!("/home/thetadev/Documents/Programmieren/Rust/rustypipe/tmp/abrmap/{}_{}.json", std::env::args().into_iter().nth(1).unwrap(), f.format_id.itag())).unwrap(); + // serde_json::to_writer(of, &f.sequence_list2).unwrap(); + // } }; Box::pin(stream) } @@ -601,6 +674,7 @@ impl TryFrom<&MediaHeader> for InitializedFormat { mime_type: None, sequence_count: None, sequence_list: Vec::new(), + sequence_list2: Vec::new(), state: BufferedRange { format_id: MessageField::some(format_id.clone()), start_time_ms: Some(0), @@ -626,6 +700,7 @@ impl TryFrom for InitializedFormat { mime_type: value.mime_type.clone(), sequence_count: value.sequence_count, sequence_list: Vec::new(), + sequence_list2: Vec::new(), state: BufferedRange { format_id: MessageField::some(format_id), start_time_ms: Some(0), @@ -653,15 +728,15 @@ mod tests { #[tokio::test] #[tracing_test::traced_test] async fn experiment() { - let rp = RustyPipe::builder().allow_abr_only().build().unwrap(); - let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); + let rp = RustyPipe::builder().build().unwrap(); + let player = rp.query().player("ZeerrnuLi5E").await.unwrap(); let stream_filter = StreamFilter::new() .allow_abr_only() - // .video_max_res(360) + .video_max_res(360) .video_formats([VideoFormat::Webm]) .audio_codecs([AudioCodec::Opus]); let (video, audio) = player.select_video_audio_stream(&stream_filter); - // let video = video.unwrap(); + let video = video.unwrap(); let audio = audio.unwrap(); let mut abr = AbrStream::new(AbrStreamOptions { @@ -671,6 +746,7 @@ mod tests { audio_streams: &[audio], // video_streams: &[video], video_streams: &[], + player_time: 10584, ..Default::default() }) .unwrap(); @@ -697,15 +773,15 @@ mod tests { #[tokio::test] #[tracing_test::traced_test] async fn first_header() { - let rp = RustyPipe::builder().allow_abr_only().build().unwrap(); - let player = rp.query().player("pxY4OXVyMe4").await.unwrap(); + let rp = RustyPipe::builder().build().unwrap(); + let player = rp.query().player("8AeOP8u89iE").await.unwrap(); let stream_filter = StreamFilter::new() .allow_abr_only() // .video_max_res(360) .video_formats([VideoFormat::Webm]) .audio_codecs([AudioCodec::Opus]); let (video, audio) = player.select_video_audio_stream(&stream_filter); - // let video = video.unwrap(); + let video = video.unwrap(); let audio = audio.unwrap(); let mut abr = AbrStream::new(AbrStreamOptions { @@ -713,8 +789,8 @@ mod tests { ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), po_token: player.po_token.as_deref(), audio_streams: &[audio], - // video_streams: &[video], - video_streams: &[], + video_streams: &[video], + // video_streams: &[], ..Default::default() }) .unwrap(); diff --git a/downloader/src/bin/abrmap.rs b/downloader/src/bin/abrmap.rs new file mode 100644 index 0000000..02d9047 --- /dev/null +++ b/downloader/src/bin/abrmap.rs @@ -0,0 +1,52 @@ +use futures_util::TryStreamExt; +use rustypipe::{ + client::RustyPipe, + model::{AudioCodec, VideoFormat}, + param::StreamFilter, +}; +use rustypipe_downloader::abr2::{AbrStream, AbrStreamOptions}; + +#[tokio::main] +async fn main() { + tracing_subscriber::fmt::init(); + + let id = std::env::args().into_iter().nth(1).unwrap(); + + let rp = RustyPipe::builder().build().unwrap(); + let player = rp + .query() + .visitor_data("Cgt0SlJzQllxNFhuMCjZ1Z3BBjIKCgJERRIEEgAgXg%3D%3D") + .player_from_client(id, rustypipe::client::ClientType::Desktop) + .await + .unwrap(); + assert_eq!(player.client_type, rustypipe::client::ClientType::Desktop); + + let stream_filter = StreamFilter::new() + .allow_abr_only() + .video_max_res(360) + .video_formats([VideoFormat::Webm]) + .audio_codecs([AudioCodec::Opus]); + let (video, audio) = player.select_video_audio_stream(&stream_filter); + let video = video.unwrap(); + let audio = audio.unwrap(); + + dbg!(&audio); + + let abr = AbrStream::new(AbrStreamOptions { + url: player.abr_streaming_url.clone().unwrap(), + ustreamer_config: player.abr_ustreamer_config.as_deref().unwrap(), + po_token: player.po_token.as_deref(), + audio_streams: &[audio], + video_streams: &[video], + // video_streams: &[], + ..Default::default() + }) + .unwrap(); + + { + let mut stream = abr.stream(); + while let Some(itm) = stream.try_next().await.unwrap() { + println!("got {} bytes", itm.data.len()); + } + } +} diff --git a/downloader/src/lib.rs b/downloader/src/lib.rs index f78df7d..35024bc 100644 --- a/downloader/src/lib.rs +++ b/downloader/src/lib.rs @@ -3,9 +3,10 @@ #![warn(missing_docs, clippy::todo, clippy::dbg_macro)] mod abr; -mod abr2; +pub mod abr2; mod abr_model; mod error; +mod range_predict; mod streamtest; mod util; diff --git a/downloader/src/range_predict.rs b/downloader/src/range_predict.rs new file mode 100644 index 0000000..a071fd1 --- /dev/null +++ b/downloader/src/range_predict.rs @@ -0,0 +1,110 @@ +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; + +use crate::abr2::TimeRange; + +struct Sx { + stream_len: i64, + header_len: i64, + duration: i64, + positions: BTreeMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct Sequence { + pub itag: i32, + pub is_init_segment: bool, + pub duration_ms: Option, + pub start_ms: Option, + pub start_data_range: i32, + pub sequence_number: Option, + pub content_length: i64, + pub time_range: Option, +} + +impl Sx { + fn new(stream_len: i64, header_len: i64, duration: i64) -> Self { + let mut positions = BTreeMap::new(); + positions.insert(header_len, 0); + positions.insert(stream_len - 1, duration); + + Self { + stream_len, + header_len, + duration, + positions, + } + } + + fn pos_predict(&self, pos: i64) -> i64 { + if pos < self.header_len { + return 0; + } + if pos >= self.stream_len { + panic!("out of range"); + } + + let blow = *self.positions.keys().rev().find(|x| **x <= pos).unwrap(); + let bhigh = *self.positions.keys().find(|x| **x >= pos).unwrap(); + let brange = bhigh - blow; + let bperc = pos as f64 / brange as f64; + + let tlow = self.positions[&blow]; + let thigh = self.positions[&bhigh]; + let trange = thigh - tlow; + + let tpoint = (trange as f64 * bperc) as i64 + tlow; + (tpoint - 5000).max(tlow) + } +} + +#[cfg(test)] +mod tests { + use std::{fs::File, io::BufReader}; + + use super::{Sequence, Sx}; + + fn fetch_seg(sequences: &[Sequence], ts: i64) -> &Sequence { + if ts <= 10000 { + &sequences[0] + } else { + sequences + .iter() + .rev() + .find(|s| s.time_range.as_ref().is_some_and(|t| t.start <= ts)) + .unwrap() + } + } + + #[test] + fn t_range_predict() { + let f = File::open( + "/home/thetadev/Documents/Programmieren/Rust/rustypipe/tmp/abrmap/HSkTpseMd-A_251_nodrc.json", + ) + .unwrap(); + let sequences: Vec = serde_json::from_reader(BufReader::new(f)).unwrap(); + let last = sequences.last().unwrap(); + let stream_len = i64::from(last.start_data_range) + last.content_length; + let header_len = sequences[0].content_length; + let ltr = last.time_range.as_ref().unwrap(); + let duration = ltr.start + ltr.duration; + + let sx = Sx::new(stream_len, header_len, duration); + + let max_sl = sequences.iter().map(|s| s.content_length).max().unwrap(); + + for offset in (0..stream_len).step_by(1000) { + let pred = sx.pos_predict(offset); + let s = fetch_seg(&sequences, pred); + let to_skip = offset - i64::from(s.start_data_range); + if to_skip < 0 { + println!("after target ({to_skip}): offset={offset} pred={pred} s={s:?}"); + } else if to_skip <= max_sl { + println!("on target ({to_skip})"); + } else { + println!("before target ({to_skip})"); + } + } + } +} diff --git a/src/client/mod.rs b/src/client/mod.rs index 4f0d792..06386bc 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -400,7 +400,6 @@ struct RustyPipeOpts { utc_offset_minutes: i16, report: bool, strict: bool, - allow_abr_only: bool, auth: Option, visitor_data: Option, } @@ -557,7 +556,6 @@ impl Default for RustyPipeOpts { utc_offset_minutes: 0, report: false, strict: false, - allow_abr_only: false, auth: None, visitor_data: None, } @@ -964,22 +962,6 @@ impl RustyPipeBuilder { self } - /// Allow fetching player data containing only the ABR (Adaptive bitrate) stream URL. - /// - /// YouTube may return only the ABR stream URL and no URLs for individual streams - /// when using desktop client. To access the streams, your application needs to support - /// the ABR streaming protocol. - /// - /// You also need to set the `allow_abr_only` option for the [`crate::param::StreamFilter`] - /// to select streams without an URL. - /// - /// **Info**: you can set this option for individual queries, too - #[must_use] - pub fn allow_abr_only(mut self) -> Self { - self.default_opts.allow_abr_only = true; - self - } - /// Enable authentication for all requests /// /// Depending on the client type RustyPipe uses either the authentication cookie or the @@ -1798,20 +1780,6 @@ impl RustyPipeQuery { self } - /// Allow fetching player data containing only the ABR (Adaptive bitrate) stream URL. - /// - /// YouTube may return only the ABR stream URL and no URLs for individual streams - /// when using desktop client. To access the streams, your application needs to support - /// the ABR streaming protocol. - /// - /// You also need to set the `allow_abr_only` option for the [`crate::param::StreamFilter`] - /// to select streams without an URL. - #[must_use] - pub fn allow_abr_only(mut self) -> Self { - self.opts.allow_abr_only = true; - self - } - /// Enable authentication for this request /// /// Depending on the client type RustyPipe uses either the authentication cookie or the @@ -2388,7 +2356,6 @@ impl RustyPipeQuery { artist: ctx_src.artist.clone(), authenticated: self.opts.auth.unwrap_or_default(), session_po_token: ctx_src.session_po_token.clone(), - allow_abr_only: self.opts.allow_abr_only, }; let request = self @@ -2680,7 +2647,6 @@ struct MapRespCtx<'a> { artist: Option, authenticated: bool, session_po_token: Option, - allow_abr_only: bool, } /// Options to give to the mapper when making requests; @@ -2709,7 +2675,6 @@ impl<'a> MapRespCtx<'a> { artist: None, authenticated: false, session_po_token: None, - allow_abr_only: false, } } } diff --git a/src/client/player.rs b/src/client/player.rs index a7eb325..760e820 100644 --- a/src/client/player.rs +++ b/src/client/player.rs @@ -50,15 +50,33 @@ struct QPlayer<'a> { #[serde(rename_all = "camelCase")] struct QPlaybackContext<'a> { content_playback_context: QContentPlaybackContext<'a>, + device_playback_capabilities: QDevicePlaybackCapabilities, } #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct QContentPlaybackContext<'a> { - /// Signature timestamp extracted from player.js - signature_timestamp: &'a str, + auto_captions_default_on: bool, + autonav_state: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + current_url: Option, + html5_preference: &'a str, + lact_milliseconds: i8, /// Referer URL from website referer: String, + /// Signature timestamp extracted from player.js + signature_timestamp: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + splay: Option, + #[serde(skip_serializing_if = "Option::is_none")] + vis: Option, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct QDevicePlaybackCapabilities { + supports_vp9_encoding: bool, + support_xhr: bool, } #[derive(Debug, Serialize)] @@ -210,8 +228,27 @@ impl RustyPipeQuery { let playback_context = deobf.as_ref().map(|deobf| QPlaybackContext { content_playback_context: QContentPlaybackContext { - signature_timestamp: &deobf.sts, + auto_captions_default_on: false, + autonav_state: "STATE_OFF", + current_url: if client_type == ClientType::Tv { + None + } else { + Some(format!("/watch?v={video_id}")) + }, + html5_preference: "HTML5_PREF_WANTS", + lact_milliseconds: if client_type == ClientType::Tv { + 10 + } else { + -1 + }, referer: format!("https://www.youtube.com/watch?v={video_id}"), + signature_timestamp: &deobf.sts, + splay: Some(false).filter(|_| client_type != ClientType::Tv), + vis: Some(0).filter(|_| client_type != ClientType::Tv), + }, + device_playback_capabilities: QDevicePlaybackCapabilities { + supports_vp9_encoding: true, + support_xhr: true, }, }); @@ -388,24 +425,6 @@ impl MapResponse for response::Player { ))); } - // Sometimes YouTube Desktop does not output any URLs for adaptive streams. - // Since this is currently rare, it is best to retry the request in this case - // unless ABR streaming is explicitly requested. - if !ctx.allow_abr_only - && !is_live - && !streaming_data.adaptive_formats.c.is_empty() - && streaming_data - .adaptive_formats - .c - .iter() - .all(|f| f.url.is_none() && f.signature_cipher.is_none()) - { - return Err(ExtractionError::Unavailable { - reason: UnavailabilityReason::TryAgain, - msg: "no adaptive stream URLs".to_owned(), - }); - } - let video_info = VideoPlayerDetails { id: video_details.video_id, name: video_details.title, @@ -718,7 +737,7 @@ impl<'a> StreamsMapper<'a> { &mut self, url: &Option, signature_cipher: &Option, - ) -> Result { + ) -> Result, ExtractionError> { let (url_base, mut url_params) = match url { Some(url) => util::url_to_params(url).map_err(|_| { @@ -733,7 +752,7 @@ impl<'a> StreamsMapper<'a> { ) }) } - None => return Ok(UrlMapRes::default()), + None => return Ok(None), }, }?; @@ -745,10 +764,7 @@ impl<'a> StreamsMapper<'a> { let url = Url::parse_with_params(url_base.as_str(), url_params.iter()) .map_err(|_| ExtractionError::InvalidData("could not combine URL".into()))?; - Ok(UrlMapRes { - url: Some(url.to_string()), - xtags: url_params.get("xtags").cloned(), - }) + Ok(Some(url.to_string())) } fn map_url_abr(&mut self, url: &str) -> Result { @@ -776,10 +792,9 @@ impl<'a> StreamsMapper<'a> { format!("invalid video format. itag: {}", f.itag).into(), )); }; - let map_res = self.map_url(&f.url, &f.signature_cipher)?; Ok(VideoStream { - url: map_res.url, + url: self.map_url(&f.url, &f.signature_cipher)?, itag: f.itag, bitrate: f.bitrate, average_bitrate: f.average_bitrate.unwrap_or(f.bitrate), @@ -799,7 +814,7 @@ impl<'a> StreamsMapper<'a> { format, codec: get_video_codec(codecs), mime: f.mime_type, - xtags: map_res.xtags, + xtags: f.xtags, drm_track_type: f.drm_track_type.map(|t| t.into()), drm_systems: f.drm_families.into_iter().map(|t| t.into()).collect(), }) @@ -818,10 +833,9 @@ impl<'a> StreamsMapper<'a> { let format = get_audio_format(mtype).ok_or_else(|| { ExtractionError::InvalidData(format!("invalid audio format. itag: {}", f.itag).into()) })?; - let map_res = self.map_url(&f.url, &f.signature_cipher)?; Ok(AudioStream { - url: map_res.url, + url: self.map_url(&f.url, &f.signature_cipher)?, itag: f.itag, bitrate: f.bitrate, average_bitrate: f.average_bitrate.unwrap_or(f.bitrate), @@ -839,10 +853,11 @@ impl<'a> StreamsMapper<'a> { mime: f.mime_type, channels: f.audio_channels, loudness_db: f.loudness_db, + is_drc: f.is_drc, track: f .audio_track - .map(|t| self.map_audio_track(t, map_res.xtags.as_deref())), - xtags: map_res.xtags, + .map(|t| self.map_audio_track(t, f.xtags.as_deref())), + xtags: f.xtags, drm_track_type: f.drm_track_type.map(|t| t.into()), drm_systems: f.drm_families.into_iter().map(|t| t.into()).collect(), }) @@ -857,24 +872,30 @@ impl<'a> StreamsMapper<'a> { let mut track_type = None; if let Some(xtags) = xtags { - xtags - .split(':') - .filter_map(|param| param.split_once('=')) - .for_each(|(k, v)| match k { - "lang" => { - lang = Some(v.to_owned()); + let xtags_data = urlencoding::decode(xtags) + .ok() + .and_then(|dec| util::b64_decode(dec.as_bytes()).ok()) + .and_then(|bts| util::kv_from_pb(bts)); + + match xtags_data { + Some(mut xtags_data) => { + if let Some(acont) = xtags_data.get("acont") { + match serde_plain::from_str(&acont) { + Ok(v) => { + track_type = Some(v); + } + Err(_) => { + self.warnings + .push(format!("could not parse audio track type `{acont}`")); + } + } } - "acont" => match serde_plain::from_str(v) { - Ok(v) => { - track_type = Some(v); - } - Err(_) => { - self.warnings - .push(format!("could not parse audio track type `{v}`")); - } - }, - _ => {} - }); + lang = xtags_data.remove("lang"); + } + None => self + .warnings + .push(format!("could not parse xtags `{xtags}`")), + } } AudioTrack { @@ -887,12 +908,6 @@ impl<'a> StreamsMapper<'a> { } } -#[derive(Default)] -struct UrlMapRes { - url: Option, - xtags: Option, -} - fn parse_mime(mime: &str) -> Option<(&str, Vec<&str>)> { static PATTERN: Lazy = Lazy::new(|| Regex::new(r#"(\w+/\w+);\scodecs="([a-zA-Z-0-9.,\s]*)""#).unwrap()); @@ -1031,7 +1046,6 @@ mod tests { artist: None, authenticated: false, session_po_token: None, - allow_abr_only: false, }) .unwrap(); @@ -1052,7 +1066,6 @@ mod tests { let url = mapper .map_url(&None, &Some(signature_cipher.to_owned())) .unwrap() - .url .unwrap(); assert_eq!(url, "https://rr5---sn-h0jelnez.googlevideo.com/videoplayback?c=WEB&clen=3781277&dur=229.301&ei=vb7nYvH5BMK8gAfBj7ToBQ&expire=1659376413&fexp=24001373%2C24007246&fvip=5&gir=yes&id=o-AB_BABwrXZJN428ZwDxq5ScPn2AbcGODnRlTVhCQ3mj2&initcwndbps=1588750&ip=2003%3Ade%3Aaf06%3A6300%3Ac750%3A1b77%3Ac74a%3A80e3&itag=251&keepalive=yes&lmt=1655510291473933&lsig=AG3C_xAwRQIgCKCGJ1iu4wlaGXy3jcJyU3inh9dr1FIfqYOZEG_MdmACIQCbungkQYFk7EhD6K2YvLaHFMjKOFWjw001_tLb0lPDtg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&mh=hH&mime=audio%2Fwebm&mm=31%2C26&mn=sn-h0jelnez%2Csn-4g5ednsl&ms=au%2Conr&mt=1659354538&mv=m&mvi=5&n=XzXGSfGusw6OCQ&ns=b_Mq_qlTFcSGlG9RpwpM9xQH&pl=37&rbqsm=fr&requiressl=yes&sig=AOq0QJ8wRQIhAPIsKd7-xi4xVHEC9gb__dU4hzfzsHEj9ytd3nt0gEceAiACJWBcw-wFEq9qir35bwKHJZxtQ9mOL7SKiVkLQNDa6A%3D%3D&source=youtube&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cspc%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&spc=lT-Khi831z8dTejFIRCvCEwx_6romtM&txp=4532434&vprv=1"); diff --git a/src/client/response/player.rs b/src/client/response/player.rs index 2cb460f..491779d 100644 --- a/src/client/response/player.rs +++ b/src/client/response/player.rs @@ -114,8 +114,8 @@ pub(crate) struct Format { pub last_modified: Option, #[serde_as(as = "Option")] pub content_length: Option, - pub bitrate: u32, + pub xtags: Option, pub width: Option, pub height: Option, @@ -143,6 +143,8 @@ pub(crate) struct Format { pub audio_sample_rate: Option, pub audio_channels: Option, pub loudness_db: Option, + #[serde(default)] + pub is_drc: bool, pub audio_track: Option, pub signature_cipher: Option, diff --git a/src/model/mod.rs b/src/model/mod.rs index f97090c..b6f7ef8 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -288,6 +288,11 @@ pub struct AudioStream { /// /// The loudness parameter is not available when using the Android client. pub loudness_db: Option, + /// True if the audio stream uses dynamic range compression (Stable Volume option) + /// + /// + /// + pub is_drc: bool, /// Audio track information /// /// Videos can have multiple audio tracks (different languages). diff --git a/src/model/ordering.rs b/src/model/ordering.rs index 445dcad..8fe8718 100644 --- a/src/model/ordering.rs +++ b/src/model/ordering.rs @@ -36,6 +36,7 @@ impl QualityOrd for AudioStream { .as_ref() .map(|t| track_type_rating(t.track_type)), ) + .then_with(|| other.is_drc.cmp(&self.is_drc)) .then_with(|| self.channels.cmp(&other.channels)) .then_with(|| cmp_bitrate(self).cmp(&cmp_bitrate(other))) } diff --git a/src/param/stream_filter.rs b/src/param/stream_filter.rs index 537c490..5143b1f 100644 --- a/src/param/stream_filter.rs +++ b/src/param/stream_filter.rs @@ -17,6 +17,7 @@ pub struct StreamFilter { audio_languages: Vec, audio_autodub: bool, audio_descriptive: bool, + audio_drc: bool, video_max_res: Option, video_max_fps: Option, video_formats: Option>, @@ -28,7 +29,7 @@ pub struct StreamFilter { drm_system: Option, } -const N_RES_AUDIO: usize = 4; +const N_RES_AUDIO: usize = 5; const N_RES_VIDEO: usize = 5; type AudioRes = Option<[i64; N_RES_AUDIO]>; type VideoRes = Option<[i64; N_RES_VIDEO]>; @@ -110,6 +111,16 @@ impl StreamFilter { self } + /// Prefer audio streams that use dynamic range compression (Stable volume). + /// + /// + /// + #[must_use] + pub fn audio_drc(mut self) -> Self { + self.audio_drc = true; + self + } + /// Set the maximum video resolution. Resolution is determined by the /// pixel count of the shorter edge (e.g. 1080p). /// @@ -271,6 +282,8 @@ impl StreamFilter { None => 0, }; + let drc = i64::from(self.audio_drc == stream.is_drc); + let channels = stream.channels.unwrap_or_default(); if let Some(max_channels) = self.audio_max_channels { if channels > max_channels { @@ -280,7 +293,7 @@ impl StreamFilter { self.check_drm(stream.drm_track_type, &stream.drm_systems)?; - Some([language, track_type, channels.into(), bitrate]) + Some([language, track_type, drc, channels.into(), bitrate]) } fn apply_video(&self, stream: &VideoStream, video_only: bool) -> VideoRes { diff --git a/src/util/mod.rs b/src/util/mod.rs index 368d114..9e54eec 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -6,7 +6,7 @@ pub mod dictionary; pub mod timeago; pub use date::{now_sec, shift_months, shift_weeks_monday, shift_years}; -pub use protobuf::{string_from_pb, ProtoBuilder}; +pub use protobuf::{kv_from_pb, string_from_pb, ProtoBuilder}; pub use visitor_data::VisitorDataCache; use std::{ @@ -486,7 +486,17 @@ pub fn b64_encode>(input: T) -> String { } pub fn b64_decode>(input: T) -> Result, data_encoding::DecodeError> { - data_encoding::BASE64URL.decode(input.as_ref()) + // Remove trailing padding + let mut x = input.as_ref(); + while !x.is_empty() { + let li = x.len() - 1; + if x[li] == b'=' { + x = &x[0..li]; + } else { + break; + } + } + data_encoding::BASE64URL_NOPAD.decode(x) } /// Get the country from its English name diff --git a/src/util/protobuf.rs b/src/util/protobuf.rs index 84492f6..b56dae9 100644 --- a/src/util/protobuf.rs +++ b/src/util/protobuf.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + /// [`ProtoBuilder`] is used to construct protobuf messages using a builder pattern #[derive(Debug, Default)] pub struct ProtoBuilder { @@ -100,7 +102,7 @@ fn parse_varint>(pb: &mut P) -> Option { } } -fn parse_field>(pb: &mut P) -> Option<(u32, u8)> { +fn parse_field(pb: &mut impl Iterator) -> Option<(u32, u8)> { parse_varint(pb).map(|v| { let f = (v >> 3) as u32; let w = (v & 0x07) as u8; @@ -108,13 +110,12 @@ fn parse_field>(pb: &mut P) -> Option<(u32, u8)> { }) } -pub fn string_from_pb>(pb: P, field: u32) -> Option { - let mut pb = pb.into_iter(); - while let Some((this_field, wire)) = parse_field(&mut pb) { +fn next_string_from_pb(pb: &mut impl Iterator, filter: &[u32]) -> Option<(u32, String)> { + while let Some((this_field, wire)) = parse_field(pb) { let to_skip = match wire { // varint 0 => { - parse_varint(&mut pb); + parse_varint(pb); 0 } // fixed 64bit @@ -123,15 +124,16 @@ pub fn string_from_pb>(pb: P, field: u32) -> Option 4, // string 2 => { - let len = parse_varint(&mut pb)?; - if this_field == field { + let len = parse_varint(pb)?; + if filter.contains(&this_field) { let mut buf = Vec::new(); for _ in 0..len { buf.push(pb.next()?); } - return String::from_utf8(buf).ok(); + return Some((this_field, String::from_utf8(buf).ok()?)); + } else { + len } - len } _ => return None, }; @@ -142,6 +144,64 @@ pub fn string_from_pb>(pb: P, field: u32) -> Option>(pb: P, field: u32) -> Option { + let mut pb = pb.into_iter(); + next_string_from_pb(&mut pb, &[field]).map(|x| x.1) +} + +/// Parse a protobuf-encoded key/value map +/// +/// K/V pairs are embedded structs of field 1 +/// K/V struct: {key = 1; value = 2} +pub fn kv_from_pb>(pb: P) -> Option> { + let mut res = HashMap::new(); + let pb = &mut (pb.into_iter()); + while let Some((this_field, wire)) = parse_field(pb) { + let to_skip = match wire { + // varint + 0 => { + parse_varint(pb); + 0 + } + // fixed 64bit + 1 => 8, + // fixed 32bit + 5 => 4, + // embed + 2 => { + let len = parse_varint(pb)?; + if this_field == 1 { + let mut tsh = pb.take(len as usize); + let (f1, v1) = next_string_from_pb(&mut tsh, &[1, 2])?; + let (f2, v2) = next_string_from_pb(&mut tsh, &[1, 2])?; + let rem = tsh.size_hint().1.unwrap_or_default(); + if rem > 0 { + tsh.nth(rem - 1); + } + + let (k, v) = if f1 == 1 && f2 == 2 { + (v1, v2) + } else if f2 == 1 && f1 == 2 { + (v2, v1) + } else { + return None; + }; + res.insert(k, v); + 0 + } else { + len + } + } + _ => return None, + }; + for _ in 0..to_skip { + pb.next(); + } + } + Some(res) +} + #[cfg(test)] mod tests { use crate::util; @@ -170,4 +230,15 @@ mod tests { let res = string_from_pb(p_bytes, 3).unwrap(); assert_eq!(res, "UC9vrvNSL3xcWGSkV86REBSg"); } + + #[test] + fn parse_proto_kv() { + let p = "ChEKBWFjb250EghvcmlnaW5hbAoKCgRsYW5nEgJlbg"; + let p_bytes = util::b64_decode(urlencoding::decode(p).unwrap().as_bytes()).unwrap(); + + let res = kv_from_pb(p_bytes).unwrap(); + assert_eq!(res.len(), 2); + assert_eq!(res["acont"], "original"); + assert_eq!(res["lang"], "en"); + } } From 71712e4eda5d78516fa9a5a7c3ab85daf1dc0bbc Mon Sep 17 00:00:00 2001 From: ta3pks Date: Tue, 17 Jun 2025 13:29:52 +0200 Subject: [PATCH 18/21] remove unwrap trying to fetch visitor data (#60) Co-authored-by: nikos efthias Reviewed-on: https://codeberg.org/ThetaDev/rustypipe/pulls/60 Co-authored-by: ta3pks Co-committed-by: ta3pks --- src/util/visitor_data.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/visitor_data.rs b/src/util/visitor_data.rs index 8bc64c7..2de2cfe 100644 --- a/src/util/visitor_data.rs +++ b/src/util/visitor_data.rs @@ -110,7 +110,7 @@ impl VisitorDataCache { /// Fetch a new visitor data ID and store it in the cache pub async fn new_visitor_data(&self) -> Result { - let vd = self.fetch_visitor_data().await.unwrap(); + let vd = self.fetch_visitor_data().await?; self.inner .req_counter From 412cd37840ded9e94aaadd5912ae9eb7397600e1 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Mon, 28 Apr 2025 15:58:13 +0200 Subject: [PATCH 19/21] test: fix isrc_search_languages (use quoted query) --- tests/youtube.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/youtube.rs b/tests/youtube.rs index fb7f860..5f64621 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -2691,25 +2691,21 @@ async fn invalid_ctoken(#[case] ep: ContinuationEndpoint, rp: RustyPipe) { } /// YouTube Music allows searching for ISRC codes -/// This feature does not seem to work with all languages and it has changed in the past. -/// This test is used to check which languages are working #[rstest] #[tokio::test] async fn isrc_search_languages(rp: RustyPipe) { for lang in LANGUAGES { - // flaky for English, skipping for now - if matches!(lang, Language::En | Language::EnGb | Language::EnIn) { - continue; - } - let tracks = rp .query() .lang(lang) - .music_search_tracks("DEUM71602459") + .music_search_tracks("\"DEUM71602459\"") .await .unwrap(); - let working = tracks.items.items.iter().any(|t| t.id == "g0iRiJ_ck48"); - assert!(working, "lang: {lang}"); + let track_id = &tracks.items.items[0].id; + assert!( + track_id == "g0iRiJ_ck48" || track_id == "YgUZtELr_jw", + "lang: {lang}; track: {track_id}" + ); } } From e7e389a316addbe01a5333e0372932f4351a5c9f Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 18 Jun 2025 14:59:55 +0200 Subject: [PATCH 20/21] feat: add unavailable field for music tracks fix: handling albums with unavailable tracks --- src/client/music_playlist.rs | 25 +- src/client/response/music_item.rs | 5 + ..._music_artist_20250113_grouped_albums.snap | 15 + ...tist__tests__map_music_artist_default.snap | 15 + ...tist__tests__map_music_artist_no_cont.snap | 15 + ...s__map_music_artist_only_more_singles.snap | 15 + ..._tests__map_music_artist_only_singles.snap | 13 + ...ic_charts__tests__map_music_charts_US.snap | 60 ++++ ...harts__tests__map_music_charts_global.snap | 40 +++ ..._details__tests__map_music_details_mv.snap | 1 + ...tails__tests__map_music_details_track.snap | 1 + ...ic_details__tests__map_music_radio_mv.snap | 25 ++ ...details__tests__map_music_radio_track.snap | 25 ++ ...sic_details__tests__map_music_related.snap | 24 ++ ...__tests__map_music_new_videos_default.snap | 10 + ...ests__map_music_new_videos_w_podcasts.snap | 100 ++++++ ...__map_music_album_20240228_twoColumns.snap | 1 + ...__map_music_album_20250225_recommends.snap | 5 + ...t__tests__map_music_album_description.snap | 11 + ...st__tests__map_music_album_one_artist.snap | 18 + ...aylist__tests__map_music_album_single.snap | 1 + ...t__tests__map_music_album_unavailable.snap | 12 + ...ests__map_music_album_various_artists.snap | 6 + ...ts__map_music_playlist_20240228_album.snap | 1 + ...ap_music_playlist_20240228_twoColumns.snap | 100 ++++++ ..._map_music_playlist_20241125_facepile.snap | 66 ++++ ...ylist__tests__map_music_playlist_long.snap | 100 ++++++ ...st__tests__map_music_playlist_nomusic.snap | 66 ++++ ...list__tests__map_music_playlist_short.snap | 87 +++++ ...__tests__map_music_search_main_artist.snap | 8 + ..._tests__map_music_search_main_default.snap | 13 + ...ch__tests__map_music_search_main_live.snap | 8 + ...h__tests__map_music_search_main_radio.snap | 6 + ...ch__tests__map_music_search_main_typo.snap | 6 + ...__map_music_search_suggestion_default.snap | 1 + ...ests__map_music_search_tracks_default.snap | 20 ++ ...ap_music_search_tracks_no_artist_link.snap | 7 + ...__tests__map_music_search_tracks_typo.snap | 20 ++ ...tests__map_music_search_tracks_videos.snap | 20 ++ ...t__music_userdata__tests__map_history.snap | 25 +- ...agination__tests__map_playlist_tracks.snap | 100 ++++++ ...__pagination__tests__map_radio_tracks.snap | 24 ++ ...__pagination__tests__map_saved_tracks.snap | 25 ++ ..._pagination__tests__map_search_tracks.snap | 20 ++ src/model/mod.rs | 2 + .../youtube__music_album_audiobook.snap | 319 ++++++++++++++++++ tests/snapshots/youtube__music_album_ep.snap | 5 + .../youtube__music_album_no_artist.snap | 14 + .../youtube__music_album_no_year.snap | 1 + .../youtube__music_album_one_artist.snap | 15 + .../snapshots/youtube__music_album_show.snap | 27 ++ .../youtube__music_album_single.snap | 1 + .../youtube__music_album_unavailable.snap | 146 +++++++- .../youtube__music_album_various_artists.snap | 6 + .../youtube__music_artist_basic.snap | 30 +- .../snapshots/youtube__music_details_mv.snap | 1 + .../youtube__music_details_track.snap | 1 + .../youtube__music_details_track_details.snap | 1 + tests/youtube.rs | 17 +- 59 files changed, 1718 insertions(+), 34 deletions(-) diff --git a/src/client/music_playlist.rs b/src/client/music_playlist.rs index 64f3d7e..3ef6e95 100644 --- a/src/client/music_playlist.rs +++ b/src/client/music_playlist.rs @@ -87,7 +87,7 @@ impl RustyPipeQuery { .iter() .enumerate() .filter_map(|(i, track)| { - if track.track_type.is_video() { + if track.track_type.is_video() && !track.unavailable { Some((i, track.name.clone())) } else { None @@ -115,25 +115,31 @@ impl RustyPipeQuery { for (i, title) in to_replace { let found_track = playlist.tracks.items.iter().find_map(|track| { if track.name == title && track.track_type.is_track() { - Some((track.id.clone(), track.duration)) + Some((track.id.clone(), track.duration, track.unavailable)) } else { None } }); - if let Some((track_id, duration)) = found_track { + if let Some((track_id, duration, unavailable)) = found_track { album.tracks[i].id = track_id; if let Some(duration) = duration { album.tracks[i].duration = Some(duration); } album.tracks[i].track_type = TrackType::Track; + album.tracks[i].unavailable = unavailable; } } // Extend the list of album tracks with the ones from the playlist if the playlist returned more tracks // This is the case for albums with more than 200 tracks (e.g. audiobooks) + // Note: in some cases the playlist may contain a loop of repeating tracks. If a track was found in the playlist + // that already exists in the album, stop. if album.tracks.len() < playlist.tracks.items.len() { let mut tn = last_tn; for mut t in playlist.tracks.items.into_iter().skip(album.tracks.len()) { + if album.tracks.iter().any(|at| at.id == t.id) { + break; + } tn += 1; t.album = album.tracks.first().and_then(|t| t.album.clone()); t.track_nr = Some(tn); @@ -296,8 +302,8 @@ impl MapResponse for response::MusicPlaylist { // Album playlists fetched via the playlist method dont include a header let (album, cover) = map_res .c - .first() - .and_then(|t: &TrackItem| { + .iter() + .find_map(|t: &TrackItem| { t.album.as_ref().map(|a| (a.clone(), t.cover.clone())) }) .ok_or(ExtractionError::InvalidData(Cow::Borrowed( @@ -305,10 +311,11 @@ impl MapResponse for response::MusicPlaylist { )))?; if !map_res.c.iter().all(|t| { - t.album - .as_ref() - .map(|a| a.id == album.id) - .unwrap_or_default() + t.unavailable + || t.album + .as_ref() + .map(|a| a.id == album.id) + .unwrap_or_default() }) { return Err(ExtractionError::InvalidData(Cow::Borrowed( "album playlist containing items from different albums", diff --git a/src/client/response/music_item.rs b/src/client/response/music_item.rs index bc912c9..5d9907d 100644 --- a/src/client/response/music_item.rs +++ b/src/client/response/music_item.rs @@ -797,6 +797,7 @@ impl MusicListMapper { track_type: vtype.into(), track_nr, by_va, + unavailable: item.music_item_renderer_display_policy == DisplayPolicy::GreyOut, })); Ok(Some(MusicItemType::Track)) } @@ -977,6 +978,7 @@ impl MusicListMapper { track_type: vtype.into(), track_nr: None, by_va, + unavailable: false, })); Ok(Some(MusicItemType::Track)) } @@ -1141,6 +1143,7 @@ impl MusicListMapper { track_type: vtype.into(), track_nr: None, by_va, + unavailable: false, })); } else { let (artists, by_va) = map_artists(subtitle_p2); @@ -1178,6 +1181,7 @@ impl MusicListMapper { track_type: vtype.into(), track_nr: None, by_va, + unavailable: false, })); } Some(MusicItemType::Track) @@ -1435,6 +1439,7 @@ pub(crate) fn map_queue_item(item: QueueMusicItem, lang: Language) -> MapResult< track_type: MusicVideoType::from_is_video(is_video).into(), track_nr: None, by_va, + unavailable: false, }, warnings, } diff --git a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_20250113_grouped_albums.snap b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_20250113_grouped_albums.snap index 9c9acaa..cf847e8 100644 --- a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_20250113_grouped_albums.snap +++ b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_20250113_grouped_albums.snap @@ -52,6 +52,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "h3T_NXRUUjM", @@ -84,6 +85,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XZfoFwWvkGQ", @@ -116,6 +118,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "LOuVxwVFJhs", @@ -148,6 +151,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "GePZUYeIQQQ", @@ -180,6 +184,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0mcING0Zdis", @@ -209,6 +214,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EAC-2ttHCyk", @@ -238,6 +244,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Bret5VaVzJk", @@ -267,6 +274,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EqP1_IcjW-s", @@ -296,6 +304,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3EoF9Of98e4", @@ -325,6 +334,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qr0eN_uIcTs", @@ -354,6 +364,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "McgSyiug6XE", @@ -387,6 +398,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ioZxvVhjFs8", @@ -416,6 +428,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3jyZJEcomkw", @@ -445,6 +458,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9oM-cflYhGk", @@ -474,6 +488,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_default.snap b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_default.snap index 6cc16cc..e684565 100644 --- a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_default.snap +++ b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_default.snap @@ -67,6 +67,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xTvyyoF_LZY", @@ -99,6 +100,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SlbfAYvA_gI", @@ -131,6 +133,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fdz_cabS9BU", @@ -163,6 +166,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hJWSZDJb-W4", @@ -195,6 +199,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fezKpDFKf5U", @@ -224,6 +229,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "doGzjheI604", @@ -253,6 +259,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zjEdX8-3CD8", @@ -282,6 +289,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DQZcxN9v0RA", @@ -311,6 +319,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2Vv-BfVoq4g", @@ -340,6 +349,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JGwWNGJdvx8", @@ -369,6 +379,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nSDgHBxUbVQ", @@ -398,6 +409,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lp-EO5I60KA", @@ -427,6 +439,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "orJSJGHjBLI", @@ -456,6 +469,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Il0S8BoucSA", @@ -485,6 +499,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_no_cont.snap b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_no_cont.snap index c921dda..7deecd8 100644 --- a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_no_cont.snap +++ b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_no_cont.snap @@ -67,6 +67,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xTvyyoF_LZY", @@ -99,6 +100,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SlbfAYvA_gI", @@ -131,6 +133,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fdz_cabS9BU", @@ -163,6 +166,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hJWSZDJb-W4", @@ -195,6 +199,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fezKpDFKf5U", @@ -224,6 +229,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "doGzjheI604", @@ -253,6 +259,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zjEdX8-3CD8", @@ -282,6 +289,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DQZcxN9v0RA", @@ -311,6 +319,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2Vv-BfVoq4g", @@ -340,6 +349,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JGwWNGJdvx8", @@ -369,6 +379,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nSDgHBxUbVQ", @@ -398,6 +409,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lp-EO5I60KA", @@ -427,6 +439,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "orJSJGHjBLI", @@ -456,6 +469,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Il0S8BoucSA", @@ -485,6 +499,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_more_singles.snap b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_more_singles.snap index 2c63b24..bca05ab 100644 --- a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_more_singles.snap +++ b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_more_singles.snap @@ -67,6 +67,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uZpH7EQ_PwE", @@ -99,6 +100,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WmQHSkjgyDM", @@ -143,6 +145,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9ssQKlLxBdQ", @@ -175,6 +178,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "y4FiCl-tUJc", @@ -207,6 +211,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KSav7HayxtI", @@ -236,6 +241,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7wtfhZwyrcc", @@ -265,6 +271,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TO-_3tck2tg", @@ -294,6 +301,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "D9G1VOjN_84", @@ -323,6 +331,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fKopy74weus", @@ -352,6 +361,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mWRsgZuwf_8", @@ -381,6 +391,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ktvTqknDobU", @@ -410,6 +421,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "I-QfPUz1es8", @@ -434,6 +446,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0I647GU3Jsc", @@ -463,6 +476,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gOsM-DYAEhY", @@ -492,6 +506,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_singles.snap b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_singles.snap index b90c6e2..879b878 100644 --- a/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_singles.snap +++ b/src/client/snapshots/rustypipe__client__music_artist__tests__map_music_artist_only_singles.snap @@ -67,6 +67,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7_Bav4c7UGM", @@ -99,6 +100,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kzUZABVj5UQ", @@ -131,6 +133,7 @@ MusicArtist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "P5uE7KDkDFE", @@ -160,6 +163,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kxjZwdLWFrc", @@ -189,6 +193,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-aneeaddeXc", @@ -218,6 +223,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YWijFdsj_Ew", @@ -247,6 +253,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "N217ZuMQnfY", @@ -276,6 +283,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "STNyxlYFyVY", @@ -305,6 +313,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "v5KZ5dalhzU", @@ -334,6 +343,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vaSSdzgDNw0", @@ -363,6 +373,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Rq_JkcROjsI", @@ -392,6 +403,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5VNZWTzJFso", @@ -421,6 +433,7 @@ MusicArtist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_US.snap b/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_US.snap index 0ce196c..d766194 100644 --- a/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_US.snap +++ b/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_US.snap @@ -36,6 +36,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UhbixyxgsiU", @@ -65,6 +66,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "saGYMhApaH8", @@ -94,6 +96,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8n5dJwWXrbo", @@ -123,6 +126,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Cr8K88UcO0s", @@ -152,6 +156,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pfxyk1glEq4", @@ -181,6 +186,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VtKcDwz6hiM", @@ -210,6 +216,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aAkMkVFwAoo", @@ -239,6 +246,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3V8aen7Flhs", @@ -268,6 +276,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rb0bjyt1OD0", @@ -297,6 +306,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-1vsm5bhoyE", @@ -326,6 +336,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ao3SN7fkQQU", @@ -359,6 +370,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "J9QwBwUnhQo", @@ -388,6 +400,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WyhU6Zb_fhY", @@ -417,6 +430,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aV-pJ8BBxj8", @@ -454,6 +468,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gSeBZqcTHLc", @@ -483,6 +498,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Vzkr-G1QEh8", @@ -512,6 +528,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SK37InR9j38", @@ -545,6 +562,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "C2YSX4sV_bA", @@ -574,6 +592,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ca48oMV59LU", @@ -603,6 +622,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TUbmIriJlp4", @@ -636,6 +656,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Z02zptUN8gI", @@ -669,6 +690,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Uq9gPaIzbe8", @@ -702,6 +724,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "b1kbLwvqugk", @@ -731,6 +754,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VF-FGf_ZZiI", @@ -760,6 +784,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Om0rYw6qzb8", @@ -793,6 +818,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PrSBuEFdRFU", @@ -826,6 +852,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9YdgldMKGGU", @@ -855,6 +882,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kiUIkL4aZ5o", @@ -884,6 +912,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mTkPFsVC5NE", @@ -917,6 +946,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YsMB0i5YTOc", @@ -946,6 +976,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3CkLMG5NwUg", @@ -975,6 +1006,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9yvzvUgzxxg", @@ -1004,6 +1036,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gPCCYMeXin0", @@ -1033,6 +1066,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gkkuezo7kX4", @@ -1070,6 +1104,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "D2nyu8d7Sq0", @@ -1099,6 +1134,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SXrcyqCPu4E", @@ -1128,6 +1164,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "p38WgakuYDo", @@ -1157,6 +1194,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "n4Z1cpdkgQU", @@ -1186,6 +1224,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4F_vcZ6KD9Q", @@ -1215,6 +1254,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], trending_tracks: [ @@ -1241,6 +1281,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UhbixyxgsiU", @@ -1265,6 +1306,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zugAhfd2r0g", @@ -1289,6 +1331,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5jJJYYaw8vw", @@ -1317,6 +1360,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VMZefv4Vrwg", @@ -1341,6 +1385,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3V8aen7Flhs", @@ -1365,6 +1410,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rb0bjyt1OD0", @@ -1389,6 +1435,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ut1OzEVUiM4", @@ -1413,6 +1460,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rAr3-Pn9yRI", @@ -1437,6 +1485,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PtPewTyPmUg", @@ -1461,6 +1510,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "G6xgMW7U0aY", @@ -1485,6 +1535,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "C2YSX4sV_bA", @@ -1509,6 +1560,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kiUIkL4aZ5o", @@ -1533,6 +1585,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9YdgldMKGGU", @@ -1557,6 +1610,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Z02zptUN8gI", @@ -1585,6 +1639,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "S0_888ZjlAA", @@ -1609,6 +1664,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "J9QwBwUnhQo", @@ -1633,6 +1689,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DWRj2BB8YHs", @@ -1665,6 +1722,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hX0aI5Jz8i8", @@ -1689,6 +1747,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Dw9VmOLwxoM", @@ -1713,6 +1772,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], artists: [ diff --git a/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_global.snap b/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_global.snap index 36575bf..c7db51e 100644 --- a/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_global.snap +++ b/src/client/snapshots/rustypipe__client__music_charts__tests__map_music_charts_global.snap @@ -32,6 +32,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jEdfjuG0Fx4", @@ -65,6 +66,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pRpeEdMmmQ0", @@ -94,6 +96,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Gzs60iBgd3E", @@ -127,6 +130,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "sABN7goDbZ8", @@ -160,6 +164,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "saGYMhApaH8", @@ -189,6 +194,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zuVV9Y55gvc", @@ -222,6 +228,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TiM_TFpT_DE", @@ -251,6 +258,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WcIcVapfqXw", @@ -284,6 +292,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Cr8K88UcO0s", @@ -313,6 +322,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BddP6PYo2gs", @@ -342,6 +352,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "POe9SOEKotk", @@ -371,6 +382,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Z02zptUN8gI", @@ -404,6 +416,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "e8laLiWolGg", @@ -445,6 +458,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SK37InR9j38", @@ -478,6 +492,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5kJMtNWUytY", @@ -507,6 +522,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gQlMMD8auMs", @@ -536,6 +552,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "D0gWr9K8Lb4", @@ -565,6 +582,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7ouFkoU8Ap8", @@ -594,6 +612,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-1vsm5bhoyE", @@ -623,6 +642,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gnMdTTeY1FY", @@ -652,6 +672,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ca48oMV59LU", @@ -681,6 +702,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VtKcDwz6hiM", @@ -710,6 +732,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5g2hT4GmAGU", @@ -739,6 +762,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CQLsdm1ZYAw", @@ -772,6 +796,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UhbixyxgsiU", @@ -801,6 +826,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mxF58TYuPaM", @@ -830,6 +856,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8n5dJwWXrbo", @@ -859,6 +886,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "j5y6xLpRwx4", @@ -892,6 +920,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jRxDUsGmwuc", @@ -921,6 +950,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RgKAFK5djSk", @@ -950,6 +980,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TGtWWb9emYI", @@ -979,6 +1010,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "no0RhhdJMlE", @@ -1008,6 +1040,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dzsuE5ugxf4", @@ -1037,6 +1070,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aAkMkVFwAoo", @@ -1066,6 +1100,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jpYkoa-uE_c", @@ -1103,6 +1138,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "A_g3lMcWVy0", @@ -1136,6 +1172,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gIOyB9ZXn8s", @@ -1169,6 +1206,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "MwpMEbgC7DA", @@ -1198,6 +1236,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AJleGCGFyIg", @@ -1227,6 +1266,7 @@ MusicCharts( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], trending_tracks: [], diff --git a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_mv.snap b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_mv.snap index fc22ac9..9abe6e6 100644 --- a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_mv.snap +++ b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_mv.snap @@ -36,6 +36,7 @@ TrackDetails( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), lyrics_id: Some("MPLYt_wrKjTn9hmry"), related_id: Some("MPTRt_wrKjTn9hmry"), diff --git a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_track.snap b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_track.snap index 7f559f0..6185cd5 100644 --- a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_track.snap +++ b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_details_track.snap @@ -54,6 +54,7 @@ TrackDetails( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), lyrics_id: Some("MPLYt_4xbv14CiQJm-1"), related_id: Some("MPTRt_4xbv14CiQJm-1"), diff --git a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_mv.snap b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_mv.snap index dab21d2..b76786f 100644 --- a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_mv.snap +++ b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_mv.snap @@ -38,6 +38,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Y8JFxS1HlDo", @@ -72,6 +73,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CM4CkVFmTds", @@ -106,6 +108,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_ysomCGaZLw", @@ -140,6 +143,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gQlMMD8auMs", @@ -174,6 +178,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uR8Mrt1IpXg", @@ -208,6 +213,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PkKnp4SdE-w", @@ -242,6 +248,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4vbDFu0PUew", @@ -276,6 +283,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "A5H8zBb3iao", @@ -310,6 +318,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_xJUCsyMQes", @@ -339,6 +348,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "n0j5NPptyM0", @@ -373,6 +383,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3GWscde8rM8", @@ -407,6 +418,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uBY1AoiF5Vo", @@ -441,6 +453,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WPdWvnAAurg", @@ -475,6 +488,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tyrVtwE8Gv0", @@ -509,6 +523,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Jh4QFaPmdss", @@ -543,6 +558,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2OvyA2__Eas", @@ -577,6 +593,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dYRITmpFbJ4", @@ -611,6 +628,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "POe9SOEKotk", @@ -645,6 +663,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pSudEWBAYRE", @@ -679,6 +698,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nnVjsos40qk", @@ -713,6 +733,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "H69tJmsgd9I", @@ -747,6 +768,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0IBSemQmno8", @@ -781,6 +803,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "MjCZfZfucEc", @@ -810,6 +833,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tg2uF3R_Ozo", @@ -844,6 +868,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("CBkSSBILdGcydUYzUl9Pem8iEVJEQU1WTVplZXJybnVMaTVFMg53QUVCOGdFQ2VBRSUzRDgY0AEB-gEQQzcxNUY2RDFGQjIwNEQwQRgKggEVUFQ6RWd0MFp6SjFSak5TWDA5NmJ3"), diff --git a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_track.snap b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_track.snap index 6524f42..ee4e860 100644 --- a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_track.snap +++ b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_radio_track.snap @@ -56,6 +56,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "u1uvv_yKhH8", @@ -108,6 +109,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QiziJ40kTz0", @@ -160,6 +162,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OXWz_x6-dro", @@ -212,6 +215,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ghrlZIMDzbM", @@ -264,6 +268,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "04tYkKUPPv4", @@ -316,6 +321,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wjCrjR5WpgQ", @@ -368,6 +374,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wkVlb8rSies", @@ -420,6 +427,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RdU3F5vN3_s", @@ -472,6 +480,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "950BdJKBhGo", @@ -524,6 +533,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "W0x7GcZkvH4", @@ -576,6 +586,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0EK_M2taRIM", @@ -628,6 +639,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "INLFlN-PZq4", @@ -680,6 +692,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8JXc4idKS_c", @@ -732,6 +745,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vFFT1iAUNDE", @@ -788,6 +802,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g92HIac9ufA", @@ -840,6 +855,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CinJhZF5ZuA", @@ -892,6 +908,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "t7hmovsG_f0", @@ -944,6 +961,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FrEDny55ch8", @@ -996,6 +1014,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PyyT5tHbOLw", @@ -1048,6 +1067,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_ZkUb7iIOqQ", @@ -1100,6 +1120,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UxZH9lRdLD0", @@ -1152,6 +1173,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aYlXNpaQydk", @@ -1204,6 +1226,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SZiwpL62to8", @@ -1256,6 +1279,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mbg1Cn6Ua9U", @@ -1308,6 +1332,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("CBkSSBILbWJnMUNuNlVhOVUiEVJEQU1WTTduaWdYUVMxWGIwMg53QUVCOGdFQ2VBRSUzRDgY0AEB-gEQQzcxNUY2RDFGQjIwNEQwQRgKggEVUFQ6RWd0dFltY3hRMjQyVldFNVZR"), diff --git a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_related.snap b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_related.snap index 4749fc2..c882bc6 100644 --- a/src/client/snapshots/rustypipe__client__music_details__tests__map_music_related.snap +++ b/src/client/snapshots/rustypipe__client__music_details__tests__map_music_related.snap @@ -35,6 +35,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g92HIac9ufA", @@ -67,6 +68,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "khgCIMs_lVQ", @@ -99,6 +101,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "i2VGa-ETiM4", @@ -131,6 +134,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "INLFlN-PZq4", @@ -163,6 +167,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ZzbNM2l-AAA", @@ -195,6 +200,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "i4loHXi8f3A", @@ -227,6 +233,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "miqQAzOXPBo", @@ -259,6 +266,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hh5GKVa8VtM", @@ -291,6 +299,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dzwSnvfKEtw", @@ -323,6 +332,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "REmUidcJt5I", @@ -355,6 +365,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OXWz_x6-dro", @@ -387,6 +398,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aFoqCI75WoY", @@ -419,6 +431,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_Pm74XignKI", @@ -451,6 +464,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-uOShlFu1v8", @@ -483,6 +497,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "LP9sF1v-vz4", @@ -515,6 +530,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KJrPsT2X-yk", @@ -547,6 +563,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tkzYyEp4zB4", @@ -579,6 +596,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ZpD59tu5_Rk", @@ -611,6 +629,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_eNXeEx9Hvk", @@ -643,6 +662,7 @@ MusicRelated( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], other_versions: [ @@ -669,6 +689,7 @@ MusicRelated( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Yi2nsnpw5h0", @@ -693,6 +714,7 @@ MusicRelated( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2Qefh0W_H88", @@ -717,6 +739,7 @@ MusicRelated( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "oo89OQvzkIo", @@ -741,6 +764,7 @@ MusicRelated( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], albums: [ diff --git a/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_default.snap b/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_default.snap index 0702ea3..88ae8ab 100644 --- a/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_default.snap +++ b/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_default.snap @@ -31,6 +31,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gFERoNpcnFU", @@ -60,6 +61,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bmEzom5sfCI", @@ -89,6 +91,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QHY2pm7uT3k", @@ -118,6 +121,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Su42LK7I4NM", @@ -147,6 +151,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mly7ha04bEE", @@ -176,6 +181,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "c91bmLbGt-g", @@ -213,6 +219,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "IwzkfMmNMpM", @@ -242,6 +249,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_-spkuonX2k", @@ -275,6 +283,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "48pBUciAbRY", @@ -304,5 +313,6 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ] diff --git a/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_w_podcasts.snap b/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_w_podcasts.snap index 3ab035d..2423d08 100644 --- a/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_w_podcasts.snap +++ b/src/client/snapshots/rustypipe__client__music_new__tests__map_music_new_videos_w_podcasts.snap @@ -31,6 +31,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_UN2gwabRBI", @@ -60,6 +61,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aY72b4ZGPbo", @@ -89,6 +91,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Cu82AvG87_g", @@ -118,6 +121,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "p9R94XSYjwI", @@ -147,6 +151,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Tlg574e9fuU", @@ -176,6 +181,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1L-RpSmlWp0", @@ -205,6 +211,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EI28gmgBMfw", @@ -234,6 +241,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Z1DEwM1E7ho", @@ -267,6 +275,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hqnDi07CsJU", @@ -296,6 +305,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_T2tvIwOMfc", @@ -325,6 +335,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "seDc-M7aSOI", @@ -354,6 +365,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "APJAQoSCwuA", @@ -383,6 +395,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "965Lv2AwODM", @@ -412,6 +425,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Yl7NAOn0YJw", @@ -441,6 +455,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TVhoS5qhVi4", @@ -470,6 +485,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dZdaP7DGze4", @@ -499,6 +515,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SsizZ2VZe6c", @@ -528,6 +545,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xFRIddDw8bw", @@ -557,6 +575,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Rbhky_2qIUo", @@ -586,6 +605,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ECovqS_ItUo", @@ -615,6 +635,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uxP0y-m6ysA", @@ -644,6 +665,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "simC880SUGk", @@ -673,6 +695,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dGLVJ35_gnA", @@ -702,6 +725,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vY6UiUDPuMk", @@ -731,6 +755,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QMQw_waEPi0", @@ -760,6 +785,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Sc2-3BK2mzM", @@ -793,6 +819,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bprHBlahnmM", @@ -817,6 +844,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FMhHc5x2DzE", @@ -846,6 +874,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nOjbJdw2dPs", @@ -875,6 +904,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1G1zcTV5yX4", @@ -904,6 +934,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BcbKoY7XpJE", @@ -933,6 +964,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mq6zggKZTFU", @@ -962,6 +994,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aQFl1xhloVo", @@ -991,6 +1024,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "A3IhjA2aMUg", @@ -1024,6 +1058,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cxIOWM0xLc4", @@ -1053,6 +1088,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "IFKAgKgVaSI", @@ -1082,6 +1118,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "iGUN99hW3nU", @@ -1111,6 +1148,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_alKEACsIds", @@ -1140,6 +1178,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WGNJIF7OoAc", @@ -1169,6 +1208,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "a_TotMZ5hxc", @@ -1202,6 +1242,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0eoeyKkWBRs", @@ -1231,6 +1272,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DU4NtqyTnuM", @@ -1260,6 +1302,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kLbn61Z4LDI", @@ -1289,6 +1332,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vMFNI5lOLwU", @@ -1326,6 +1370,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AZoZbtI67Yk", @@ -1355,6 +1400,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ah4Dn3VAnMk", @@ -1384,6 +1430,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "sLklEvxhmAQ", @@ -1413,6 +1460,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2Lbp1P4pP6c", @@ -1442,6 +1490,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2TYIa09PXyo", @@ -1471,6 +1520,7 @@ expression: map_res.c track_type: episode, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Hdy7l8fkREo", @@ -1500,6 +1550,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "A-sjPe3xvqY", @@ -1533,6 +1584,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jFVX_v2yAas", @@ -1562,6 +1614,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YDfL2Ns8wz4", @@ -1591,6 +1644,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "du4hVdxqyr8", @@ -1620,6 +1674,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "G5vlW0PZ878", @@ -1649,6 +1704,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Gtg2TSR19Mg", @@ -1678,6 +1734,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vJ3wwezOV_8", @@ -1707,6 +1764,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "76q5EiRyYks", @@ -1736,6 +1794,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nEjntI9GMVM", @@ -1765,6 +1824,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Gtct_ipIQmo", @@ -1794,6 +1854,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aw4kqTyZshk", @@ -1823,6 +1884,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xjoCNfK3vxo", @@ -1852,6 +1914,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DN1gYO3bu-k", @@ -1876,6 +1939,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "X_cqTeG7v98", @@ -1905,6 +1969,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "b_B4ebhKvQ4", @@ -1934,6 +1999,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VQp1QmwOzxw", @@ -1963,6 +2029,7 @@ expression: map_res.c track_type: episode, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "suAR1PYFNYA", @@ -1992,6 +2059,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "No3Cr6ph-9U", @@ -2021,6 +2089,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ORJEgiVY08U", @@ -2050,6 +2119,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2px4-y1Y0PI", @@ -2079,6 +2149,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kchzKOizhGg", @@ -2108,6 +2179,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "V6eAGSz4JI8", @@ -2137,6 +2209,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1A5hWzS00Nc", @@ -2166,6 +2239,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bzsSkarE4zw", @@ -2199,6 +2273,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "59HJZIMVxAg", @@ -2228,6 +2303,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8XQYz7JKjWI", @@ -2257,6 +2333,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5FkJkpTWSWk", @@ -2294,6 +2371,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1m51ncAU4uA", @@ -2327,6 +2405,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ycff6mFkoPY", @@ -2356,6 +2435,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g0ghPuWqYR0", @@ -2385,6 +2465,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1YiTQJcKajE", @@ -2414,6 +2495,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TuyisGsNr4g", @@ -2443,6 +2525,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ClU3aqamHGQ", @@ -2472,6 +2555,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bYyB3FzPRfg", @@ -2505,6 +2589,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "I5eu4XMWZR8", @@ -2534,6 +2619,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ziNtA-mcXTY", @@ -2563,6 +2649,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CDEikOST7ZQ", @@ -2596,6 +2683,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YQzvJSR5jy8", @@ -2625,6 +2713,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lPaplIqUXJc", @@ -2654,6 +2743,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "78Y0SxVVxP4", @@ -2683,6 +2773,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2e-xqMWT9GY", @@ -2712,6 +2803,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "81RRIPE404o", @@ -2741,6 +2833,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uxR8VhGG9Pc", @@ -2770,6 +2863,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JSNwR0MzGZQ", @@ -2799,6 +2893,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DS8dvzDXpjQ", @@ -2828,6 +2923,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "j10zAWP5KsM", @@ -2857,6 +2953,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ugFKFWhsoZA", @@ -2886,6 +2983,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xXO1h6Kthcw", @@ -2915,6 +3013,7 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VOUqmbeilXA", @@ -2944,5 +3043,6 @@ expression: map_res.c track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ] diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20240228_twoColumns.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20240228_twoColumns.snap index 3a080cd..3438871 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20240228_twoColumns.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20240228_twoColumns.snap @@ -69,6 +69,7 @@ MusicAlbum( track_type: video, track_nr: Some(1), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20250225_recommends.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20250225_recommends.snap index d13d6de..ee819e1 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20250225_recommends.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_20250225_recommends.snap @@ -61,6 +61,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "lhPOMUjV4rE", @@ -82,6 +83,7 @@ MusicAlbum( track_type: video, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "Bu26uFtpt58", @@ -103,6 +105,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "RgwNqqiVqdY", @@ -124,6 +127,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "2TuOh30XbCI", @@ -145,6 +149,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_description.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_description.snap index 09e8d67..fcd9927 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_description.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_description.snap @@ -65,6 +65,7 @@ MusicAlbum( track_type: video, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "fk4BbF7B29w", @@ -86,6 +87,7 @@ MusicAlbum( track_type: video, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "z7NEG3SGZ_g", @@ -107,6 +109,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "a1IuJLebHgM", @@ -128,6 +131,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "-fsCc7Be1H0", @@ -149,6 +153,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "l8djdhhFuxo", @@ -170,6 +175,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "Qiu59lZShCo", @@ -191,6 +197,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "-hzFTJDJGkQ", @@ -212,6 +219,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "Db9ciJPIaEU", @@ -233,6 +241,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "jb5g4UFHmfQ", @@ -254,6 +263,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "1kZsaRkVEUY", @@ -275,6 +285,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_one_artist.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_one_artist.snap index 1d55603..e0ebfef 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_one_artist.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_one_artist.snap @@ -61,6 +61,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "rREEBXp0y9s", @@ -82,6 +83,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "zvU5Y8Q19hU", @@ -103,6 +105,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "ARKLrzzTQA0", @@ -124,6 +127,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "tstLgN8A_Ng", @@ -145,6 +149,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "k2DjgQOY3Ts", @@ -166,6 +171,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "azHwhecxEsI", @@ -187,6 +193,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "_FcsdYIQ2co", @@ -208,6 +215,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "27bOWEbshyE", @@ -229,6 +237,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "riD_3oZwt8w", @@ -250,6 +259,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "8GNvjF3no9s", @@ -271,6 +281,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "YHMFzf1uN2U", @@ -292,6 +303,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "jvV-z5F3oAo", @@ -313,6 +325,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "u8_9cxlrh8k", @@ -334,6 +347,7 @@ MusicAlbum( track_type: track, track_nr: Some(14), by_va: false, + unavailable: false, ), TrackItem( id: "gSvKcvM1Wk0", @@ -355,6 +369,7 @@ MusicAlbum( track_type: track, track_nr: Some(15), by_va: false, + unavailable: false, ), TrackItem( id: "wQHgKRJ0pDQ", @@ -376,6 +391,7 @@ MusicAlbum( track_type: track, track_nr: Some(16), by_va: false, + unavailable: false, ), TrackItem( id: "Ckz5i6-hzf0", @@ -397,6 +413,7 @@ MusicAlbum( track_type: track, track_nr: Some(17), by_va: false, + unavailable: false, ), TrackItem( id: "y5zuUgyFqrc", @@ -418,6 +435,7 @@ MusicAlbum( track_type: track, track_nr: Some(18), by_va: false, + unavailable: false, ), ], variants: [ diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_single.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_single.snap index bf5add2..9bb270a 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_single.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_single.snap @@ -69,6 +69,7 @@ MusicAlbum( track_type: video, track_nr: Some(1), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_unavailable.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_unavailable.snap index 27d07af..3637c4f 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_unavailable.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_unavailable.snap @@ -56,6 +56,7 @@ MusicAlbum( track_type: video, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "5jd-AhBwcCQ", @@ -77,6 +78,7 @@ MusicAlbum( track_type: video, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "_cmORZMgv6I", @@ -98,6 +100,7 @@ MusicAlbum( track_type: video, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "M_kVMsFaGYs", @@ -119,6 +122,7 @@ MusicAlbum( track_type: video, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "c8AfY6yhdkM", @@ -140,6 +144,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "DSQEKEegiH0", @@ -161,6 +166,7 @@ MusicAlbum( track_type: video, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "2TTOKQSzuQY", @@ -182,6 +188,7 @@ MusicAlbum( track_type: video, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "iRaX0BfME70", @@ -203,6 +210,7 @@ MusicAlbum( track_type: video, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "Kn3cruxYj0c", @@ -224,6 +232,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "-P1FyntN_Uc", @@ -245,6 +254,7 @@ MusicAlbum( track_type: video, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "njdlNT1RRo4", @@ -266,6 +276,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "Si-CXM8CHqQ", @@ -287,6 +298,7 @@ MusicAlbum( track_type: track, track_nr: Some(18), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_various_artists.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_various_artists.snap index 189d625..d8f03c7 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_various_artists.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_album_various_artists.snap @@ -56,6 +56,7 @@ MusicAlbum( track_type: video, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "9WYpLYAEub0", @@ -77,6 +78,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "R48tE237bW4", @@ -98,6 +100,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "-UzsoR6z-vg", @@ -119,6 +122,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "kbNVyn8Ex28", @@ -140,6 +144,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "NJrQZUzWP5Y", @@ -161,6 +166,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_album.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_album.snap index 5d69c60..eeafa78 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_album.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_album.snap @@ -59,6 +59,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: None, diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_twoColumns.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_twoColumns.snap index 367d1be..4694e0f 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_twoColumns.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20240228_twoColumns.snap @@ -84,6 +84,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "P-zJCLBqZc4", @@ -116,6 +117,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_mAPAtjWZGE", @@ -148,6 +150,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JbXkjRqWTxc", @@ -184,6 +187,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "72b8D6s_y_U", @@ -216,6 +220,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mHKNroJOcig", @@ -248,6 +253,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0C1NFu4NB_4", @@ -280,6 +286,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EnLWwwtO1-A", @@ -316,6 +323,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cafxLTAWi-g", @@ -352,6 +360,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uyemSV1SpnE", @@ -384,6 +393,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ogc58xMpPCc", @@ -408,6 +418,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tsw1LgVkFjE", @@ -440,6 +451,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xSB8trUFX1A", @@ -472,6 +484,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "yEKTrciCvvY", @@ -496,6 +509,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "LbHsWjX9dv4", @@ -528,6 +542,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "L2apFB6EF-Y", @@ -560,6 +575,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uCW2sZZofhk", @@ -592,6 +608,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XZ9DKiNZszM", @@ -616,6 +633,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "J1AOKFRqCjg", @@ -652,6 +670,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XNd6d6H1LBo", @@ -676,6 +695,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SSy4VdjEJKM", @@ -708,6 +728,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0am_BfODDvc", @@ -744,6 +765,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xv3qKrCq2w8", @@ -776,6 +798,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pZC82a-2eo0", @@ -808,6 +831,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kOmmYiigFLE", @@ -840,6 +864,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Jcp48M-vRJw", @@ -872,6 +897,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YeSgtLJQGJs", @@ -904,6 +930,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_LY6aFUVmOU", @@ -940,6 +967,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SCTMdJ1cuoU", @@ -972,6 +1000,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TEOwoK-CMes", @@ -1004,6 +1033,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JgI6z6aQhEA", @@ -1036,6 +1066,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1FxeCa6kypU", @@ -1072,6 +1103,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hG6YzmvbosI", @@ -1104,6 +1136,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "y3PKcVd7UtM", @@ -1136,6 +1169,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UiCRuNo4dGg", @@ -1168,6 +1202,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3uXHaVENo6E", @@ -1192,6 +1227,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EX2d37tT5fo", @@ -1224,6 +1260,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RjQxmy90hTg", @@ -1268,6 +1305,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "IsLFK8TkaVw", @@ -1300,6 +1338,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "myRx1SRqxic", @@ -1332,6 +1371,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BDuDCIt2eiY", @@ -1368,6 +1408,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Do0lH6GDy7w", @@ -1400,6 +1441,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g2oZ6FSl9TU", @@ -1432,6 +1474,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cHc3cXXIydc", @@ -1464,6 +1507,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ITW3C8lIQlk", @@ -1496,6 +1540,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rKGRuQBnatM", @@ -1528,6 +1573,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JstDN42iDDo", @@ -1564,6 +1610,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "POcbY0NTG9w", @@ -1596,6 +1643,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Jf3JOkPsogI", @@ -1632,6 +1680,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lKLGceNzFAM", @@ -1664,6 +1713,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XNupKC5A6jc", @@ -1696,6 +1746,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BDWxBtjUyWQ", @@ -1728,6 +1779,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7LZIEUxH9Ro", @@ -1760,6 +1812,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5K9y2WGUl0E", @@ -1792,6 +1845,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UzuQCBPpZ7U", @@ -1828,6 +1882,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SU20Ah4PE48", @@ -1860,6 +1915,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3RI2LsrZ9OE", @@ -1892,6 +1948,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2KoWN3sAFms", @@ -1924,6 +1981,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EcHhTnHOzAk", @@ -1956,6 +2014,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "NjjMprtE004", @@ -1988,6 +2047,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gk5sKJ4PgPU", @@ -2020,6 +2080,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "K81Cfizqe9A", @@ -2052,6 +2113,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bM7QN9S0Dno", @@ -2084,6 +2146,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "07O7i2BzqUM", @@ -2116,6 +2179,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "m2mJGmMtBfA", @@ -2148,6 +2212,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0gTcGawN9xk", @@ -2180,6 +2245,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_tbHFWpYFbA", @@ -2212,6 +2278,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "X2rGbIe14Ys", @@ -2244,6 +2311,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "HIVVqNy5w_g", @@ -2280,6 +2348,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cJH0qBxeBmI", @@ -2304,6 +2373,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "a0C_z75ES4A", @@ -2336,6 +2406,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jJQAZKK5_5I", @@ -2368,6 +2439,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FcBaTjGk5Cg", @@ -2400,6 +2472,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vwNNfKpGw00", @@ -2432,6 +2505,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UKwFZI9zHlY", @@ -2464,6 +2538,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "x62rX6BYeYE", @@ -2496,6 +2571,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9BXn7ZNc35Q", @@ -2532,6 +2608,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QKYN0pLq1ew", @@ -2564,6 +2641,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "P5Aq3oxynt4", @@ -2596,6 +2674,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tYbZqVBulkU", @@ -2628,6 +2707,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KUpIwlt3TAA", @@ -2660,6 +2740,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nlkNJ4oavoQ", @@ -2692,6 +2773,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pduHLli6NnA", @@ -2716,6 +2798,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rbNpTesNEuw", @@ -2748,6 +2831,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ecMLL1XKbQA", @@ -2780,6 +2864,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OvfD_geCvkI", @@ -2812,6 +2897,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Qg9ea0wi_18", @@ -2844,6 +2930,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "z5bVgD6KjQU", @@ -2880,6 +2967,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UqiemFNeprQ", @@ -2912,6 +3000,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1yAcDPQ7bPs", @@ -2936,6 +3025,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xbHdNkV1Bgg", @@ -2972,6 +3062,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AjGbzsAH2dI", @@ -3008,6 +3099,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "29OvRKJlOX4", @@ -3040,6 +3132,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JVUypCxmfQA", @@ -3072,6 +3165,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KWIfPu8860w", @@ -3104,6 +3198,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "x1DGqCmCeaE", @@ -3136,6 +3231,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Of5EmGLKEn4", @@ -3160,6 +3256,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "T9_p5vicleo", @@ -3192,6 +3289,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "R_X1K3arztQ", @@ -3224,6 +3322,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VTFALCPPUN4", @@ -3256,6 +3355,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("4qmFsgJbEi1WTFJEQ0xBSzV1eV9rYjdFQmk2eTNHcnRKcmk0X1pINTZNczc4NkRGRWltYk0aKmVoVlFWRHBGWjNSWFZrVmFRbFJGVGxGVlJsWlBUa0dTQVFNSXVnUSUzRA%3D%3D"), diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20241125_facepile.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20241125_facepile.snap index 68e8b5d..5646999 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20241125_facepile.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_20241125_facepile.snap @@ -59,6 +59,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RPGLMuxkLCs", @@ -83,6 +84,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "z-ALpnnQLrk", @@ -107,6 +109,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "_rrbTTv8zcQ", @@ -131,6 +134,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "JE16OKTawLw", @@ -155,6 +159,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RQNY0Wzm7DQ", @@ -179,6 +184,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "uhy24PKBkd0", @@ -203,6 +209,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "OL1hQadBHfs", @@ -227,6 +234,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "Zge_SUfk0r8", @@ -251,6 +259,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "yFGIeU_IDE4", @@ -275,6 +284,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "P6MVqfQzPIg", @@ -299,6 +309,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "9n0pLDn8Z_I", @@ -323,6 +334,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "oXbx2YtIkeQ", @@ -347,6 +359,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "pfBBTTwxo8Q", @@ -371,6 +384,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "WxtRqzxSAh0", @@ -395,6 +409,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "ianUckvxtLw", @@ -419,6 +434,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "eb2Ghj1g1ic", @@ -443,6 +459,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "8TpEsyVtCog", @@ -467,6 +484,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "KD_WAei4LMg", @@ -491,6 +509,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "qfpOCrtweKk", @@ -515,6 +534,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "6gv3nrOA_bQ", @@ -539,6 +559,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "waaic6UnkU8", @@ -563,6 +584,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "lSy4MLC_uV4", @@ -587,6 +609,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "BuN8-U_quok", @@ -611,6 +634,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "g_UTG10nzaQ", @@ -635,6 +659,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "kNykFWaDbGw", @@ -659,6 +684,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "gJF7vxCYTgY", @@ -683,6 +709,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "CodZMQ_Anc0", @@ -707,6 +734,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "oKHMTKJdZ_M", @@ -731,6 +759,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "--O_Eyok_eE", @@ -755,6 +784,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "2bT3ljKMSo8", @@ -779,6 +809,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "YRAX_slrbsI", @@ -803,6 +834,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "aRRbCEwUSuw", @@ -827,6 +859,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "5sV8SzTbJS8", @@ -851,6 +884,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "ZxxZlU2o1TE", @@ -875,6 +909,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "gIjo5at4AxE", @@ -899,6 +934,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "NSGk7-kyeEU", @@ -923,6 +959,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "cgJtZ7Otc4Y", @@ -947,6 +984,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "l5LQu3Q0nWY", @@ -971,6 +1009,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "YX4Z3ZlWUFc", @@ -995,6 +1034,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "LoyvqR41lKw", @@ -1019,6 +1059,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "HbQtMZbtx_Q", @@ -1043,6 +1084,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "0DHRbP9ecgw", @@ -1067,6 +1109,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "rFOFkvk-xus", @@ -1091,6 +1134,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "P8zxnSihJ_8", @@ -1115,6 +1159,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RWgeHl9XkCY", @@ -1139,6 +1184,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "I1n539enNNY", @@ -1163,6 +1209,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "70VKekyZz5g", @@ -1187,6 +1234,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "2OWJ1bwFu6Y", @@ -1211,6 +1259,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "zLiSA2i-niw", @@ -1235,6 +1284,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "wyXlw7nMpko", @@ -1259,6 +1309,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "NrU4fhzvFpA", @@ -1283,6 +1334,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "1xhKegaA1hQ", @@ -1307,6 +1359,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "9F4lZ8psBtg", @@ -1331,6 +1384,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "G3uUtejX9to", @@ -1355,6 +1409,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "-0Xn5pViCss", @@ -1379,6 +1434,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "a7u71Fco99I", @@ -1403,6 +1459,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "H6uUbvcgKdk", @@ -1427,6 +1484,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "tPRTCauHtkw", @@ -1451,6 +1509,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "pMKAQExcarM", @@ -1475,6 +1534,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "7E-z-7KCdBI", @@ -1499,6 +1559,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "EPtbC0ZVddo", @@ -1523,6 +1584,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "TpPHng0eGJs", @@ -1547,6 +1609,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "rt2QFQwJYcs", @@ -1571,6 +1634,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "WPyfaztFDQ4", @@ -1595,6 +1659,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "5lmumP0DaUw", @@ -1619,6 +1684,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), ], ctoken: None, diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_long.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_long.snap index 0c6184d..77ffab3 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_long.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_long.snap @@ -59,6 +59,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8rRj5ZXRNko", @@ -83,6 +84,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lHZtcC67yrY", @@ -107,6 +109,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TSkVVVBS9k8", @@ -131,6 +134,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lc-cnCRhE7c", @@ -155,6 +159,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3ryohiCVq3M", @@ -179,6 +184,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BNHamTwxJ6Q", @@ -207,6 +213,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5mqelmYUcI0", @@ -231,6 +238,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "k9EYjn5f_nE", @@ -255,6 +263,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fkMg_X9lHMc", @@ -279,6 +288,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4wOoLLDXbDY", @@ -303,6 +313,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Z_mf9aCHag8", @@ -327,6 +338,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cZ58odQo87A", @@ -351,6 +363,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1il3RFk5Okw", @@ -375,6 +388,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8WQMBv2deYQ", @@ -399,6 +413,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vGrfFzagzHs", @@ -423,6 +438,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1gDbpWC_9pE", @@ -447,6 +463,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "p-AWcCCbBHw", @@ -471,6 +488,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RPN88D_HjMU", @@ -499,6 +517,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5PST7Ld4wWU", @@ -523,6 +542,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "opoDBF_b-fg", @@ -547,6 +567,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AMT9IOyXmBM", @@ -571,6 +592,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VP5B1UmgHfc", @@ -595,6 +617,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vcuQpbs0yT0", @@ -619,6 +642,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "LeMLVEJLruQ", @@ -643,6 +667,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "MtDPKJSsBgc", @@ -667,6 +692,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4tDpYxNYqPg", @@ -691,6 +717,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EkWjaoH7k6w", @@ -715,6 +742,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tERRFWuYG48", @@ -739,6 +767,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wCcJuN47UcY", @@ -763,6 +792,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qdtLCfEcPL4", @@ -787,6 +817,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wjXUBG15eZ8", @@ -811,6 +842,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "HBjDZMJUduo", @@ -835,6 +867,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xkXQQ0IAbk0", @@ -859,6 +892,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DraA3PUuoQc", @@ -883,6 +917,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wMIGQp4YhuU", @@ -907,6 +942,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "38lrK74voaI", @@ -931,6 +967,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2qW9rOSFF1M", @@ -959,6 +996,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tMILH6UEfPA", @@ -983,6 +1021,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "izHB2EdMngg", @@ -1007,6 +1046,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "haECT-SerHk", @@ -1031,6 +1071,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cVikZ8Oe_XA", @@ -1055,6 +1096,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "drFsXLChrWc", @@ -1079,6 +1121,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1EMFt7m_8yE", @@ -1103,6 +1146,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_yWU0lFghxU", @@ -1127,6 +1171,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XlD-LO3ogFM", @@ -1151,6 +1196,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nAzjWqNfgvc", @@ -1179,6 +1225,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PySC3RGhZJU", @@ -1203,6 +1250,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "G-iwLoyH6ZE", @@ -1227,6 +1275,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fgCOUO-s8nY", @@ -1251,6 +1300,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "m-Ik3yy728Y", @@ -1275,6 +1325,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "U0_UYW5Y4cM", @@ -1299,6 +1350,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rsrDYTEicq8", @@ -1323,6 +1375,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2aU4wRgl_0E", @@ -1347,6 +1400,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FzcJxJAxFtw", @@ -1375,6 +1429,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2hyibXdOp5w", @@ -1399,6 +1454,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YaKG5cUVB30", @@ -1423,6 +1479,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ahwc-ouFeTQ", @@ -1447,6 +1504,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SoImFhORKpg", @@ -1471,6 +1529,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jP4-XrbGt3M", @@ -1495,6 +1554,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Yy2RsG4lnm4", @@ -1519,6 +1579,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "388e_8mu1t4", @@ -1543,6 +1604,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dHHtPi-j7dQ", @@ -1567,6 +1629,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "d8ERTCVXIUE", @@ -1591,6 +1654,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vQXn3EzzYY4", @@ -1615,6 +1679,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zA-BTpC-yvI", @@ -1639,6 +1704,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rnzIN9H_G10", @@ -1663,6 +1729,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fcBbT1GTxqM", @@ -1687,6 +1754,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "wCDsm_dt1cI", @@ -1711,6 +1779,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4j3AOJV1J8I", @@ -1735,6 +1804,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RtuW08ZIgvg", @@ -1759,6 +1829,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cbTXqKBIQ40", @@ -1783,6 +1854,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "oSd0Lph4luY", @@ -1807,6 +1879,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "oq0rrYrufYU", @@ -1831,6 +1904,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0-P_YkS0z8s", @@ -1855,6 +1929,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4BAKb2p450Q", @@ -1879,6 +1954,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "yqObMM_QzVQ", @@ -1903,6 +1979,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dlvStoOyEzE", @@ -1927,6 +2004,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VNttGAaek2U", @@ -1951,6 +2029,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TxZMfufRJfo", @@ -1975,6 +2054,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "6agT2asF4as", @@ -1999,6 +2079,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EcW0n83La5A", @@ -2023,6 +2104,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_b61hg8UlZM", @@ -2047,6 +2129,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kDMFranvFuQ", @@ -2071,6 +2154,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1apku0pVDeE", @@ -2095,6 +2179,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g6JYzOjglBs", @@ -2119,6 +2204,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "GYK-NfOo7b4", @@ -2143,6 +2229,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "omUuR45iU0g", @@ -2167,6 +2254,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "w7BE3inS-NM", @@ -2191,6 +2279,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FM-5BPMnhm0", @@ -2215,6 +2304,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "MnNZNfixTOw", @@ -2239,6 +2329,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qe80EeU8cT8", @@ -2263,6 +2354,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-s2-6KYgqpQ", @@ -2287,6 +2379,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RSlp874hESE", @@ -2315,6 +2408,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "oTI3tRQ_-3k", @@ -2339,6 +2433,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_okA84gaEJw", @@ -2363,6 +2458,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pLHnnJRaP7Q", @@ -2387,6 +2483,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "H2hGrsExuyc", @@ -2411,6 +2508,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RsZvjqG2lec", @@ -2435,6 +2533,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qYRCiQ6d35w", @@ -2463,6 +2562,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("4qmFsgI-EiRWTFBMNWREeDY4MVQ0YlI3WkYxSXVXek92MW9tbFJiRTdQaUoaFmVnWlFWRHBEUjFtU0FRTUl1Z1ElM0Q%3D"), diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_nomusic.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_nomusic.snap index 2abbf05..30b53f4 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_nomusic.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_nomusic.snap @@ -59,6 +59,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RPGLMuxkLCs", @@ -83,6 +84,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "z-ALpnnQLrk", @@ -107,6 +109,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "_rrbTTv8zcQ", @@ -131,6 +134,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "JE16OKTawLw", @@ -155,6 +159,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RQNY0Wzm7DQ", @@ -179,6 +184,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "uhy24PKBkd0", @@ -203,6 +209,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "OL1hQadBHfs", @@ -227,6 +234,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "Zge_SUfk0r8", @@ -251,6 +259,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "yFGIeU_IDE4", @@ -275,6 +284,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "P6MVqfQzPIg", @@ -299,6 +309,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "9n0pLDn8Z_I", @@ -323,6 +334,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "oXbx2YtIkeQ", @@ -347,6 +359,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "pfBBTTwxo8Q", @@ -371,6 +384,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "WxtRqzxSAh0", @@ -395,6 +409,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "ianUckvxtLw", @@ -419,6 +434,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "eb2Ghj1g1ic", @@ -443,6 +459,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "8TpEsyVtCog", @@ -467,6 +484,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "KD_WAei4LMg", @@ -491,6 +509,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "qfpOCrtweKk", @@ -515,6 +534,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "6gv3nrOA_bQ", @@ -539,6 +559,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "waaic6UnkU8", @@ -563,6 +584,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "lSy4MLC_uV4", @@ -587,6 +609,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "BuN8-U_quok", @@ -611,6 +634,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "g_UTG10nzaQ", @@ -635,6 +659,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "kNykFWaDbGw", @@ -659,6 +684,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "gJF7vxCYTgY", @@ -683,6 +709,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "CodZMQ_Anc0", @@ -707,6 +734,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "oKHMTKJdZ_M", @@ -731,6 +759,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "--O_Eyok_eE", @@ -755,6 +784,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "2bT3ljKMSo8", @@ -779,6 +809,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "YRAX_slrbsI", @@ -803,6 +834,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "aRRbCEwUSuw", @@ -827,6 +859,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "5sV8SzTbJS8", @@ -851,6 +884,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "ZxxZlU2o1TE", @@ -875,6 +909,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "gIjo5at4AxE", @@ -899,6 +934,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "NSGk7-kyeEU", @@ -923,6 +959,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "cgJtZ7Otc4Y", @@ -947,6 +984,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "l5LQu3Q0nWY", @@ -971,6 +1009,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "YX4Z3ZlWUFc", @@ -995,6 +1034,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "LoyvqR41lKw", @@ -1019,6 +1059,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "HbQtMZbtx_Q", @@ -1043,6 +1084,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "0DHRbP9ecgw", @@ -1067,6 +1109,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "rFOFkvk-xus", @@ -1091,6 +1134,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "P8zxnSihJ_8", @@ -1115,6 +1159,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "RWgeHl9XkCY", @@ -1139,6 +1184,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "I1n539enNNY", @@ -1163,6 +1209,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "70VKekyZz5g", @@ -1187,6 +1234,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "2OWJ1bwFu6Y", @@ -1211,6 +1259,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "zLiSA2i-niw", @@ -1235,6 +1284,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "wyXlw7nMpko", @@ -1259,6 +1309,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "NrU4fhzvFpA", @@ -1283,6 +1334,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "1xhKegaA1hQ", @@ -1307,6 +1359,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "9F4lZ8psBtg", @@ -1331,6 +1384,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "G3uUtejX9to", @@ -1355,6 +1409,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "-0Xn5pViCss", @@ -1379,6 +1434,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "a7u71Fco99I", @@ -1403,6 +1459,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "H6uUbvcgKdk", @@ -1427,6 +1484,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "tPRTCauHtkw", @@ -1451,6 +1509,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "pMKAQExcarM", @@ -1475,6 +1534,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "7E-z-7KCdBI", @@ -1499,6 +1559,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "EPtbC0ZVddo", @@ -1523,6 +1584,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "TpPHng0eGJs", @@ -1547,6 +1609,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "rt2QFQwJYcs", @@ -1571,6 +1634,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "WPyfaztFDQ4", @@ -1595,6 +1659,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "5lmumP0DaUw", @@ -1619,6 +1684,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), ], ctoken: None, diff --git a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_short.snap b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_short.snap index 7f4f115..14a7a71 100644 --- a/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_short.snap +++ b/src/client/snapshots/rustypipe__client__music_playlist__tests__map_music_playlist_short.snap @@ -61,6 +61,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nBZlrbrBO1I", @@ -85,6 +86,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AcTDlsUej2w", @@ -109,6 +111,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "k6ZoE4RrcDs", @@ -133,6 +136,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2n5GKLdrTfk", @@ -157,6 +161,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "psuRGfAaju4", @@ -181,6 +186,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_JGGLJMpVks", @@ -205,6 +211,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1YUBbF24H44", @@ -229,6 +236,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "E0WRQpjckYg", @@ -253,6 +261,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mqiH0ZSkM9I", @@ -277,6 +286,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UAWcs5H-qgQ", @@ -301,6 +311,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bqO3Y5e4Dow", @@ -325,6 +336,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ouEezpuPc3A", @@ -349,6 +361,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "i-qT5n_5Mys", @@ -373,6 +386,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PMGY8fLwess", @@ -397,6 +411,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2ebfSItB0oM", @@ -421,6 +436,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "c4BLVznuWnU", @@ -445,6 +461,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "c0wUKCekI34", @@ -469,6 +486,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vNfgVjZF8_4", @@ -493,6 +511,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XPpTgCho5ZA", @@ -517,6 +536,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-oqAU5VxFWs", @@ -541,6 +561,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CA1VHbdq5hY", @@ -565,6 +586,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aNzCDt2eidg", @@ -589,6 +611,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "A48hOToMuRE", @@ -613,6 +636,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qHm9MG9xw1o", @@ -637,6 +661,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "74NhLkjIeMs", @@ -661,6 +686,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EptPhiK_q0E", @@ -685,6 +711,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "44u7_wQ1s0g", @@ -709,6 +736,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "toOyxylnNkI", @@ -733,6 +761,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ljXSjIph5ZM", @@ -757,6 +786,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DJFMRLIe-0o", @@ -785,6 +815,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "goqqohUitmw", @@ -809,6 +840,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_LwX7GCE5rI", @@ -833,6 +865,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7KHPC-kEQOA", @@ -861,6 +894,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "26PAgklYYvo", @@ -885,6 +919,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bO3S8CKafbE", @@ -909,6 +944,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tMsbeyeTtpk", @@ -933,6 +969,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fvXn3rmhdc4", @@ -957,6 +994,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2p4n7JgdCsc", @@ -981,6 +1019,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "HtNS1afUOnE", @@ -1005,6 +1044,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ufbDvPaVrzs", @@ -1029,6 +1069,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "H1_icnjg6MY", @@ -1053,6 +1094,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7Lna4Hu4-AQ", @@ -1081,6 +1123,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "K9qu2QMBguw", @@ -1113,6 +1156,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uWeqeQkjLto", @@ -1137,6 +1181,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "X_ZOGHUWwqE", @@ -1161,6 +1206,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mHeK0Cwr9sg", @@ -1185,6 +1231,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0Bf3CJZ4hvg", @@ -1209,6 +1256,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7TCncxWNcPU", @@ -1233,6 +1281,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PxNYvk_0Onw", @@ -1257,6 +1306,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WLoWBe9BRP4", @@ -1281,6 +1331,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1XYLKoEETVA", @@ -1305,6 +1356,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ghl_vkEV3tc", @@ -1329,6 +1381,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5qHRMFQ0pLg", @@ -1353,6 +1406,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "X-vispdELDo", @@ -1377,6 +1431,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "il_L6c_fOvs", @@ -1401,6 +1456,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hCjcgoubkPM", @@ -1425,6 +1481,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nwXlRq_QyTI", @@ -1449,6 +1506,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ZdsER1S3t8k", @@ -1477,6 +1535,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fyrsExw_LUg", @@ -1501,6 +1560,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BS4t017LSoA", @@ -1533,6 +1593,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0AYzzzBaPBI", @@ -1557,6 +1618,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zM0K3LC7Aak", @@ -1581,6 +1643,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1le0xDbrVj8", @@ -1605,6 +1668,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RdFaKz71-5M", @@ -1629,6 +1693,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "d6hUByfuhM4", @@ -1653,6 +1718,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-uxeu0MbNR0", @@ -1677,6 +1743,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "35VK8yonvsc", @@ -1701,6 +1768,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ELD3aRzbVQg", @@ -1725,6 +1793,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BD7HwXv18aU", @@ -1749,6 +1818,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WJJLfUwIVR4", @@ -1773,6 +1843,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "NjW1S0WIiJw", @@ -1797,6 +1868,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-4szr0EMrgk", @@ -1821,6 +1893,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "88NWeOGrxys", @@ -1853,6 +1926,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BxqtS-7GxFM", @@ -1877,6 +1951,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KUKt_LbaBnM", @@ -1901,6 +1976,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bhL7A8k6kU8", @@ -1925,6 +2001,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mUN36hFtazE", @@ -1949,6 +2026,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "dcBZP_pt0uY", @@ -1973,6 +2051,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "m342B1Vv3tM", @@ -1997,6 +2076,7 @@ MusicPlaylist( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "N_5RiRBvPSk", @@ -2029,6 +2109,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Q5kH0wg_sKo", @@ -2061,6 +2142,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "j9zlc5zufl8", @@ -2093,6 +2175,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ufxjiU7BgR4", @@ -2125,6 +2208,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7OfB_8rrtug", @@ -2157,6 +2241,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UqmvAc81XuM", @@ -2189,6 +2274,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QDULTFB8gSY", @@ -2221,6 +2307,7 @@ MusicPlaylist( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: None, diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_artist.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_artist.snap index 05732a9..9824ee8 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_artist.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_artist.snap @@ -54,6 +54,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "aZ1hziFhj1o", @@ -86,6 +87,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_l2IU1O3l6QK", @@ -154,6 +156,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "65Q7EdWnjqM", @@ -186,6 +189,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "EL72UcDZLSk", @@ -218,6 +222,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "b1kbLwvqugk", @@ -242,6 +247,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "3tmd-ClpJxA", @@ -266,6 +272,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "FuXNumBwDOM", @@ -290,6 +297,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_BiCQyyofUtj", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_default.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_default.snap index ae29e6a..8aa60c8 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_default.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_default.snap @@ -29,6 +29,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "NU611fxGyPU", @@ -53,6 +54,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "Yi2nsnpw5h0", @@ -77,6 +79,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "2Qefh0W_H88", @@ -101,6 +104,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "BL-aIpCLWnU", @@ -133,6 +137,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "PpKu3UsHYrk", @@ -165,6 +170,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "jynOfK8JB0E", @@ -197,6 +203,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "pgjQkcYD-rQ", @@ -221,6 +228,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "w2GXdb-pHo8", @@ -245,6 +253,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "JepNreB58TA", @@ -269,6 +278,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_rR0VQ4fTxPM", @@ -616,6 +626,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "GE0UAdxPTc0", @@ -640,6 +651,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "4gi9y3sTrXE", @@ -664,6 +676,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), User(UserItem( id: "UCOeTBeQwhOSvNcaZhxM1PUg", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_live.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_live.snap index b0f605b..ff12ea6 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_live.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_live.snap @@ -67,6 +67,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "Yx-sGL0xX-U", @@ -99,6 +100,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "HzdD8kbDzZA", @@ -131,6 +133,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "Zh7Un8gVFak", @@ -155,6 +158,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "BMnD36Abw_0", @@ -179,6 +183,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_UQFAF6UM4DN", @@ -611,6 +616,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "MiVivWh7zrA", @@ -635,6 +641,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "7-hMhhUO8b8", @@ -659,6 +666,7 @@ MusicSearchResult( track_type: episode, track_nr: None, by_va: false, + unavailable: false, )), User(UserItem( id: "UCdQrWgvHD9f-caMSn3SS-WQ", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_radio.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_radio.snap index c399053..d08f976 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_radio.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_radio.snap @@ -37,6 +37,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "VHLPvrlclmQ", @@ -69,6 +70,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "R9TPed_ohKM", @@ -101,6 +103,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "Ej1nxBxFSKc", @@ -125,6 +128,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "26OrUhkRa3c", @@ -149,6 +153,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "Idk-oFqn3kM", @@ -173,6 +178,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_CYbQPbuAWrt", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_typo.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_typo.snap index 2128d16..708bfcf 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_typo.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_main_typo.snap @@ -73,6 +73,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "pt0YvfnhGgI", @@ -105,6 +106,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "0yPnvetCm-U", @@ -137,6 +139,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "3ryohiCVq3M", @@ -161,6 +164,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "6Bt1KeMNqvc", @@ -185,6 +189,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Track(TrackItem( id: "5YQRHUItXTI", @@ -209,6 +214,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, )), Album(AlbumItem( id: "MPREb_V5f8YfHKp2j", diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_suggestion_default.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_suggestion_default.snap index e7e40c0..9846487 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_suggestion_default.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_suggestion_default.snap @@ -75,6 +75,7 @@ MusicSearchSuggestion( track_type: track, track_nr: None, by_va: false, + unavailable: false, )), ], ) diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_default.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_default.snap index 1a7fbc3..c47ba13 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_default.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_default.snap @@ -37,6 +37,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cATe8Toht70", @@ -73,6 +74,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0I1UpXSYdOQ", @@ -105,6 +107,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9G2tG8V5_PY", @@ -137,6 +140,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WwNKyoizf8k", @@ -169,6 +173,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kS1o36LXQkc", @@ -201,6 +206,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UQQ6L1j6mXE", @@ -233,6 +239,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9l9dCro-7l8", @@ -265,6 +272,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "S_PRpDtgUfI", @@ -297,6 +305,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Xt_ReZc0gnw", @@ -329,6 +338,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "diN3WCxpqis", @@ -361,6 +371,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "9q3FfH_57Rc", @@ -393,6 +404,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "U29V08A9yBs", @@ -429,6 +441,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "HHEKbGlLoEM", @@ -461,6 +474,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qE_dGvQG1rU", @@ -493,6 +507,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1tyPs3ccT7E", @@ -529,6 +544,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "6pSmQ-MHKbg", @@ -561,6 +577,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rNsISA-kWzM", @@ -593,6 +610,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AdvPpJVvyEg", @@ -625,6 +643,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7q7o-kjIKpo", @@ -657,6 +676,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("EqQDEgtibGFjayBtYW1iYRqUA0VnV0tBUUlJQVVnVWFnd1FBeEFFRUFrUURoQUtFQVdDQVF0Q1RDMWhTWEJEVEZkdVZZSUJDMk5CVkdVNFZHOW9kRGN3Z2dFTE1Fa3hWWEJZVTFsa1QxR0NBUXM1UnpKMFJ6aFdOVjlRV1lJQkMxZDNUa3Q1YjJsNlpqaHJnZ0VMYTFNeGJ6TTJURmhSYTJPQ0FRdFZVVkUyVERGcU5tMVlSWUlCQ3psc09XUkRjbTh0TjJ3NGdnRUxVMTlRVW5CRWRHZFZaa21DQVF0WWRGOVNaVnBqTUdkdWQ0SUJDMlJwVGpOWFEzaHdjV2x6Z2dFTE9YRXpSbVpJWHpVM1VtT0NBUXRWTWpsV01EaEJPWGxDYzRJQkMwaElSVXRpUjJ4TWIwVk5nZ0VMY1VWZlpFZDJVVWN4Y2xXQ0FRdEVXak14Y0hoNVdXaFNhNElCQ3pad1UyMVJMVTFJUzJKbmdnRUxjazV6U1ZOQkxXdFhlazJDQVF0QlpIWlFjRXBXZG5sRlo0SUJDemR4TjI4dGEycEpTM0J2GPHq0C4%3D"), diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_no_artist_link.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_no_artist_link.snap index 89e49d0..25fd51f 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_no_artist_link.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_no_artist_link.snap @@ -41,6 +41,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OJ5ZittaTCk", @@ -73,6 +74,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "H199HKaUk3g", @@ -105,6 +107,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UlNOkZEcSjQ", @@ -137,6 +140,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "L61sF-655Zw", @@ -169,6 +173,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "bOK90e8P3k0", @@ -201,6 +206,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "oRHLx2mc2zY", @@ -241,6 +247,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: None, diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_typo.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_typo.snap index b66f30c..f5dc29e 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_typo.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_typo.snap @@ -37,6 +37,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pt0YvfnhGgI", @@ -69,6 +70,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VinJmH-uidY", @@ -101,6 +103,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YmSmymHRnEE", @@ -133,6 +136,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TgfIbiHCOLo", @@ -165,6 +169,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lCi6N_uq3vE", @@ -197,6 +202,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QIjqe2B3RdQ", @@ -229,6 +235,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "q2pUotlXPeM", @@ -261,6 +268,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0yPnvetCm-U", @@ -293,6 +301,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EU5Vly60VGU", @@ -325,6 +334,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UnxQ0TI4IMs", @@ -357,6 +367,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ufpny1KxwcU", @@ -389,6 +400,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "duzWgZFJNwA", @@ -421,6 +433,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "rnXq-1n0lt0", @@ -453,6 +466,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vHkqdC6-rOI", @@ -485,6 +499,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "nTlceSET_b8", @@ -517,6 +532,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "D8GhmRiIfxI", @@ -549,6 +565,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "01CS-jTaY1U", @@ -581,6 +598,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2sKkKKKXO28", @@ -613,6 +631,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "czlgl6n9voM", @@ -645,6 +664,7 @@ MusicSearchResult( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("EqcDEg5saWJsaW5nc21lbnNjaBqUA0VnV0tBUUlJQVVnVWFnd1FBeEFFRUFrUURoQUtFQVdDQVFzMk5EZzFVR2hQZEVoNldZSUJDM0IwTUZsMlptNW9SMmRKZ2dFTFZtbHVTbTFJTFhWcFpGbUNBUXRaYlZOdGVXMUlVbTVGUllJQkMxUm5aa2xpYVVoRFQweHZnZ0VMYkVOcE5rNWZkWEV6ZGtXQ0FRdFJTV3B4WlRKQ00xSmtVWUlCQzNFeWNGVnZkR3hZVUdWTmdnRUxNSGxRYm5abGRFTnRMVldDQVF0RlZUVldiSGsyTUZaSFZZSUJDMVZ1ZUZFd1ZFazBTVTF6Z2dFTGRXWndibmt4UzNoM1kxV0NBUXRrZFhwWFoxcEdTazUzUVlJQkMzSnVXSEV0TVc0d2JIUXdnZ0VMZGtocmNXUkROaTF5VDBtQ0FRdHVWR3hqWlZORlZGOWlPSUlCQzBRNFIyaHRVbWxKWm5oSmdnRUxNREZEVXkxcVZHRlpNVldDQVFzeWMwdHJTMHRMV0U4eU9JSUJDMk42Ykdkc05tNDVkbTlOGPHq0C4%3D"), diff --git a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_videos.snap b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_videos.snap index 0bd76fe..9298f11 100644 --- a/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_videos.snap +++ b/src/client/snapshots/rustypipe__client__music_search__tests__map_music_search_tracks_videos.snap @@ -29,6 +29,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vbl9KrZxOF8", @@ -53,6 +54,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "eMfROJt0a7Q", @@ -77,6 +79,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1ktLEhfkBCI", @@ -101,6 +104,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2hAlp3Khsnk", @@ -125,6 +129,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CHixjhwY0ek", @@ -149,6 +154,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8YXKgZ393Ec", @@ -173,6 +179,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KFNznAXnjXc", @@ -197,6 +204,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hDhJeJZmTDA", @@ -221,6 +229,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "6kKSDXiip_8", @@ -245,6 +254,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vfzlr70ogaI", @@ -269,6 +279,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Fjth6cKGI88", @@ -293,6 +304,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fznwvW9Kn4s", @@ -317,6 +329,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Jore0zZW-_M", @@ -341,6 +354,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_THM-2Ph-6I", @@ -365,6 +379,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "koJAGIUlnD0", @@ -389,6 +404,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4tvQPrHcR4w", @@ -413,6 +429,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CUh6MTvB_4E", @@ -437,6 +454,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4TWR90KJl84", @@ -461,6 +479,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Cw7eMibV-Xk", @@ -485,6 +504,7 @@ MusicSearchResult( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("EqQDEgtibGFjayBtYW1iYRqUA0VnV0tBUUlRQVVnVWFnd1FBeEFFRUFrUURoQUtFQVdDQVF0YVpXVnljbTUxVEdrMVJZSUJDM1ppYkRsTGNscDRUMFk0Z2dFTFpVMW1VazlLZERCaE4xR0NBUXN4YTNSTVJXaG1hMEpEU1lJQkN6Sm9RV3h3TTB0b2MyNXJnZ0VMUTBocGVHcG9kMWt3Wld1Q0FRczRXVmhMWjFvek9UTkZZNElCQzB0R1RucHVRVmh1YWxoamdnRUxhRVJvU21WS1dtMVVSRUdDQVFzMmEwdFRSRmhwYVhCZk9JSUJDM1ptZW14eU56QnZaMkZKZ2dFTFJtcDBhRFpqUzBkSk9EaUNBUXRtZW01M2RsYzVTMjQwYzRJQkMwcHZjbVV3ZWxwWExWOU5nZ0VMWDFSSVRTMHlVR2d0TmttQ0FRdHJiMHBCUjBsVmJHNUVNSUlCQ3pSMGRsRlFja2hqVWpSM2dnRUxRMVZvTmsxVWRrSmZORVdDQVFzMFZGZFNPVEJMU213NE5JSUJDME4zTjJWTmFXSldMVmhyGPHq0C4%3D"), diff --git a/src/client/snapshots/rustypipe__client__music_userdata__tests__map_history.snap b/src/client/snapshots/rustypipe__client__music_userdata__tests__map_history.snap index d025f4a..06d0fe8 100644 --- a/src/client/snapshots/rustypipe__client__music_userdata__tests__map_history.snap +++ b/src/client/snapshots/rustypipe__client__music_userdata__tests__map_history.snap @@ -1,5 +1,5 @@ --- -source: src/client/music_history.rs +source: src/client/music_userdata.rs expression: map_res.c --- Paginator( @@ -37,6 +37,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -73,6 +74,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -109,6 +111,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -145,6 +148,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -181,6 +185,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -217,6 +222,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -257,6 +263,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -285,6 +292,7 @@ Paginator( track_type: episode, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Today"), @@ -321,6 +329,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -357,6 +366,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -393,6 +403,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -429,6 +440,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -469,6 +481,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -505,6 +518,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -541,6 +555,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -577,6 +592,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -617,6 +633,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -653,6 +670,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -689,6 +707,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -725,6 +744,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -761,6 +781,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -797,6 +818,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), @@ -829,6 +851,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), playback_date: "[date]", playback_date_txt: Some("Last week"), diff --git a/src/client/snapshots/rustypipe__client__pagination__tests__map_playlist_tracks.snap b/src/client/snapshots/rustypipe__client__pagination__tests__map_playlist_tracks.snap index 1c3a627..d005c8a 100644 --- a/src/client/snapshots/rustypipe__client__pagination__tests__map_playlist_tracks.snap +++ b/src/client/snapshots/rustypipe__client__pagination__tests__map_playlist_tracks.snap @@ -28,6 +28,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "f9g6NCHQrcE", @@ -56,6 +57,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CAVfEwrwT_o", @@ -84,6 +86,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "VUr9JZQ8F2g", @@ -108,6 +111,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XQat6rNNbdQ", @@ -132,6 +136,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "EQyU6fGDn0c", @@ -156,6 +161,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g4poKgQZX6w", @@ -180,6 +186,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "YTHr7gxwYUQ", @@ -204,6 +211,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "MfCSDn6q6j4", @@ -228,6 +236,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "gx9KFXb5x_o", @@ -252,6 +261,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "d7R7DQ5tlQo", @@ -276,6 +286,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cZPjgcqHSa8", @@ -300,6 +311,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ogDLdREonWY", @@ -324,6 +336,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pRQpKprUUPY", @@ -348,6 +361,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "qZoQw9b4uCo", @@ -372,6 +386,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "q23qghoF6Nk", @@ -396,6 +411,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "yU0aKa7PFBg", @@ -420,6 +436,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DVCAqvypaCc", @@ -444,6 +461,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XdnI7sm6LeQ", @@ -468,6 +486,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KcOXNSJtFLg", @@ -492,6 +511,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "K0UxHXZwgsg", @@ -516,6 +536,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "eyyNwOSQ3Yg", @@ -540,6 +561,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1yskotqNuXI", @@ -564,6 +586,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "C03n4AAiL9w", @@ -588,6 +611,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "a2wNRTKRusM", @@ -612,6 +636,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AIf61iHwWMQ", @@ -636,6 +661,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BixqbSRjY2Y", @@ -660,6 +686,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Acgy-3d4P6o", @@ -684,6 +711,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5M_yA9M7yNc", @@ -708,6 +736,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PjJuezhos3U", @@ -732,6 +761,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XMutaJI2-kc", @@ -756,6 +786,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Xac6Q7hcZkQ", @@ -780,6 +811,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "JfwjsjBcDoU", @@ -804,6 +836,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zshiQUV3ohw", @@ -828,6 +861,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g1eTAt1_VAM", @@ -856,6 +890,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "c3rLrFC8igY", @@ -880,6 +915,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: true, ), TrackItem( id: "1im4DNEYzEM", @@ -908,6 +944,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8BUxw9ocM2s", @@ -932,6 +969,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g4cSpnGbHPE", @@ -960,6 +998,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1Sdj9MiCowQ", @@ -988,6 +1027,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2DbR35g-0ZY", @@ -1012,6 +1052,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "j09hpp3AxIE", @@ -1036,6 +1077,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "J3GN6JXjV3g", @@ -1060,6 +1102,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "pULl-p02upM", @@ -1084,6 +1127,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "O6By8JeCtQQ", @@ -1108,6 +1152,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "NGn3IYQ7M7E", @@ -1132,6 +1177,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "o43oI5x86dI", @@ -1156,6 +1202,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7TNqUrINxzs", @@ -1180,6 +1227,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "f3BD5Zm3cp0", @@ -1208,6 +1256,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "sF4yTDp95Eo", @@ -1232,6 +1281,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1EwLNHg6ejY", @@ -1256,6 +1306,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-l75qaSDWe8", @@ -1280,6 +1331,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7h7ntYLLrfQ", @@ -1304,6 +1356,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ApUl3Ops69M", @@ -1328,6 +1381,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2YcJ8Wightw", @@ -1352,6 +1406,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "W3q8Od5qJio", @@ -1376,6 +1431,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WPFLAjmWCtk", @@ -1400,6 +1456,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tC76tIp0kBk", @@ -1424,6 +1481,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kiMG_JV2gbo", @@ -1448,6 +1506,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "CrYYg_atdtk", @@ -1472,6 +1531,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XTPGpBBwt1w", @@ -1496,6 +1556,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "uC08L4xxjNM", @@ -1520,6 +1581,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5fAoV_AAMf0", @@ -1544,6 +1606,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "u5Vz7obL460", @@ -1568,6 +1631,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ZPJlyRv_IGI", @@ -1592,6 +1656,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "s2SLbln-JwE", @@ -1616,6 +1681,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "28xHtRw6pG8", @@ -1640,6 +1706,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "joWoKqUTRvc", @@ -1664,6 +1731,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "XNMFTqhcNrE", @@ -1688,6 +1756,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "v3vPLgJ9FX8", @@ -1716,6 +1785,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UFXOd179kOA", @@ -1740,6 +1810,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4xRsDnKgHZc", @@ -1764,6 +1835,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "mE3IjoEqMqY", @@ -1788,6 +1860,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "E7e5vxKerqA", @@ -1812,6 +1885,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "axmZ_5Rx4Go", @@ -1836,6 +1910,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "44Ig6BsOCYA", @@ -1860,6 +1935,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "3iLBFEJjdN0", @@ -1884,6 +1960,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "M-ncq2eHF_k", @@ -1908,6 +1985,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-AJoJ-ggiKI", @@ -1932,6 +2010,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "cgb-zp9DDHg", @@ -1960,6 +2039,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Q7ZXg3KQLt0", @@ -1984,6 +2064,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ysAEZOwp5rM", @@ -2008,6 +2089,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "m5vfng33SVE", @@ -2032,6 +2114,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "yMfgjVlGbUE", @@ -2056,6 +2139,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OQIYEPe6DWY", @@ -2080,6 +2164,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "5FS8RIH7BpI", @@ -2104,6 +2189,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "zSRKgFB9piY", @@ -2128,6 +2214,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "e4eHhgwHCME", @@ -2156,6 +2243,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "q3hZvho7jNk", @@ -2180,6 +2268,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0nWysyj_Z4Y", @@ -2204,6 +2293,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "aGCcLWU0OVo", @@ -2228,6 +2318,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OQsXLK4MeEA", @@ -2252,6 +2343,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "xm7dxIqOO2M", @@ -2276,6 +2368,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "jlaaByab4Zk", @@ -2304,6 +2397,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "KG9-jSqXz4U", @@ -2328,6 +2422,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "7dISZnwsBSA", @@ -2352,6 +2447,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "F_PPdS-PB14", @@ -2376,6 +2472,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DMg9idvVY8M", @@ -2400,6 +2497,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DGEmoSFI94Y", @@ -2424,6 +2522,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "BtZufymxHvE", @@ -2452,6 +2551,7 @@ Paginator( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("4qmFsgI8EiRWTFBMNWREeDY4MVQ0YlI3WkYxSXVXek92MW9tbFJiRTdQaUoaFGVnZFFWRHBEVGtGQ2tnRURDTG9F"), diff --git a/src/client/snapshots/rustypipe__client__pagination__tests__map_radio_tracks.snap b/src/client/snapshots/rustypipe__client__pagination__tests__map_radio_tracks.snap index 2f5c164..ea322b1 100644 --- a/src/client/snapshots/rustypipe__client__pagination__tests__map_radio_tracks.snap +++ b/src/client/snapshots/rustypipe__client__pagination__tests__map_radio_tracks.snap @@ -56,6 +56,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hh5GKVa8VtM", @@ -108,6 +109,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RdU3F5vN3_s", @@ -160,6 +162,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OXWz_x6-dro", @@ -212,6 +215,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ghrlZIMDzbM", @@ -264,6 +268,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "QiziJ40kTz0", @@ -316,6 +321,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "950BdJKBhGo", @@ -368,6 +374,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "tkzYyEp4zB4", @@ -420,6 +427,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ffqliB42Nh4", @@ -472,6 +480,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vFFT1iAUNDE", @@ -528,6 +537,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8JXc4idKS_c", @@ -580,6 +590,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4JJFrjkRxmo", @@ -632,6 +643,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0EK_M2taRIM", @@ -684,6 +696,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "04tYkKUPPv4", @@ -736,6 +749,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "W0x7GcZkvH4", @@ -788,6 +802,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "INLFlN-PZq4", @@ -840,6 +855,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "GhL8GUjXEfk", @@ -892,6 +908,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "TaZkqPK0sbw", @@ -948,6 +965,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ogKU5EQ0Wn0", @@ -1000,6 +1018,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "g92HIac9ufA", @@ -1052,6 +1071,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_E6gDU0m_hk", @@ -1104,6 +1124,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FrEDny55ch8", @@ -1156,6 +1177,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "-uOShlFu1v8", @@ -1208,6 +1230,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "PyyT5tHbOLw", @@ -1260,6 +1283,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("CBkSSBILUHl5VDV0SGJPTHciEVJEQU1WTTduaWdYUVMxWGIwMg53QUVCOGdFQ2VBRSUzRDgY0AEB-gEQQzcxNUY2RDFGQjIwNEQwQRgKggEVUFQ6RWd0UWVYbFVOWFJJWWs5TWR3"), diff --git a/src/client/snapshots/rustypipe__client__pagination__tests__map_saved_tracks.snap b/src/client/snapshots/rustypipe__client__pagination__tests__map_saved_tracks.snap index 65aea83..f343dca 100644 --- a/src/client/snapshots/rustypipe__client__pagination__tests__map_saved_tracks.snap +++ b/src/client/snapshots/rustypipe__client__pagination__tests__map_saved_tracks.snap @@ -36,6 +36,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "0uSu-jHdDd4", @@ -68,6 +69,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "11pkE_azpBQ", @@ -100,6 +102,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "1tJPy7XlfCQ", @@ -132,6 +135,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "2JpUBTLjfPA", @@ -164,6 +168,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "6WiuMIp9B6Y", @@ -196,6 +201,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "8nfNNAlsTTA", @@ -228,6 +234,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "C1U6oXpz4As", @@ -260,6 +267,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "DvKw0jTUN-s", @@ -292,6 +300,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "GDSVX--bsRU", @@ -324,6 +333,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "I-ArzgPbNx8", @@ -356,6 +366,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OElgvIuT8TY", @@ -388,6 +399,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "RGlOEBJyhrc", @@ -420,6 +432,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "UUCM1WR611g", @@ -452,6 +465,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "WlzrZsEtWbs", @@ -484,6 +498,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "apY7iYoYtD8", @@ -516,6 +531,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "azSEPwrxG2c", @@ -548,6 +564,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "b9FNHTk-tAM", @@ -580,6 +597,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "eAeGr78VYxM", @@ -612,6 +630,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "efCzrXOWM0Q", @@ -644,6 +663,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "fbmHQLiF1qs", @@ -676,6 +696,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "h0qhAXLom-Y", @@ -708,6 +729,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hTL2vAvAbNM", @@ -740,6 +762,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "hptOG4EVgMs", @@ -772,6 +795,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "iRIlHsC8xL8", @@ -804,6 +828,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("4qmFsgJcEhRGRW11c2ljX2xpa2VkX3ZpZGVvcxpEQ0JwNkprTkNhMUZIVW05SlEwRkZVVUZvYjBOYVZ6UnBSRUZxWXpsaVF6ZENhRU4yT1ZwdFRVRjNnZ01HS2dRSUFCQUI%3D"), diff --git a/src/client/snapshots/rustypipe__client__pagination__tests__map_search_tracks.snap b/src/client/snapshots/rustypipe__client__pagination__tests__map_search_tracks.snap index 6e7e4ef..731e3e6 100644 --- a/src/client/snapshots/rustypipe__client__pagination__tests__map_search_tracks.snap +++ b/src/client/snapshots/rustypipe__client__pagination__tests__map_search_tracks.snap @@ -36,6 +36,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "vMZqNPZADFw", @@ -68,6 +69,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "C8B-nBnB7Bk", @@ -100,6 +102,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "29MOu6Y781I", @@ -132,6 +135,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "AdvPpJVvyEg", @@ -164,6 +168,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "kv3Z269PQvE", @@ -196,6 +201,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "y74ZqAkFkK4", @@ -228,6 +234,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "ZVnqAUnj-1Y", @@ -260,6 +267,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "REmUidcJt5I", @@ -292,6 +300,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "63sEilefjtQ", @@ -324,6 +333,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_LGy1K5vmq8", @@ -356,6 +366,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Ak98OIfed8o", @@ -388,6 +399,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "_aSqdZKxcuU", @@ -420,6 +432,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "6Lb4bmEEfnY", @@ -452,6 +465,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "4lrp5FWFIak", @@ -484,6 +498,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "Kk8vT1o_gYE", @@ -524,6 +539,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "FbUrY0GdO88", @@ -556,6 +572,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "OFesVwAdT80", @@ -588,6 +605,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "lNeJjPPKE1g", @@ -620,6 +638,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), TrackItem( id: "SW_woyyA1Bg", @@ -652,6 +671,7 @@ Paginator( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), ], ctoken: Some("EqQDEgtibGFjayBtYW1iYRqUA0VnV0tBUUlJQVVnb2Fnd1FBeEFFRUFrUURoQUtFQVdDQVF0eVRuTkpVMEV0YTFkNlRZSUJDM1pOV25GT1VGcEJSRVozZ2dFTFF6aENMVzVDYmtJM1FtdUNBUXN5T1UxUGRUWlpOemd4U1lJQkMwRmtkbEJ3U2xaMmVVVm5nZ0VMYTNZeldqSTJPVkJSZGtXQ0FRdDVOelJhY1VGclJtdExOSUlCQzFwV2JuRkJWVzVxTFRGWmdnRUxVa1Z0Vldsa1kwcDBOVW1DQVFzMk0zTkZhV3hsWm1wMFVZSUJDMTlNUjNreFN6VjJiWEU0Z2dFTFFXczVPRTlKWm1Wa09HLUNBUXRmWVZOeFpGcExlR04xVllJQkN6Wk1ZalJpYlVWRlptNVpnZ0VMTkd4eWNEVkdWMFpKWVd1Q0FRdExhemgyVkRGdlgyZFpSWUlCQzBaaVZYSlpNRWRrVHpnNGdnRUxUMFpsYzFaM1FXUlVPRENDQVF0c1RtVkthbEJRUzBVeFo0SUJDMU5YWDNkdmVYbEJNVUpuGPHq0C4%3D"), diff --git a/src/model/mod.rs b/src/model/mod.rs index 1829adc..9ceb38f 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1049,6 +1049,8 @@ pub struct TrackItem { pub track_nr: Option, /// Is the track by 'Various artists'? pub by_va: bool, + /// Is the track unavailable on YouTube Music? + pub unavailable: bool, } /// YouTube Music artist list item diff --git a/tests/snapshots/youtube__music_album_audiobook.snap b/tests/snapshots/youtube__music_album_audiobook.snap index 3f3bd96..7c5ce80 100644 --- a/tests/snapshots/youtube__music_album_audiobook.snap +++ b/tests/snapshots/youtube__music_album_audiobook.snap @@ -35,6 +35,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "B12pddzDBAs", @@ -51,6 +52,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "J4jGyX1f998", @@ -67,6 +69,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "xSwgv3_59Jg", @@ -83,6 +86,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "WzmdYCTH-ZI", @@ -99,6 +103,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "5OQfpOqbaY8", @@ -115,6 +120,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "7UeTt_0QS1M", @@ -131,6 +137,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "2RP6xm9TWPA", @@ -147,6 +154,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "4EiyZzC98vA", @@ -163,6 +171,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "d7c18oVKGuw", @@ -179,6 +188,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "bKCEe30O-9E", @@ -195,6 +205,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "jzZVXzd-IgI", @@ -211,6 +222,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "A5GNL_YP6rc", @@ -227,6 +239,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "TihFSZ8IZHo", @@ -243,6 +256,7 @@ MusicAlbum( track_type: track, track_nr: Some(14), by_va: false, + unavailable: false, ), TrackItem( id: "1QfMUYC9BR8", @@ -259,6 +273,7 @@ MusicAlbum( track_type: track, track_nr: Some(15), by_va: false, + unavailable: false, ), TrackItem( id: "AhuZlNLGQK0", @@ -275,6 +290,7 @@ MusicAlbum( track_type: track, track_nr: Some(16), by_va: false, + unavailable: false, ), TrackItem( id: "Twrr-ReUadg", @@ -291,6 +307,7 @@ MusicAlbum( track_type: track, track_nr: Some(17), by_va: false, + unavailable: false, ), TrackItem( id: "F6JJmeRk3NY", @@ -307,6 +324,7 @@ MusicAlbum( track_type: track, track_nr: Some(18), by_va: false, + unavailable: false, ), TrackItem( id: "bERcihhazVQ", @@ -323,6 +341,7 @@ MusicAlbum( track_type: track, track_nr: Some(19), by_va: false, + unavailable: false, ), TrackItem( id: "zmsB0ixj4L8", @@ -339,6 +358,7 @@ MusicAlbum( track_type: track, track_nr: Some(20), by_va: false, + unavailable: false, ), TrackItem( id: "_AeZoRyNZ0Q", @@ -355,6 +375,7 @@ MusicAlbum( track_type: track, track_nr: Some(21), by_va: false, + unavailable: false, ), TrackItem( id: "iX_GlsDkgSs", @@ -371,6 +392,7 @@ MusicAlbum( track_type: track, track_nr: Some(22), by_va: false, + unavailable: false, ), TrackItem( id: "TdR76HsPNZI", @@ -387,6 +409,7 @@ MusicAlbum( track_type: track, track_nr: Some(23), by_va: false, + unavailable: false, ), TrackItem( id: "gz6e4SE3L_8", @@ -403,6 +426,7 @@ MusicAlbum( track_type: track, track_nr: Some(24), by_va: false, + unavailable: false, ), TrackItem( id: "jrZYEoLg1lY", @@ -419,6 +443,7 @@ MusicAlbum( track_type: track, track_nr: Some(25), by_va: false, + unavailable: false, ), TrackItem( id: "z4CRs-_heos", @@ -435,6 +460,7 @@ MusicAlbum( track_type: track, track_nr: Some(26), by_va: false, + unavailable: false, ), TrackItem( id: "RM8Jk0AhLNY", @@ -451,6 +477,7 @@ MusicAlbum( track_type: track, track_nr: Some(27), by_va: false, + unavailable: false, ), TrackItem( id: "mICWuD7UbpE", @@ -467,6 +494,7 @@ MusicAlbum( track_type: track, track_nr: Some(28), by_va: false, + unavailable: false, ), TrackItem( id: "ieJk5E2FrTQ", @@ -483,6 +511,7 @@ MusicAlbum( track_type: track, track_nr: Some(29), by_va: false, + unavailable: false, ), TrackItem( id: "DWa2LY_SXyQ", @@ -499,6 +528,7 @@ MusicAlbum( track_type: track, track_nr: Some(30), by_va: false, + unavailable: false, ), TrackItem( id: "vBzgEusfeIU", @@ -515,6 +545,7 @@ MusicAlbum( track_type: track, track_nr: Some(31), by_va: false, + unavailable: false, ), TrackItem( id: "t3U95rPrFrY", @@ -531,6 +562,7 @@ MusicAlbum( track_type: track, track_nr: Some(32), by_va: false, + unavailable: false, ), TrackItem( id: "F0HVKbHFXOA", @@ -547,6 +579,7 @@ MusicAlbum( track_type: track, track_nr: Some(33), by_va: false, + unavailable: false, ), TrackItem( id: "VB6RraDXSEM", @@ -563,6 +596,7 @@ MusicAlbum( track_type: track, track_nr: Some(34), by_va: false, + unavailable: false, ), TrackItem( id: "tqi9j41-xhU", @@ -579,6 +613,7 @@ MusicAlbum( track_type: track, track_nr: Some(35), by_va: false, + unavailable: false, ), TrackItem( id: "tyCtChD9gNY", @@ -595,6 +630,7 @@ MusicAlbum( track_type: track, track_nr: Some(36), by_va: false, + unavailable: false, ), TrackItem( id: "fn2pYeEM288", @@ -611,6 +647,7 @@ MusicAlbum( track_type: track, track_nr: Some(37), by_va: false, + unavailable: false, ), TrackItem( id: "1hphnoWnbFM", @@ -627,6 +664,7 @@ MusicAlbum( track_type: track, track_nr: Some(38), by_va: false, + unavailable: false, ), TrackItem( id: "cnige70U6nw", @@ -643,6 +681,7 @@ MusicAlbum( track_type: track, track_nr: Some(39), by_va: false, + unavailable: false, ), TrackItem( id: "N_DmWGxuDg8", @@ -659,6 +698,7 @@ MusicAlbum( track_type: track, track_nr: Some(40), by_va: false, + unavailable: false, ), TrackItem( id: "v536-IdXIqc", @@ -675,6 +715,7 @@ MusicAlbum( track_type: track, track_nr: Some(41), by_va: false, + unavailable: false, ), TrackItem( id: "ZkFmAt8MS90", @@ -691,6 +732,7 @@ MusicAlbum( track_type: track, track_nr: Some(42), by_va: false, + unavailable: false, ), TrackItem( id: "tzCu8HlkxDE", @@ -707,6 +749,7 @@ MusicAlbum( track_type: track, track_nr: Some(43), by_va: false, + unavailable: false, ), TrackItem( id: "mJGIaHm03Tc", @@ -723,6 +766,7 @@ MusicAlbum( track_type: track, track_nr: Some(44), by_va: false, + unavailable: false, ), TrackItem( id: "qsZee8A6QB0", @@ -739,6 +783,7 @@ MusicAlbum( track_type: track, track_nr: Some(45), by_va: false, + unavailable: false, ), TrackItem( id: "8Wpxs6QRqu4", @@ -755,6 +800,7 @@ MusicAlbum( track_type: track, track_nr: Some(46), by_va: false, + unavailable: false, ), TrackItem( id: "82eUY70WLqE", @@ -771,6 +817,7 @@ MusicAlbum( track_type: track, track_nr: Some(47), by_va: false, + unavailable: false, ), TrackItem( id: "03KktUmXdMg", @@ -787,6 +834,7 @@ MusicAlbum( track_type: track, track_nr: Some(48), by_va: false, + unavailable: false, ), TrackItem( id: "ki5f2zgRAjI", @@ -803,6 +851,7 @@ MusicAlbum( track_type: track, track_nr: Some(49), by_va: false, + unavailable: false, ), TrackItem( id: "O05G6kmQW2g", @@ -819,6 +868,7 @@ MusicAlbum( track_type: track, track_nr: Some(50), by_va: false, + unavailable: false, ), TrackItem( id: "Dayba7Kf90U", @@ -835,6 +885,7 @@ MusicAlbum( track_type: track, track_nr: Some(51), by_va: false, + unavailable: false, ), TrackItem( id: "V1G2tVnsyfU", @@ -851,6 +902,7 @@ MusicAlbum( track_type: track, track_nr: Some(52), by_va: false, + unavailable: false, ), TrackItem( id: "ugegWLyUGjg", @@ -867,6 +919,7 @@ MusicAlbum( track_type: track, track_nr: Some(53), by_va: false, + unavailable: false, ), TrackItem( id: "o0OY_x2Sb1E", @@ -883,6 +936,7 @@ MusicAlbum( track_type: track, track_nr: Some(54), by_va: false, + unavailable: false, ), TrackItem( id: "aefFzoIlJZY", @@ -899,6 +953,7 @@ MusicAlbum( track_type: track, track_nr: Some(55), by_va: false, + unavailable: false, ), TrackItem( id: "Wp6E3VPS2mM", @@ -915,6 +970,7 @@ MusicAlbum( track_type: track, track_nr: Some(56), by_va: false, + unavailable: false, ), TrackItem( id: "tLuYgcr6Dpg", @@ -931,6 +987,7 @@ MusicAlbum( track_type: track, track_nr: Some(57), by_va: false, + unavailable: false, ), TrackItem( id: "375_yqG6YbI", @@ -947,6 +1004,7 @@ MusicAlbum( track_type: track, track_nr: Some(58), by_va: false, + unavailable: false, ), TrackItem( id: "ANqW0THg1Pw", @@ -963,6 +1021,7 @@ MusicAlbum( track_type: track, track_nr: Some(59), by_va: false, + unavailable: false, ), TrackItem( id: "3qfEL7ZCgL8", @@ -979,6 +1038,7 @@ MusicAlbum( track_type: track, track_nr: Some(60), by_va: false, + unavailable: false, ), TrackItem( id: "_G8r-gk0msY", @@ -995,6 +1055,7 @@ MusicAlbum( track_type: track, track_nr: Some(61), by_va: false, + unavailable: false, ), TrackItem( id: "whI1u7a_rSU", @@ -1011,6 +1072,7 @@ MusicAlbum( track_type: track, track_nr: Some(62), by_va: false, + unavailable: false, ), TrackItem( id: "X2swFoUEp30", @@ -1027,6 +1089,7 @@ MusicAlbum( track_type: track, track_nr: Some(63), by_va: false, + unavailable: false, ), TrackItem( id: "5nXXHqVDIqY", @@ -1043,6 +1106,7 @@ MusicAlbum( track_type: track, track_nr: Some(64), by_va: false, + unavailable: false, ), TrackItem( id: "AgT-3d32lkQ", @@ -1059,6 +1123,7 @@ MusicAlbum( track_type: track, track_nr: Some(65), by_va: false, + unavailable: false, ), TrackItem( id: "NvR28TRH1Kc", @@ -1075,6 +1140,7 @@ MusicAlbum( track_type: track, track_nr: Some(66), by_va: false, + unavailable: false, ), TrackItem( id: "218UZATQgwY", @@ -1091,6 +1157,7 @@ MusicAlbum( track_type: track, track_nr: Some(67), by_va: false, + unavailable: false, ), TrackItem( id: "rCUpwhyh7ag", @@ -1107,6 +1174,7 @@ MusicAlbum( track_type: track, track_nr: Some(68), by_va: false, + unavailable: false, ), TrackItem( id: "FseNJJS42Wk", @@ -1123,6 +1191,7 @@ MusicAlbum( track_type: track, track_nr: Some(69), by_va: false, + unavailable: false, ), TrackItem( id: "ahufTwdimiY", @@ -1139,6 +1208,7 @@ MusicAlbum( track_type: track, track_nr: Some(70), by_va: false, + unavailable: false, ), TrackItem( id: "w_hYzT2BSz0", @@ -1155,6 +1225,7 @@ MusicAlbum( track_type: track, track_nr: Some(71), by_va: false, + unavailable: false, ), TrackItem( id: "L8bxsR6xR8Y", @@ -1171,6 +1242,7 @@ MusicAlbum( track_type: track, track_nr: Some(72), by_va: false, + unavailable: false, ), TrackItem( id: "StCyrfSVKRA", @@ -1187,6 +1259,7 @@ MusicAlbum( track_type: track, track_nr: Some(73), by_va: false, + unavailable: false, ), TrackItem( id: "bfb0z96jjDw", @@ -1203,6 +1276,7 @@ MusicAlbum( track_type: track, track_nr: Some(74), by_va: false, + unavailable: false, ), TrackItem( id: "_Cs_HEjIxE4", @@ -1219,6 +1293,7 @@ MusicAlbum( track_type: track, track_nr: Some(75), by_va: false, + unavailable: false, ), TrackItem( id: "rlZTCrB9DUY", @@ -1235,6 +1310,7 @@ MusicAlbum( track_type: track, track_nr: Some(76), by_va: false, + unavailable: false, ), TrackItem( id: "0gXRizztpCE", @@ -1251,6 +1327,7 @@ MusicAlbum( track_type: track, track_nr: Some(77), by_va: false, + unavailable: false, ), TrackItem( id: "U3gNQeexaFA", @@ -1267,6 +1344,7 @@ MusicAlbum( track_type: track, track_nr: Some(78), by_va: false, + unavailable: false, ), TrackItem( id: "SDVj1LdZAWs", @@ -1283,6 +1361,7 @@ MusicAlbum( track_type: track, track_nr: Some(79), by_va: false, + unavailable: false, ), TrackItem( id: "aStx8DVBL4w", @@ -1299,6 +1378,7 @@ MusicAlbum( track_type: track, track_nr: Some(80), by_va: false, + unavailable: false, ), TrackItem( id: "39HPvtWzT5w", @@ -1315,6 +1395,7 @@ MusicAlbum( track_type: track, track_nr: Some(81), by_va: false, + unavailable: false, ), TrackItem( id: "KDpAcnRvf98", @@ -1331,6 +1412,7 @@ MusicAlbum( track_type: track, track_nr: Some(82), by_va: false, + unavailable: false, ), TrackItem( id: "Qg7M-RQatI8", @@ -1347,6 +1429,7 @@ MusicAlbum( track_type: track, track_nr: Some(83), by_va: false, + unavailable: false, ), TrackItem( id: "V35JMnicqpE", @@ -1363,6 +1446,7 @@ MusicAlbum( track_type: track, track_nr: Some(84), by_va: false, + unavailable: false, ), TrackItem( id: "fqVlv9bXo38", @@ -1379,6 +1463,7 @@ MusicAlbum( track_type: track, track_nr: Some(85), by_va: false, + unavailable: false, ), TrackItem( id: "zcv2WC4ccCM", @@ -1395,6 +1480,7 @@ MusicAlbum( track_type: track, track_nr: Some(86), by_va: false, + unavailable: false, ), TrackItem( id: "Em3S3CXYgsc", @@ -1411,6 +1497,7 @@ MusicAlbum( track_type: track, track_nr: Some(87), by_va: false, + unavailable: false, ), TrackItem( id: "Pru_NJ16FX8", @@ -1427,6 +1514,7 @@ MusicAlbum( track_type: track, track_nr: Some(88), by_va: false, + unavailable: false, ), TrackItem( id: "2klbe4CmXaQ", @@ -1443,6 +1531,7 @@ MusicAlbum( track_type: track, track_nr: Some(89), by_va: false, + unavailable: false, ), TrackItem( id: "qePq7ltD6j4", @@ -1459,6 +1548,7 @@ MusicAlbum( track_type: track, track_nr: Some(90), by_va: false, + unavailable: false, ), TrackItem( id: "oBiS9b_v4wM", @@ -1475,6 +1565,7 @@ MusicAlbum( track_type: track, track_nr: Some(91), by_va: false, + unavailable: false, ), TrackItem( id: "g2_3XksRrek", @@ -1491,6 +1582,7 @@ MusicAlbum( track_type: track, track_nr: Some(92), by_va: false, + unavailable: false, ), TrackItem( id: "-eW-lGQghx8", @@ -1507,6 +1599,7 @@ MusicAlbum( track_type: track, track_nr: Some(93), by_va: false, + unavailable: false, ), TrackItem( id: "adRnRqIr19Q", @@ -1523,6 +1616,7 @@ MusicAlbum( track_type: track, track_nr: Some(94), by_va: false, + unavailable: false, ), TrackItem( id: "C1fvUpxJ8G0", @@ -1539,6 +1633,7 @@ MusicAlbum( track_type: track, track_nr: Some(95), by_va: false, + unavailable: false, ), TrackItem( id: "MgkJ7uW13hM", @@ -1555,6 +1650,7 @@ MusicAlbum( track_type: track, track_nr: Some(96), by_va: false, + unavailable: false, ), TrackItem( id: "pB22pN3oudY", @@ -1571,6 +1667,7 @@ MusicAlbum( track_type: track, track_nr: Some(97), by_va: false, + unavailable: false, ), TrackItem( id: "d4JvNP7oR4g", @@ -1587,6 +1684,7 @@ MusicAlbum( track_type: track, track_nr: Some(98), by_va: false, + unavailable: false, ), TrackItem( id: "FfUZhLb3L1A", @@ -1603,6 +1701,7 @@ MusicAlbum( track_type: track, track_nr: Some(99), by_va: false, + unavailable: false, ), TrackItem( id: "pGdz8B_V9vs", @@ -1619,6 +1718,7 @@ MusicAlbum( track_type: track, track_nr: Some(100), by_va: false, + unavailable: false, ), TrackItem( id: "wWzLLDr7VZY", @@ -1635,6 +1735,7 @@ MusicAlbum( track_type: track, track_nr: Some(101), by_va: false, + unavailable: false, ), TrackItem( id: "sjwsqR7A-nI", @@ -1651,6 +1752,7 @@ MusicAlbum( track_type: track, track_nr: Some(102), by_va: false, + unavailable: false, ), TrackItem( id: "ZBxtouT9Rpo", @@ -1667,6 +1769,7 @@ MusicAlbum( track_type: track, track_nr: Some(103), by_va: false, + unavailable: false, ), TrackItem( id: "Ym_pEJYSd1Y", @@ -1683,6 +1786,7 @@ MusicAlbum( track_type: track, track_nr: Some(104), by_va: false, + unavailable: false, ), TrackItem( id: "48rzTOM0u5g", @@ -1699,6 +1803,7 @@ MusicAlbum( track_type: track, track_nr: Some(105), by_va: false, + unavailable: false, ), TrackItem( id: "KGN_cz6acJg", @@ -1715,6 +1820,7 @@ MusicAlbum( track_type: track, track_nr: Some(106), by_va: false, + unavailable: false, ), TrackItem( id: "JPYOtU69FBI", @@ -1731,6 +1837,7 @@ MusicAlbum( track_type: track, track_nr: Some(107), by_va: false, + unavailable: false, ), TrackItem( id: "UKJsludf1ME", @@ -1747,6 +1854,7 @@ MusicAlbum( track_type: track, track_nr: Some(108), by_va: false, + unavailable: false, ), TrackItem( id: "aO0GCv90tok", @@ -1763,6 +1871,7 @@ MusicAlbum( track_type: track, track_nr: Some(109), by_va: false, + unavailable: false, ), TrackItem( id: "yqLiNPBAIF4", @@ -1779,6 +1888,7 @@ MusicAlbum( track_type: track, track_nr: Some(110), by_va: false, + unavailable: false, ), TrackItem( id: "Wm71AIJ08ss", @@ -1795,6 +1905,7 @@ MusicAlbum( track_type: track, track_nr: Some(111), by_va: false, + unavailable: false, ), TrackItem( id: "LxSyUI2fjzM", @@ -1811,6 +1922,7 @@ MusicAlbum( track_type: track, track_nr: Some(112), by_va: false, + unavailable: false, ), TrackItem( id: "4SVHRTay_PU", @@ -1827,6 +1939,7 @@ MusicAlbum( track_type: track, track_nr: Some(113), by_va: false, + unavailable: false, ), TrackItem( id: "zhrqkGwyk4o", @@ -1843,6 +1956,7 @@ MusicAlbum( track_type: track, track_nr: Some(114), by_va: false, + unavailable: false, ), TrackItem( id: "2YuvSWutjbY", @@ -1859,6 +1973,7 @@ MusicAlbum( track_type: track, track_nr: Some(115), by_va: false, + unavailable: false, ), TrackItem( id: "QT-BvFEO3ho", @@ -1875,6 +1990,7 @@ MusicAlbum( track_type: track, track_nr: Some(116), by_va: false, + unavailable: false, ), TrackItem( id: "27rrlVQ7D4M", @@ -1891,6 +2007,7 @@ MusicAlbum( track_type: track, track_nr: Some(117), by_va: false, + unavailable: false, ), TrackItem( id: "7m0EEXEBRo4", @@ -1907,6 +2024,7 @@ MusicAlbum( track_type: track, track_nr: Some(118), by_va: false, + unavailable: false, ), TrackItem( id: "34H2shrx38w", @@ -1923,6 +2041,7 @@ MusicAlbum( track_type: track, track_nr: Some(119), by_va: false, + unavailable: false, ), TrackItem( id: "yCuI-ii6dLA", @@ -1939,6 +2058,7 @@ MusicAlbum( track_type: track, track_nr: Some(120), by_va: false, + unavailable: false, ), TrackItem( id: "E6Uzcr7zwoQ", @@ -1955,6 +2075,7 @@ MusicAlbum( track_type: track, track_nr: Some(121), by_va: false, + unavailable: false, ), TrackItem( id: "gpL45b1fugI", @@ -1971,6 +2092,7 @@ MusicAlbum( track_type: track, track_nr: Some(122), by_va: false, + unavailable: false, ), TrackItem( id: "ZHGQcDZ2lDo", @@ -1987,6 +2109,7 @@ MusicAlbum( track_type: track, track_nr: Some(123), by_va: false, + unavailable: false, ), TrackItem( id: "EkVfn3H1YNw", @@ -2003,6 +2126,7 @@ MusicAlbum( track_type: track, track_nr: Some(124), by_va: false, + unavailable: false, ), TrackItem( id: "iqh3t9ScmdM", @@ -2019,6 +2143,7 @@ MusicAlbum( track_type: track, track_nr: Some(125), by_va: false, + unavailable: false, ), TrackItem( id: "lfdocX0dHjo", @@ -2035,6 +2160,7 @@ MusicAlbum( track_type: track, track_nr: Some(126), by_va: false, + unavailable: false, ), TrackItem( id: "LBz5HWuwICc", @@ -2051,6 +2177,7 @@ MusicAlbum( track_type: track, track_nr: Some(127), by_va: false, + unavailable: false, ), TrackItem( id: "DLiAozDSkn4", @@ -2067,6 +2194,7 @@ MusicAlbum( track_type: track, track_nr: Some(128), by_va: false, + unavailable: false, ), TrackItem( id: "1oAe6NOWODM", @@ -2083,6 +2211,7 @@ MusicAlbum( track_type: track, track_nr: Some(129), by_va: false, + unavailable: false, ), TrackItem( id: "CpEo9pBL9cw", @@ -2099,6 +2228,7 @@ MusicAlbum( track_type: track, track_nr: Some(130), by_va: false, + unavailable: false, ), TrackItem( id: "DioQU4tkLZQ", @@ -2115,6 +2245,7 @@ MusicAlbum( track_type: track, track_nr: Some(131), by_va: false, + unavailable: false, ), TrackItem( id: "aShFQKy3Z8M", @@ -2131,6 +2262,7 @@ MusicAlbum( track_type: track, track_nr: Some(132), by_va: false, + unavailable: false, ), TrackItem( id: "RgZACT1rJ4A", @@ -2147,6 +2279,7 @@ MusicAlbum( track_type: track, track_nr: Some(133), by_va: false, + unavailable: false, ), TrackItem( id: "Vqg-K1lFtf4", @@ -2163,6 +2296,7 @@ MusicAlbum( track_type: track, track_nr: Some(134), by_va: false, + unavailable: false, ), TrackItem( id: "FgzKDQ-KvkQ", @@ -2179,6 +2313,7 @@ MusicAlbum( track_type: track, track_nr: Some(135), by_va: false, + unavailable: false, ), TrackItem( id: "q6qGmT7z_mk", @@ -2195,6 +2330,7 @@ MusicAlbum( track_type: track, track_nr: Some(136), by_va: false, + unavailable: false, ), TrackItem( id: "BSEUTCp4JzQ", @@ -2211,6 +2347,7 @@ MusicAlbum( track_type: track, track_nr: Some(137), by_va: false, + unavailable: false, ), TrackItem( id: "GorIwpkX6bk", @@ -2227,6 +2364,7 @@ MusicAlbum( track_type: track, track_nr: Some(138), by_va: false, + unavailable: false, ), TrackItem( id: "NYiNrt7VMzA", @@ -2243,6 +2381,7 @@ MusicAlbum( track_type: track, track_nr: Some(139), by_va: false, + unavailable: false, ), TrackItem( id: "9pPalZZsIlQ", @@ -2259,6 +2398,7 @@ MusicAlbum( track_type: track, track_nr: Some(140), by_va: false, + unavailable: false, ), TrackItem( id: "GUPplhf2Wts", @@ -2275,6 +2415,7 @@ MusicAlbum( track_type: track, track_nr: Some(141), by_va: false, + unavailable: false, ), TrackItem( id: "sUc4pA09dMA", @@ -2291,6 +2432,7 @@ MusicAlbum( track_type: track, track_nr: Some(142), by_va: false, + unavailable: false, ), TrackItem( id: "ykieQtMZjgI", @@ -2307,6 +2449,7 @@ MusicAlbum( track_type: track, track_nr: Some(143), by_va: false, + unavailable: false, ), TrackItem( id: "P_aAJjwygaA", @@ -2323,6 +2466,7 @@ MusicAlbum( track_type: track, track_nr: Some(144), by_va: false, + unavailable: false, ), TrackItem( id: "d2QMPdcl7YM", @@ -2339,6 +2483,7 @@ MusicAlbum( track_type: track, track_nr: Some(145), by_va: false, + unavailable: false, ), TrackItem( id: "V0gQO8dH6b4", @@ -2355,6 +2500,7 @@ MusicAlbum( track_type: track, track_nr: Some(146), by_va: false, + unavailable: false, ), TrackItem( id: "cgOzxcg52v8", @@ -2371,6 +2517,7 @@ MusicAlbum( track_type: track, track_nr: Some(147), by_va: false, + unavailable: false, ), TrackItem( id: "rjTEyuRGrYY", @@ -2387,6 +2534,7 @@ MusicAlbum( track_type: track, track_nr: Some(148), by_va: false, + unavailable: false, ), TrackItem( id: "6DwpgjU82ww", @@ -2403,6 +2551,7 @@ MusicAlbum( track_type: track, track_nr: Some(149), by_va: false, + unavailable: false, ), TrackItem( id: "dwk9eQZse6E", @@ -2419,6 +2568,7 @@ MusicAlbum( track_type: track, track_nr: Some(150), by_va: false, + unavailable: false, ), TrackItem( id: "zmM1aeBv_mo", @@ -2435,6 +2585,7 @@ MusicAlbum( track_type: track, track_nr: Some(151), by_va: false, + unavailable: false, ), TrackItem( id: "QL1HMAEp21k", @@ -2451,6 +2602,7 @@ MusicAlbum( track_type: track, track_nr: Some(152), by_va: false, + unavailable: false, ), TrackItem( id: "rtzG_mr5q-c", @@ -2467,6 +2619,7 @@ MusicAlbum( track_type: track, track_nr: Some(153), by_va: false, + unavailable: false, ), TrackItem( id: "Eg2WlrlzO8Y", @@ -2483,6 +2636,7 @@ MusicAlbum( track_type: track, track_nr: Some(154), by_va: false, + unavailable: false, ), TrackItem( id: "QMXkBa6exqA", @@ -2499,6 +2653,7 @@ MusicAlbum( track_type: track, track_nr: Some(155), by_va: false, + unavailable: false, ), TrackItem( id: "n0dStgWvR08", @@ -2515,6 +2670,7 @@ MusicAlbum( track_type: track, track_nr: Some(156), by_va: false, + unavailable: false, ), TrackItem( id: "FxslNrm_3jU", @@ -2531,6 +2687,7 @@ MusicAlbum( track_type: track, track_nr: Some(157), by_va: false, + unavailable: false, ), TrackItem( id: "rlJXZLKXjyM", @@ -2547,6 +2704,7 @@ MusicAlbum( track_type: track, track_nr: Some(158), by_va: false, + unavailable: false, ), TrackItem( id: "RQ6lvrVddyk", @@ -2563,6 +2721,7 @@ MusicAlbum( track_type: track, track_nr: Some(159), by_va: false, + unavailable: false, ), TrackItem( id: "LCLBV5T8s5k", @@ -2579,6 +2738,7 @@ MusicAlbum( track_type: track, track_nr: Some(160), by_va: false, + unavailable: false, ), TrackItem( id: "bNigSN7siMU", @@ -2595,6 +2755,7 @@ MusicAlbum( track_type: track, track_nr: Some(161), by_va: false, + unavailable: false, ), TrackItem( id: "KFBydJkaTD4", @@ -2611,6 +2772,7 @@ MusicAlbum( track_type: track, track_nr: Some(162), by_va: false, + unavailable: false, ), TrackItem( id: "1PUlvwOASBw", @@ -2627,6 +2789,7 @@ MusicAlbum( track_type: track, track_nr: Some(163), by_va: false, + unavailable: false, ), TrackItem( id: "pyvOIiyn5JY", @@ -2643,6 +2806,7 @@ MusicAlbum( track_type: track, track_nr: Some(164), by_va: false, + unavailable: false, ), TrackItem( id: "eQKlU7pzFRw", @@ -2659,6 +2823,7 @@ MusicAlbum( track_type: track, track_nr: Some(165), by_va: false, + unavailable: false, ), TrackItem( id: "pbROCT8IwDs", @@ -2675,6 +2840,7 @@ MusicAlbum( track_type: track, track_nr: Some(166), by_va: false, + unavailable: false, ), TrackItem( id: "6eklRsup2Cg", @@ -2691,6 +2857,7 @@ MusicAlbum( track_type: track, track_nr: Some(167), by_va: false, + unavailable: false, ), TrackItem( id: "Sx047sHMOV8", @@ -2707,6 +2874,7 @@ MusicAlbum( track_type: track, track_nr: Some(168), by_va: false, + unavailable: false, ), TrackItem( id: "uIhFD_Y1RM8", @@ -2723,6 +2891,7 @@ MusicAlbum( track_type: track, track_nr: Some(169), by_va: false, + unavailable: false, ), TrackItem( id: "OdiW4u-MJWk", @@ -2739,6 +2908,7 @@ MusicAlbum( track_type: track, track_nr: Some(170), by_va: false, + unavailable: false, ), TrackItem( id: "IQQ4H5wKhqw", @@ -2755,6 +2925,7 @@ MusicAlbum( track_type: track, track_nr: Some(171), by_va: false, + unavailable: false, ), TrackItem( id: "heJoxdCFgXE", @@ -2771,6 +2942,7 @@ MusicAlbum( track_type: track, track_nr: Some(172), by_va: false, + unavailable: false, ), TrackItem( id: "k7Vhuh9N7hg", @@ -2787,6 +2959,7 @@ MusicAlbum( track_type: track, track_nr: Some(173), by_va: false, + unavailable: false, ), TrackItem( id: "0Aeaczuom_0", @@ -2803,6 +2976,7 @@ MusicAlbum( track_type: track, track_nr: Some(174), by_va: false, + unavailable: false, ), TrackItem( id: "5sJd3YkpnNg", @@ -2819,6 +2993,7 @@ MusicAlbum( track_type: track, track_nr: Some(175), by_va: false, + unavailable: false, ), TrackItem( id: "K3xED9BLZ0g", @@ -2835,6 +3010,7 @@ MusicAlbum( track_type: track, track_nr: Some(176), by_va: false, + unavailable: false, ), TrackItem( id: "wxBk25H3Zw4", @@ -2851,6 +3027,7 @@ MusicAlbum( track_type: track, track_nr: Some(177), by_va: false, + unavailable: false, ), TrackItem( id: "Gxdv90qTiBA", @@ -2867,6 +3044,7 @@ MusicAlbum( track_type: track, track_nr: Some(178), by_va: false, + unavailable: false, ), TrackItem( id: "ewUX4G705t0", @@ -2883,6 +3061,7 @@ MusicAlbum( track_type: track, track_nr: Some(179), by_va: false, + unavailable: false, ), TrackItem( id: "fIAs-O1seGs", @@ -2899,6 +3078,7 @@ MusicAlbum( track_type: track, track_nr: Some(180), by_va: false, + unavailable: false, ), TrackItem( id: "CLmbiozyb3g", @@ -2915,6 +3095,7 @@ MusicAlbum( track_type: track, track_nr: Some(181), by_va: false, + unavailable: false, ), TrackItem( id: "cZqX4kRFrls", @@ -2931,6 +3112,7 @@ MusicAlbum( track_type: track, track_nr: Some(182), by_va: false, + unavailable: false, ), TrackItem( id: "GzKlXy_klc0", @@ -2947,6 +3129,7 @@ MusicAlbum( track_type: track, track_nr: Some(183), by_va: false, + unavailable: false, ), TrackItem( id: "N9TK0-c90NQ", @@ -2963,6 +3146,7 @@ MusicAlbum( track_type: track, track_nr: Some(184), by_va: false, + unavailable: false, ), TrackItem( id: "AdmAEn7yJBg", @@ -2979,6 +3163,7 @@ MusicAlbum( track_type: track, track_nr: Some(185), by_va: false, + unavailable: false, ), TrackItem( id: "goV3qAE4nDo", @@ -2995,6 +3180,7 @@ MusicAlbum( track_type: track, track_nr: Some(186), by_va: false, + unavailable: false, ), TrackItem( id: "HpX-bfM-z8c", @@ -3011,6 +3197,7 @@ MusicAlbum( track_type: track, track_nr: Some(187), by_va: false, + unavailable: false, ), TrackItem( id: "GT5EGpOqAeM", @@ -3027,6 +3214,7 @@ MusicAlbum( track_type: track, track_nr: Some(188), by_va: false, + unavailable: false, ), TrackItem( id: "M8cQ5zntKks", @@ -3043,6 +3231,7 @@ MusicAlbum( track_type: track, track_nr: Some(189), by_va: false, + unavailable: false, ), TrackItem( id: "EDdwfxA88RQ", @@ -3059,6 +3248,7 @@ MusicAlbum( track_type: track, track_nr: Some(190), by_va: false, + unavailable: false, ), TrackItem( id: "deQx4nzAHvI", @@ -3075,6 +3265,7 @@ MusicAlbum( track_type: track, track_nr: Some(191), by_va: false, + unavailable: false, ), TrackItem( id: "-TYmP5BWkZA", @@ -3091,6 +3282,7 @@ MusicAlbum( track_type: track, track_nr: Some(192), by_va: false, + unavailable: false, ), TrackItem( id: "NKWffyEyvvQ", @@ -3107,6 +3299,7 @@ MusicAlbum( track_type: track, track_nr: Some(193), by_va: false, + unavailable: false, ), TrackItem( id: "5SQgoPx88Xk", @@ -3123,6 +3316,7 @@ MusicAlbum( track_type: track, track_nr: Some(194), by_va: false, + unavailable: false, ), TrackItem( id: "8MmcjOWCXcI", @@ -3139,6 +3333,7 @@ MusicAlbum( track_type: track, track_nr: Some(195), by_va: false, + unavailable: false, ), TrackItem( id: "Cs8eNJJsOwg", @@ -3155,6 +3350,7 @@ MusicAlbum( track_type: track, track_nr: Some(196), by_va: false, + unavailable: false, ), TrackItem( id: "u9ulcct7UW8", @@ -3171,6 +3367,7 @@ MusicAlbum( track_type: track, track_nr: Some(197), by_va: false, + unavailable: false, ), TrackItem( id: "_Q3Ybt6A0A4", @@ -3187,6 +3384,7 @@ MusicAlbum( track_type: track, track_nr: Some(198), by_va: false, + unavailable: false, ), TrackItem( id: "OwLevpAaw50", @@ -3203,6 +3401,7 @@ MusicAlbum( track_type: track, track_nr: Some(199), by_va: false, + unavailable: false, ), TrackItem( id: "wKg1h1i_pLk", @@ -3219,6 +3418,7 @@ MusicAlbum( track_type: track, track_nr: Some(200), by_va: false, + unavailable: false, ), TrackItem( id: "svY6h_e3LYI", @@ -3251,6 +3451,7 @@ MusicAlbum( track_type: track, track_nr: Some(201), by_va: false, + unavailable: false, ), TrackItem( id: "Hir7IMW_37k", @@ -3283,6 +3484,7 @@ MusicAlbum( track_type: track, track_nr: Some(202), by_va: false, + unavailable: false, ), TrackItem( id: "wrp-KxyqmKs", @@ -3315,6 +3517,7 @@ MusicAlbum( track_type: track, track_nr: Some(203), by_va: false, + unavailable: false, ), TrackItem( id: "tFQF6fw09ec", @@ -3347,6 +3550,7 @@ MusicAlbum( track_type: track, track_nr: Some(204), by_va: false, + unavailable: false, ), TrackItem( id: "tzlG81GlTXQ", @@ -3379,6 +3583,7 @@ MusicAlbum( track_type: track, track_nr: Some(205), by_va: false, + unavailable: false, ), TrackItem( id: "Vno9w1ba-C0", @@ -3411,6 +3616,7 @@ MusicAlbum( track_type: track, track_nr: Some(206), by_va: false, + unavailable: false, ), TrackItem( id: "Ve19y3AhLBk", @@ -3443,6 +3649,7 @@ MusicAlbum( track_type: track, track_nr: Some(207), by_va: false, + unavailable: false, ), TrackItem( id: "8oHasQ_tiuI", @@ -3475,6 +3682,7 @@ MusicAlbum( track_type: track, track_nr: Some(208), by_va: false, + unavailable: false, ), TrackItem( id: "Ap42W06bL2c", @@ -3507,6 +3715,7 @@ MusicAlbum( track_type: track, track_nr: Some(209), by_va: false, + unavailable: false, ), TrackItem( id: "qmiLwRF0fOs", @@ -3539,6 +3748,7 @@ MusicAlbum( track_type: track, track_nr: Some(210), by_va: false, + unavailable: false, ), TrackItem( id: "BdiOwfRyToY", @@ -3571,6 +3781,7 @@ MusicAlbum( track_type: track, track_nr: Some(211), by_va: false, + unavailable: false, ), TrackItem( id: "PlBZ0cGf5DE", @@ -3603,6 +3814,7 @@ MusicAlbum( track_type: track, track_nr: Some(212), by_va: false, + unavailable: false, ), TrackItem( id: "v9MgxVJWCow", @@ -3635,6 +3847,7 @@ MusicAlbum( track_type: track, track_nr: Some(213), by_va: false, + unavailable: false, ), TrackItem( id: "5nwe4RMmA8s", @@ -3667,6 +3880,7 @@ MusicAlbum( track_type: track, track_nr: Some(214), by_va: false, + unavailable: false, ), TrackItem( id: "6ZP4rXcPFd0", @@ -3699,6 +3913,7 @@ MusicAlbum( track_type: track, track_nr: Some(215), by_va: false, + unavailable: false, ), TrackItem( id: "eVhWJKVdo40", @@ -3731,6 +3946,7 @@ MusicAlbum( track_type: track, track_nr: Some(216), by_va: false, + unavailable: false, ), TrackItem( id: "Vt7keSTK0No", @@ -3763,6 +3979,7 @@ MusicAlbum( track_type: track, track_nr: Some(217), by_va: false, + unavailable: false, ), TrackItem( id: "Ff3SyoUlcyY", @@ -3795,6 +4012,7 @@ MusicAlbum( track_type: track, track_nr: Some(218), by_va: false, + unavailable: false, ), TrackItem( id: "gMTJQzds2ac", @@ -3827,6 +4045,7 @@ MusicAlbum( track_type: track, track_nr: Some(219), by_va: false, + unavailable: false, ), TrackItem( id: "UgAOUifyrqc", @@ -3859,6 +4078,7 @@ MusicAlbum( track_type: track, track_nr: Some(220), by_va: false, + unavailable: false, ), TrackItem( id: "IGZoSexffaY", @@ -3891,6 +4111,7 @@ MusicAlbum( track_type: track, track_nr: Some(221), by_va: false, + unavailable: false, ), TrackItem( id: "_yk6rIXnfyw", @@ -3923,6 +4144,7 @@ MusicAlbum( track_type: track, track_nr: Some(222), by_va: false, + unavailable: false, ), TrackItem( id: "nhznAYDKokI", @@ -3955,6 +4177,7 @@ MusicAlbum( track_type: track, track_nr: Some(223), by_va: false, + unavailable: false, ), TrackItem( id: "xxcWex5wCpc", @@ -3987,6 +4210,7 @@ MusicAlbum( track_type: track, track_nr: Some(224), by_va: false, + unavailable: false, ), TrackItem( id: "bHuVgebOTtY", @@ -4019,6 +4243,7 @@ MusicAlbum( track_type: track, track_nr: Some(225), by_va: false, + unavailable: false, ), TrackItem( id: "4dSMRBLFXE8", @@ -4051,6 +4276,7 @@ MusicAlbum( track_type: track, track_nr: Some(226), by_va: false, + unavailable: false, ), TrackItem( id: "7nrceuJOGrQ", @@ -4083,6 +4309,7 @@ MusicAlbum( track_type: track, track_nr: Some(227), by_va: false, + unavailable: false, ), TrackItem( id: "rs_bvUV0-ZE", @@ -4115,6 +4342,7 @@ MusicAlbum( track_type: track, track_nr: Some(228), by_va: false, + unavailable: false, ), TrackItem( id: "SjDAX5b1sCA", @@ -4147,6 +4375,7 @@ MusicAlbum( track_type: track, track_nr: Some(229), by_va: false, + unavailable: false, ), TrackItem( id: "9LPuIbBxM_4", @@ -4179,6 +4408,7 @@ MusicAlbum( track_type: track, track_nr: Some(230), by_va: false, + unavailable: false, ), TrackItem( id: "xoTJCozaeFw", @@ -4211,6 +4441,7 @@ MusicAlbum( track_type: track, track_nr: Some(231), by_va: false, + unavailable: false, ), TrackItem( id: "o9R4zEStCg0", @@ -4243,6 +4474,7 @@ MusicAlbum( track_type: track, track_nr: Some(232), by_va: false, + unavailable: false, ), TrackItem( id: "v9aTac8EXeU", @@ -4275,6 +4507,7 @@ MusicAlbum( track_type: track, track_nr: Some(233), by_va: false, + unavailable: false, ), TrackItem( id: "Q6LQBbg9OFg", @@ -4307,6 +4540,7 @@ MusicAlbum( track_type: track, track_nr: Some(234), by_va: false, + unavailable: false, ), TrackItem( id: "m3uHhmbvtLQ", @@ -4339,6 +4573,7 @@ MusicAlbum( track_type: track, track_nr: Some(235), by_va: false, + unavailable: false, ), TrackItem( id: "6Q6paXKnxN4", @@ -4371,6 +4606,7 @@ MusicAlbum( track_type: track, track_nr: Some(236), by_va: false, + unavailable: false, ), TrackItem( id: "bZmfzI9OhCs", @@ -4403,6 +4639,7 @@ MusicAlbum( track_type: track, track_nr: Some(237), by_va: false, + unavailable: false, ), TrackItem( id: "LywfUGAGUPc", @@ -4435,6 +4672,7 @@ MusicAlbum( track_type: track, track_nr: Some(238), by_va: false, + unavailable: false, ), TrackItem( id: "r3vVFZ3zl94", @@ -4467,6 +4705,7 @@ MusicAlbum( track_type: track, track_nr: Some(239), by_va: false, + unavailable: false, ), TrackItem( id: "Qenx-MfJ9mw", @@ -4499,6 +4738,7 @@ MusicAlbum( track_type: track, track_nr: Some(240), by_va: false, + unavailable: false, ), TrackItem( id: "vl_qPscUgdQ", @@ -4531,6 +4771,7 @@ MusicAlbum( track_type: track, track_nr: Some(241), by_va: false, + unavailable: false, ), TrackItem( id: "FQwclGtvT8A", @@ -4563,6 +4804,7 @@ MusicAlbum( track_type: track, track_nr: Some(242), by_va: false, + unavailable: false, ), TrackItem( id: "XfZemPEMHYM", @@ -4595,6 +4837,7 @@ MusicAlbum( track_type: track, track_nr: Some(243), by_va: false, + unavailable: false, ), TrackItem( id: "tXEWSfM5jBI", @@ -4627,6 +4870,7 @@ MusicAlbum( track_type: track, track_nr: Some(244), by_va: false, + unavailable: false, ), TrackItem( id: "CyYeGELAYks", @@ -4659,6 +4903,7 @@ MusicAlbum( track_type: track, track_nr: Some(245), by_va: false, + unavailable: false, ), TrackItem( id: "V4crS8euIlY", @@ -4691,6 +4936,7 @@ MusicAlbum( track_type: track, track_nr: Some(246), by_va: false, + unavailable: false, ), TrackItem( id: "6wkfFwX8hEk", @@ -4723,6 +4969,7 @@ MusicAlbum( track_type: track, track_nr: Some(247), by_va: false, + unavailable: false, ), TrackItem( id: "7BrXtew4Xf8", @@ -4755,6 +5002,7 @@ MusicAlbum( track_type: track, track_nr: Some(248), by_va: false, + unavailable: false, ), TrackItem( id: "zBOsHSF010g", @@ -4787,6 +5035,7 @@ MusicAlbum( track_type: track, track_nr: Some(249), by_va: false, + unavailable: false, ), TrackItem( id: "5hY-Mmqfg-U", @@ -4819,6 +5068,7 @@ MusicAlbum( track_type: track, track_nr: Some(250), by_va: false, + unavailable: false, ), TrackItem( id: "GWsWxGtQG2U", @@ -4851,6 +5101,7 @@ MusicAlbum( track_type: track, track_nr: Some(251), by_va: false, + unavailable: false, ), TrackItem( id: "CS61jsoqGxM", @@ -4883,6 +5134,7 @@ MusicAlbum( track_type: track, track_nr: Some(252), by_va: false, + unavailable: false, ), TrackItem( id: "--MDZ6MoFOk", @@ -4915,6 +5167,7 @@ MusicAlbum( track_type: track, track_nr: Some(253), by_va: false, + unavailable: false, ), TrackItem( id: "APxYXEvS1gI", @@ -4947,6 +5200,7 @@ MusicAlbum( track_type: track, track_nr: Some(254), by_va: false, + unavailable: false, ), TrackItem( id: "hTZCV0xIaNo", @@ -4979,6 +5233,7 @@ MusicAlbum( track_type: track, track_nr: Some(255), by_va: false, + unavailable: false, ), TrackItem( id: "fUyVsvSLXAA", @@ -5011,6 +5266,7 @@ MusicAlbum( track_type: track, track_nr: Some(256), by_va: false, + unavailable: false, ), TrackItem( id: "Ex8KXjkzH6U", @@ -5043,6 +5299,7 @@ MusicAlbum( track_type: track, track_nr: Some(257), by_va: false, + unavailable: false, ), TrackItem( id: "Jq9_Roh-_qQ", @@ -5075,6 +5332,7 @@ MusicAlbum( track_type: track, track_nr: Some(258), by_va: false, + unavailable: false, ), TrackItem( id: "O-k4WTkVF_Y", @@ -5107,6 +5365,7 @@ MusicAlbum( track_type: track, track_nr: Some(259), by_va: false, + unavailable: false, ), TrackItem( id: "e0VydtqA7zA", @@ -5139,6 +5398,7 @@ MusicAlbum( track_type: track, track_nr: Some(260), by_va: false, + unavailable: false, ), TrackItem( id: "tYHQ1jqyY04", @@ -5171,6 +5431,7 @@ MusicAlbum( track_type: track, track_nr: Some(261), by_va: false, + unavailable: false, ), TrackItem( id: "uJdxfG7mtxg", @@ -5203,6 +5464,7 @@ MusicAlbum( track_type: track, track_nr: Some(262), by_va: false, + unavailable: false, ), TrackItem( id: "y9WgL5asujI", @@ -5235,6 +5497,7 @@ MusicAlbum( track_type: track, track_nr: Some(263), by_va: false, + unavailable: false, ), TrackItem( id: "M2_kYfPFD_o", @@ -5267,6 +5530,7 @@ MusicAlbum( track_type: track, track_nr: Some(264), by_va: false, + unavailable: false, ), TrackItem( id: "mMk8rWLu2kQ", @@ -5299,6 +5563,7 @@ MusicAlbum( track_type: track, track_nr: Some(265), by_va: false, + unavailable: false, ), TrackItem( id: "CdlO0Z_uhbM", @@ -5331,6 +5596,7 @@ MusicAlbum( track_type: track, track_nr: Some(266), by_va: false, + unavailable: false, ), TrackItem( id: "5loS8hlMQ7U", @@ -5363,6 +5629,7 @@ MusicAlbum( track_type: track, track_nr: Some(267), by_va: false, + unavailable: false, ), TrackItem( id: "2db5x8VGr8A", @@ -5395,6 +5662,7 @@ MusicAlbum( track_type: track, track_nr: Some(268), by_va: false, + unavailable: false, ), TrackItem( id: "cTRGKM8Jsgc", @@ -5427,6 +5695,7 @@ MusicAlbum( track_type: track, track_nr: Some(269), by_va: false, + unavailable: false, ), TrackItem( id: "nrfztfR0soo", @@ -5459,6 +5728,7 @@ MusicAlbum( track_type: track, track_nr: Some(270), by_va: false, + unavailable: false, ), TrackItem( id: "3om6N_pNGZA", @@ -5491,6 +5761,7 @@ MusicAlbum( track_type: track, track_nr: Some(271), by_va: false, + unavailable: false, ), TrackItem( id: "VN1KvIPeJ00", @@ -5523,6 +5794,7 @@ MusicAlbum( track_type: track, track_nr: Some(272), by_va: false, + unavailable: false, ), TrackItem( id: "LRuhIRN5d1U", @@ -5555,6 +5827,7 @@ MusicAlbum( track_type: track, track_nr: Some(273), by_va: false, + unavailable: false, ), TrackItem( id: "dE8U1hliRr4", @@ -5587,6 +5860,7 @@ MusicAlbum( track_type: track, track_nr: Some(274), by_va: false, + unavailable: false, ), TrackItem( id: "vjIb2Klunv0", @@ -5619,6 +5893,7 @@ MusicAlbum( track_type: track, track_nr: Some(275), by_va: false, + unavailable: false, ), TrackItem( id: "h8BydzKZOtI", @@ -5651,6 +5926,7 @@ MusicAlbum( track_type: track, track_nr: Some(276), by_va: false, + unavailable: false, ), TrackItem( id: "ADwyhkSHBVM", @@ -5683,6 +5959,7 @@ MusicAlbum( track_type: track, track_nr: Some(277), by_va: false, + unavailable: false, ), TrackItem( id: "6cDrKGImmQk", @@ -5715,6 +5992,7 @@ MusicAlbum( track_type: track, track_nr: Some(278), by_va: false, + unavailable: false, ), TrackItem( id: "CdrnLzIJGdk", @@ -5747,6 +6025,7 @@ MusicAlbum( track_type: track, track_nr: Some(279), by_va: false, + unavailable: false, ), TrackItem( id: "N-ZzOlAX43w", @@ -5779,6 +6058,7 @@ MusicAlbum( track_type: track, track_nr: Some(280), by_va: false, + unavailable: false, ), TrackItem( id: "7MHmAXMX1F8", @@ -5811,6 +6091,7 @@ MusicAlbum( track_type: track, track_nr: Some(281), by_va: false, + unavailable: false, ), TrackItem( id: "vSlyuw3eyeU", @@ -5843,6 +6124,7 @@ MusicAlbum( track_type: track, track_nr: Some(282), by_va: false, + unavailable: false, ), TrackItem( id: "K8ez5KNbl-A", @@ -5875,6 +6157,7 @@ MusicAlbum( track_type: track, track_nr: Some(283), by_va: false, + unavailable: false, ), TrackItem( id: "J9y2_6f5Dqc", @@ -5907,6 +6190,7 @@ MusicAlbum( track_type: track, track_nr: Some(284), by_va: false, + unavailable: false, ), TrackItem( id: "d4Grp66WWsM", @@ -5939,6 +6223,7 @@ MusicAlbum( track_type: track, track_nr: Some(285), by_va: false, + unavailable: false, ), TrackItem( id: "gYCKh7_DAAw", @@ -5971,6 +6256,7 @@ MusicAlbum( track_type: track, track_nr: Some(286), by_va: false, + unavailable: false, ), TrackItem( id: "L59dwOH-nHQ", @@ -6003,6 +6289,7 @@ MusicAlbum( track_type: track, track_nr: Some(287), by_va: false, + unavailable: false, ), TrackItem( id: "KS4nFrdUDS8", @@ -6035,6 +6322,7 @@ MusicAlbum( track_type: track, track_nr: Some(288), by_va: false, + unavailable: false, ), TrackItem( id: "4bEhuh2DtBQ", @@ -6067,6 +6355,7 @@ MusicAlbum( track_type: track, track_nr: Some(289), by_va: false, + unavailable: false, ), TrackItem( id: "76nvjlkt2xY", @@ -6099,6 +6388,7 @@ MusicAlbum( track_type: track, track_nr: Some(290), by_va: false, + unavailable: false, ), TrackItem( id: "F7mUlqh-y04", @@ -6131,6 +6421,7 @@ MusicAlbum( track_type: track, track_nr: Some(291), by_va: false, + unavailable: false, ), TrackItem( id: "KivOUvqJ2n4", @@ -6163,6 +6454,7 @@ MusicAlbum( track_type: track, track_nr: Some(292), by_va: false, + unavailable: false, ), TrackItem( id: "EHzrgnOh5GA", @@ -6195,6 +6487,7 @@ MusicAlbum( track_type: track, track_nr: Some(293), by_va: false, + unavailable: false, ), TrackItem( id: "10xak85mCso", @@ -6227,6 +6520,7 @@ MusicAlbum( track_type: track, track_nr: Some(294), by_va: false, + unavailable: false, ), TrackItem( id: "yDnNqeQnn3A", @@ -6259,6 +6553,7 @@ MusicAlbum( track_type: track, track_nr: Some(295), by_va: false, + unavailable: false, ), TrackItem( id: "l7n3auySj4A", @@ -6291,6 +6586,7 @@ MusicAlbum( track_type: track, track_nr: Some(296), by_va: false, + unavailable: false, ), TrackItem( id: "Ywtfz72Zywk", @@ -6323,6 +6619,7 @@ MusicAlbum( track_type: track, track_nr: Some(297), by_va: false, + unavailable: false, ), TrackItem( id: "FZpI_baOd_s", @@ -6355,6 +6652,7 @@ MusicAlbum( track_type: track, track_nr: Some(298), by_va: false, + unavailable: false, ), TrackItem( id: "8OXK57SjsL0", @@ -6387,6 +6685,7 @@ MusicAlbum( track_type: track, track_nr: Some(299), by_va: false, + unavailable: false, ), TrackItem( id: "5M-AVirsHzY", @@ -6419,6 +6718,7 @@ MusicAlbum( track_type: track, track_nr: Some(300), by_va: false, + unavailable: false, ), TrackItem( id: "4BQlY5tiXqY", @@ -6451,6 +6751,7 @@ MusicAlbum( track_type: track, track_nr: Some(301), by_va: false, + unavailable: false, ), TrackItem( id: "1n-_LCwDMUg", @@ -6483,6 +6784,7 @@ MusicAlbum( track_type: track, track_nr: Some(302), by_va: false, + unavailable: false, ), TrackItem( id: "V-DyXyW8UI4", @@ -6515,6 +6817,7 @@ MusicAlbum( track_type: track, track_nr: Some(303), by_va: false, + unavailable: false, ), TrackItem( id: "GygcLOKL8B4", @@ -6547,6 +6850,7 @@ MusicAlbum( track_type: track, track_nr: Some(304), by_va: false, + unavailable: false, ), TrackItem( id: "S78K3PuQ-GM", @@ -6579,6 +6883,7 @@ MusicAlbum( track_type: track, track_nr: Some(305), by_va: false, + unavailable: false, ), TrackItem( id: "HcbO6kTLRZo", @@ -6611,6 +6916,7 @@ MusicAlbum( track_type: track, track_nr: Some(306), by_va: false, + unavailable: false, ), TrackItem( id: "-MCqkAaGfl0", @@ -6643,6 +6949,7 @@ MusicAlbum( track_type: track, track_nr: Some(307), by_va: false, + unavailable: false, ), TrackItem( id: "G4edEm1rbeo", @@ -6675,6 +6982,7 @@ MusicAlbum( track_type: track, track_nr: Some(308), by_va: false, + unavailable: false, ), TrackItem( id: "KA26JvGwM28", @@ -6707,6 +7015,7 @@ MusicAlbum( track_type: track, track_nr: Some(309), by_va: false, + unavailable: false, ), TrackItem( id: "9GR32DB5RwY", @@ -6739,6 +7048,7 @@ MusicAlbum( track_type: track, track_nr: Some(310), by_va: false, + unavailable: false, ), TrackItem( id: "06rRLhqrcTk", @@ -6771,6 +7081,7 @@ MusicAlbum( track_type: track, track_nr: Some(311), by_va: false, + unavailable: false, ), TrackItem( id: "gw2h1uGGwak", @@ -6803,6 +7114,7 @@ MusicAlbum( track_type: track, track_nr: Some(312), by_va: false, + unavailable: false, ), TrackItem( id: "U1OnhVQHw4c", @@ -6835,6 +7147,7 @@ MusicAlbum( track_type: track, track_nr: Some(313), by_va: false, + unavailable: false, ), TrackItem( id: "C8UAKN2G0R8", @@ -6867,6 +7180,7 @@ MusicAlbum( track_type: track, track_nr: Some(314), by_va: false, + unavailable: false, ), TrackItem( id: "-q-TeXqQ9AA", @@ -6899,6 +7213,7 @@ MusicAlbum( track_type: track, track_nr: Some(315), by_va: false, + unavailable: false, ), TrackItem( id: "r77eoDVeFh0", @@ -6931,6 +7246,7 @@ MusicAlbum( track_type: track, track_nr: Some(316), by_va: false, + unavailable: false, ), TrackItem( id: "g8RfSPyjiXc", @@ -6963,6 +7279,7 @@ MusicAlbum( track_type: track, track_nr: Some(317), by_va: false, + unavailable: false, ), TrackItem( id: "au27GX2h7Zc", @@ -6995,6 +7312,7 @@ MusicAlbum( track_type: track, track_nr: Some(318), by_va: false, + unavailable: false, ), TrackItem( id: "hGHRyXDMR0M", @@ -7027,6 +7345,7 @@ MusicAlbum( track_type: track, track_nr: Some(319), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_ep.snap b/tests/snapshots/youtube__music_album_ep.snap index 0920a61..fcf693f 100644 --- a/tests/snapshots/youtube__music_album_ep.snap +++ b/tests/snapshots/youtube__music_album_ep.snap @@ -40,6 +40,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "Jz-26iiDuYs", @@ -61,6 +62,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "Bu26uFtpt58", @@ -82,6 +84,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "RgwNqqiVqdY", @@ -103,6 +106,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "2TuOh30XbCI", @@ -124,6 +128,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_no_artist.snap b/tests/snapshots/youtube__music_album_no_artist.snap index 36c65ca..1939dd3 100644 --- a/tests/snapshots/youtube__music_album_no_artist.snap +++ b/tests/snapshots/youtube__music_album_no_artist.snap @@ -39,6 +39,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "s-qSnZyyvzs", @@ -60,6 +61,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "4jXoRBcQ8PY", @@ -81,6 +83,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "DRES9S4VQI8", @@ -102,6 +105,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "yhZVimwD4B4", @@ -127,6 +131,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "5d6YiFkdzLM", @@ -148,6 +153,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "3Qe7-uN2PjU", @@ -173,6 +179,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "SKZ_MTsXFP4", @@ -194,6 +201,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "n5-ujUwazDA", @@ -215,6 +223,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "VaREivfDJeY", @@ -236,6 +245,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "cWcD0WIK2PA", @@ -261,6 +271,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "QRELvH564T4", @@ -282,6 +293,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "eCY0-GyG46s", @@ -303,6 +315,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "UIrHYTEyUfA", @@ -328,6 +341,7 @@ MusicAlbum( track_type: track, track_nr: Some(14), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_no_year.snap b/tests/snapshots/youtube__music_album_no_year.snap index dc9a815..a4b2c2d 100644 --- a/tests/snapshots/youtube__music_album_no_year.snap +++ b/tests/snapshots/youtube__music_album_no_year.snap @@ -56,6 +56,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_one_artist.snap b/tests/snapshots/youtube__music_album_one_artist.snap index 31f2166..c092826 100644 --- a/tests/snapshots/youtube__music_album_one_artist.snap +++ b/tests/snapshots/youtube__music_album_one_artist.snap @@ -66,6 +66,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "-xFJfXE2Cms", @@ -91,6 +92,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "KWDAaQDq8CQ", @@ -116,6 +118,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "0bcovdD1gQo", @@ -141,6 +144,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "lJsqxERcxR8", @@ -162,6 +166,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "iLfB6-slQdc", @@ -183,6 +188,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "4DjGZIdMcZk", @@ -204,6 +210,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "hakoZyX4QIc", @@ -225,6 +232,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "GOh96GiHVgI", @@ -246,6 +254,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "ne_jRAHABx0", @@ -267,6 +276,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "g8oyC2g5V64", @@ -288,6 +298,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "RxTEv7wXvG0", @@ -309,6 +320,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "V8iVLlSZeNs", @@ -330,6 +342,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "OESslKlpao4", @@ -351,6 +364,7 @@ MusicAlbum( track_type: track, track_nr: Some(14), by_va: false, + unavailable: false, ), TrackItem( id: "ennw5cHAebo", @@ -372,6 +386,7 @@ MusicAlbum( track_type: track, track_nr: Some(15), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_show.snap b/tests/snapshots/youtube__music_album_show.snap index 87ad246..dbd2c04 100644 --- a/tests/snapshots/youtube__music_album_show.snap +++ b/tests/snapshots/youtube__music_album_show.snap @@ -48,6 +48,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "Wqrg6ceVgK8", @@ -73,6 +74,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "oWlZR0mU3fQ", @@ -98,6 +100,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "pcdWTaNK_w4", @@ -123,6 +126,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "hJhcL8A4AEI", @@ -148,6 +152,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "ROwmS2PzXiE", @@ -173,6 +178,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "u5fduXogSKU", @@ -198,6 +204,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "37aeBkbW5Y4", @@ -223,6 +230,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "Hn2701yNst0", @@ -248,6 +256,7 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, ), TrackItem( id: "dQiTv0BdwwA", @@ -273,6 +282,7 @@ MusicAlbum( track_type: track, track_nr: Some(10), by_va: false, + unavailable: false, ), TrackItem( id: "DXYXlAljscM", @@ -298,6 +308,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "mfbmff4MQ2M", @@ -323,6 +334,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "mHkR5PHlHpQ", @@ -348,6 +360,7 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, ), TrackItem( id: "VBnKIZ1b5Cg", @@ -373,6 +386,7 @@ MusicAlbum( track_type: track, track_nr: Some(14), by_va: false, + unavailable: false, ), TrackItem( id: "1iOIPRlLFgM", @@ -398,6 +412,7 @@ MusicAlbum( track_type: track, track_nr: Some(15), by_va: false, + unavailable: false, ), TrackItem( id: "z1nDiIcnxoM", @@ -423,6 +438,7 @@ MusicAlbum( track_type: track, track_nr: Some(16), by_va: false, + unavailable: false, ), TrackItem( id: "TNpe9wfbW9U", @@ -448,6 +464,7 @@ MusicAlbum( track_type: track, track_nr: Some(17), by_va: false, + unavailable: false, ), TrackItem( id: "9FtXAfifarI", @@ -473,6 +490,7 @@ MusicAlbum( track_type: track, track_nr: Some(18), by_va: false, + unavailable: false, ), TrackItem( id: "bRG8YR7ZBtI", @@ -498,6 +516,7 @@ MusicAlbum( track_type: track, track_nr: Some(19), by_va: false, + unavailable: false, ), TrackItem( id: "wYV9GxkHdRE", @@ -523,6 +542,7 @@ MusicAlbum( track_type: track, track_nr: Some(20), by_va: false, + unavailable: false, ), TrackItem( id: "wbrz2yUKiwo", @@ -548,6 +568,7 @@ MusicAlbum( track_type: track, track_nr: Some(21), by_va: false, + unavailable: false, ), TrackItem( id: "_MUx8LqzuY8", @@ -573,6 +594,7 @@ MusicAlbum( track_type: track, track_nr: Some(22), by_va: false, + unavailable: false, ), TrackItem( id: "s0xXo8ftgCA", @@ -598,6 +620,7 @@ MusicAlbum( track_type: track, track_nr: Some(23), by_va: false, + unavailable: false, ), TrackItem( id: "6Q_etK9rgV8", @@ -623,6 +646,7 @@ MusicAlbum( track_type: track, track_nr: Some(24), by_va: false, + unavailable: false, ), TrackItem( id: "4pwRZBhZH6Y", @@ -648,6 +672,7 @@ MusicAlbum( track_type: track, track_nr: Some(25), by_va: false, + unavailable: false, ), TrackItem( id: "O75q5a1s02E", @@ -673,6 +698,7 @@ MusicAlbum( track_type: track, track_nr: Some(26), by_va: false, + unavailable: false, ), TrackItem( id: "KSD9dI_ZgPQ", @@ -698,6 +724,7 @@ MusicAlbum( track_type: track, track_nr: Some(27), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_single.snap b/tests/snapshots/youtube__music_album_single.snap index baa3162..570a89b 100644 --- a/tests/snapshots/youtube__music_album_single.snap +++ b/tests/snapshots/youtube__music_album_single.snap @@ -48,6 +48,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_unavailable.snap b/tests/snapshots/youtube__music_album_unavailable.snap index b3624c5..e80ce2b 100644 --- a/tests/snapshots/youtube__music_album_unavailable.snap +++ b/tests/snapshots/youtube__music_album_unavailable.snap @@ -48,6 +48,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "t0v0UOgOt18", @@ -69,6 +70,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "HjJYAkUXrxI", @@ -90,10 +92,33 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, + ), + TrackItem( + id: "d53Dhq4_VvA", + name: "Severed", + duration: Some(244), + cover: [], + artists: [ + ArtistId( + id: None, + name: "The Decemberists", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(4), + by_va: false, + unavailable: true, ), TrackItem( id: "Hg0KUOTL06I", - name: "Swim Home", + name: "SWIM HOME", duration: Some(187), cover: [], artists: [ @@ -111,6 +136,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "c8AfY6yhdkM", @@ -132,6 +158,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), TrackItem( id: "_ZmdHjVvwhc", @@ -153,6 +180,7 @@ MusicAlbum( track_type: track, track_nr: Some(7), by_va: false, + unavailable: false, ), TrackItem( id: "wBe1Zi3q1n8", @@ -174,6 +202,7 @@ MusicAlbum( track_type: track, track_nr: Some(8), by_va: false, + unavailable: false, ), TrackItem( id: "l8Pj8s9uPGc", @@ -195,6 +224,29 @@ MusicAlbum( track_type: track, track_nr: Some(9), by_va: false, + unavailable: false, + ), + TrackItem( + id: "2ZbW3zfLfXo", + name: "Young Forever", + duration: Some(244), + cover: [], + artists: [ + ArtistId( + id: None, + name: "JR JR", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(10), + by_va: false, + unavailable: true, ), TrackItem( id: "Kn3cruxYj0c", @@ -216,6 +268,7 @@ MusicAlbum( track_type: track, track_nr: Some(11), by_va: false, + unavailable: false, ), TrackItem( id: "Sy1lIOl1YN0", @@ -237,6 +290,7 @@ MusicAlbum( track_type: track, track_nr: Some(12), by_va: false, + unavailable: false, ), TrackItem( id: "njdlNT1RRo4", @@ -258,6 +312,95 @@ MusicAlbum( track_type: track, track_nr: Some(13), by_va: false, + unavailable: false, + ), + TrackItem( + id: "bANUH8SNV4E", + name: "SLAVES OF FEAR", + duration: Some(294), + cover: [], + artists: [ + ArtistId( + id: None, + name: "HEALTH", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(14), + by_va: false, + unavailable: true, + ), + TrackItem( + id: "jn7fJSTUbUM", + name: "All Your Life", + duration: Some(266), + cover: [], + artists: [ + ArtistId( + id: None, + name: "Angelo De Augustine", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(15), + by_va: false, + unavailable: true, + ), + TrackItem( + id: "-MCzjr9LSIA", + name: "Culture", + duration: Some(194), + cover: [], + artists: [ + ArtistId( + id: None, + name: "Hembree", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(16), + by_va: false, + unavailable: true, + ), + TrackItem( + id: "StZKjRiFtOQ", + name: "Still Want To Be Here", + duration: Some(233), + cover: [], + artists: [ + ArtistId( + id: None, + name: "Frightened Rabbit", + ), + ], + artist_id: None, + album: Some(AlbumId( + id: "MPREb_AzuWg8qAVVl", + name: "13 Reasons Why (Season 3)", + )), + view_count: "[view_count]", + track_type: track, + track_nr: Some(17), + by_va: false, + unavailable: true, ), TrackItem( id: "Si-CXM8CHqQ", @@ -279,6 +422,7 @@ MusicAlbum( track_type: track, track_nr: Some(18), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_album_various_artists.snap b/tests/snapshots/youtube__music_album_various_artists.snap index f7eb3d8..769dde5 100644 --- a/tests/snapshots/youtube__music_album_various_artists.snap +++ b/tests/snapshots/youtube__music_album_various_artists.snap @@ -35,6 +35,7 @@ MusicAlbum( track_type: track, track_nr: Some(1), by_va: false, + unavailable: false, ), TrackItem( id: "9WYpLYAEub0", @@ -56,6 +57,7 @@ MusicAlbum( track_type: track, track_nr: Some(2), by_va: false, + unavailable: false, ), TrackItem( id: "R48tE237bW4", @@ -77,6 +79,7 @@ MusicAlbum( track_type: track, track_nr: Some(3), by_va: false, + unavailable: false, ), TrackItem( id: "-UzsoR6z-vg", @@ -98,6 +101,7 @@ MusicAlbum( track_type: track, track_nr: Some(4), by_va: false, + unavailable: false, ), TrackItem( id: "kbNVyn8Ex28", @@ -119,6 +123,7 @@ MusicAlbum( track_type: track, track_nr: Some(5), by_va: false, + unavailable: false, ), TrackItem( id: "NJrQZUzWP5Y", @@ -140,6 +145,7 @@ MusicAlbum( track_type: track, track_nr: Some(6), by_va: false, + unavailable: false, ), ], variants: [], diff --git a/tests/snapshots/youtube__music_artist_basic.snap b/tests/snapshots/youtube__music_artist_basic.snap index 4aba0e1..d73c2a2 100644 --- a/tests/snapshots/youtube__music_artist_basic.snap +++ b/tests/snapshots/youtube__music_artist_basic.snap @@ -101,21 +101,6 @@ MusicArtist( year: Some(2003), by_va: false, ), - AlbumItem( - id: "MPREb_QyGCcLWExXj", - name: "Als wär\'s das erste Mal (Exklusive Piano Version)", - cover: "[cover]", - artists: [ - ArtistId( - id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"), - name: "Unheilig", - ), - ], - artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"), - album_type: single, - year: Some(2014), - by_va: false, - ), AlbumItem( id: "MPREb_R3p5kDRIGKL", name: "Astronaut", @@ -161,6 +146,21 @@ MusicArtist( year: Some(2017), by_va: false, ), + AlbumItem( + id: "MPREb_UA3c5UyVGYs", + name: "Geboren um zu leben", + cover: "[cover]", + artists: [ + ArtistId( + id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"), + name: "Unheilig", + ), + ], + artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"), + album_type: single, + year: Some(2025), + by_va: false, + ), AlbumItem( id: "MPREb_V0FEmw2pj2u", name: "Sonnentag", diff --git a/tests/snapshots/youtube__music_details_mv.snap b/tests/snapshots/youtube__music_details_mv.snap index afbd05f..8fa7abf 100644 --- a/tests/snapshots/youtube__music_details_mv.snap +++ b/tests/snapshots/youtube__music_details_mv.snap @@ -20,6 +20,7 @@ TrackDetails( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), lyrics_id: Some("MPLYt_wrKjTn9hmry"), related_id: Some("MPTRt_wrKjTn9hmry"), diff --git a/tests/snapshots/youtube__music_details_track.snap b/tests/snapshots/youtube__music_details_track.snap index 4d85918..ef6ff9c 100644 --- a/tests/snapshots/youtube__music_details_track.snap +++ b/tests/snapshots/youtube__music_details_track.snap @@ -27,6 +27,7 @@ TrackDetails( track_type: track, track_nr: None, by_va: false, + unavailable: false, ), lyrics_id: Some("MPLYt_cjEzeaBgZAq-2"), related_id: Some("MPTRt_cjEzeaBgZAq-2"), diff --git a/tests/snapshots/youtube__music_details_track_details.snap b/tests/snapshots/youtube__music_details_track_details.snap index e91052f..b506083 100644 --- a/tests/snapshots/youtube__music_details_track_details.snap +++ b/tests/snapshots/youtube__music_details_track_details.snap @@ -20,6 +20,7 @@ TrackDetails( track_type: video, track_nr: None, by_va: false, + unavailable: false, ), lyrics_id: None, related_id: None, diff --git a/tests/youtube.rs b/tests/youtube.rs index 5f64621..d8e60f9 100644 --- a/tests/youtube.rs +++ b/tests/youtube.rs @@ -27,7 +27,7 @@ use rustypipe::validate; //#PLAYER #[rstest] -#[case::desktop(ClientType::Desktop)] +// #[case::desktop(ClientType::Desktop)] TODO: add SABR support #[case::tv(ClientType::Tv)] #[case::mobile(ClientType::Mobile)] // #[case::android(ClientType::Android)] Removed since it requires Android device attestation @@ -721,7 +721,7 @@ async fn get_video_details_live(rp: RustyPipe) { assert_eq!(details.channel.id, "UCSJ4gkVC6NrvII8umztf0Ow"); assert_eq!(details.channel.name, "Lofi Girl"); assert!(!details.channel.avatar.is_empty(), "no channel avatars"); - assert_eq!(details.channel.verification, Verification::Verified); + assert_eq!(details.channel.verification, Verification::Artist); assert_gteo(details.channel.subscriber_count, 5_500_000, "subscribers"); assert_gte(details.view_count, 100, "views"); assert_gteo(details.like_count, 1_800_000, "likes"); @@ -2507,17 +2507,17 @@ async fn music_radio_not_found(rp: RustyPipe) { #[tokio::test] async fn music_charts( #[case] country: Country, - #[case] plid_top: &str, - #[case] plid_trend: &str, + #[case] _plid_top: &str, + #[case] _plid_trend: &str, rp: RustyPipe, ) { let charts = rp.query().music_charts(Some(country)).await.unwrap(); - assert_eq!(charts.top_playlist_id.expect("top_playlist_id"), plid_top); - - assert_gte(charts.top_tracks.len(), 30, "top tracks"); + // assert_eq!(charts.top_playlist_id.expect("top_playlist_id"), plid_top); + // assert_gte(charts.top_tracks.len(), 30, "top tracks"); assert_gte(charts.artists.len(), 30, "top artists"); + /* // Currently (01.02.2024) is no trending playlist shown for Global and US if country != Country::Us { assert_eq!( @@ -2526,6 +2526,7 @@ async fn music_charts( ); assert_gte(charts.trending_tracks.len(), 15, "trending tracks"); } + */ // Chart playlists only available in USA if country == Country::Us { @@ -2703,7 +2704,7 @@ async fn isrc_search_languages(rp: RustyPipe) { .unwrap(); let track_id = &tracks.items.items[0].id; assert!( - track_id == "g0iRiJ_ck48" || track_id == "YgUZtELr_jw", + track_id == "g0iRiJ_ck48" || track_id == "YgUZtELr_jw" || track_id == "oMhM4CFEY3I", "lang: {lang}; track: {track_id}" ); } From 6035e6db4e613038e14fe775f0d2eae889737d93 Mon Sep 17 00:00:00 2001 From: ThetaDev Date: Wed, 18 Jun 2025 15:35:47 +0200 Subject: [PATCH 21/21] fix: parse channel subscriber/video count correctly --- src/client/channel.rs | 5 +-- src/client/playlist.rs | 8 ++--- src/client/response/mod.rs | 31 +++++++++++-------- ...map_channel_playlists_20241109_lockup.snap | 2 +- ...p_channel_videos_20240324_pageheader2.snap | 2 +- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/client/channel.rs b/src/client/channel.rs index 8dcb827..dc67579 100644 --- a/src/client/channel.rs +++ b/src/client/channel.rs @@ -468,8 +468,9 @@ fn map_channel( let subscriber_count = sub_part.and_then(|t| { util::parse_large_numstr_or_warn::(t.as_str(), ctx.lang, &mut warnings) }); - let video_count = - vc_part.and_then(|t| util::parse_numeric_or_warn(t.as_str(), &mut warnings)); + let video_count = vc_part.and_then(|t| { + util::parse_large_numstr_or_warn(t.as_str(), ctx.lang, &mut warnings) + }); Channel { id: metadata.external_id, diff --git a/src/client/playlist.rs b/src/client/playlist.rs index 63d80bf..c080dd6 100644 --- a/src/client/playlist.rs +++ b/src/client/playlist.rs @@ -140,10 +140,10 @@ impl MapResponse for response::Playlist { .next() .and_then(|r| r.metadata_parts.into_iter().next()) .and_then(|p| match p { - response::MetadataPart::Text(_) => None, - response::MetadataPart::AvatarStack { - avatar_stack_view_model, - } => ChannelId::try_from(avatar_stack_view_model.text).ok(), + response::MetadataPart::Text { .. } => None, + response::MetadataPart::AvatarStack { avatar_stack } => { + ChannelId::try_from(avatar_stack.avatar_stack_view_model.text).ok() + } }); // remove "by" prefix if let Some(c) = channel.as_mut() { diff --git a/src/client/response/mod.rs b/src/client/response/mod.rs index 42d1445..e160826 100644 --- a/src/client/response/mod.rs +++ b/src/client/response/mod.rs @@ -647,31 +647,36 @@ pub(crate) struct PhMetadataRow { #[serde_as] #[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(untagged)] pub(crate) enum MetadataPart { - Text(#[serde_as(as = "AttributedText")] TextComponent), - #[serde(rename_all = "camelCase")] - AvatarStack { - avatar_stack_view_model: TextComponentBox, + Text { + #[serde_as(as = "AttributedText")] + text: TextComponent, }, + #[serde(rename_all = "camelCase")] + AvatarStack { avatar_stack: AvatarStackInner }, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct AvatarStackInner { + pub avatar_stack_view_model: TextComponentBox, } impl MetadataPart { pub fn into_text_component(self) -> TextComponent { match self { - MetadataPart::Text(text_component) => text_component, - MetadataPart::AvatarStack { - avatar_stack_view_model, - } => avatar_stack_view_model.text, + MetadataPart::Text { text } => text, + MetadataPart::AvatarStack { avatar_stack } => avatar_stack.avatar_stack_view_model.text, } } pub fn as_str(&self) -> &str { match self { - MetadataPart::Text(s) => s.as_str(), - MetadataPart::AvatarStack { - avatar_stack_view_model, - } => avatar_stack_view_model.text.as_str(), + MetadataPart::Text { text } => text.as_str(), + MetadataPart::AvatarStack { avatar_stack } => { + avatar_stack.avatar_stack_view_model.text.as_str() + } } } } diff --git a/src/client/snapshots/rustypipe__client__channel__tests__map_channel_playlists_20241109_lockup.snap b/src/client/snapshots/rustypipe__client__channel__tests__map_channel_playlists_20241109_lockup.snap index 3ae88c8..8dc1c76 100644 --- a/src/client/snapshots/rustypipe__client__channel__tests__map_channel_playlists_20241109_lockup.snap +++ b/src/client/snapshots/rustypipe__client__channel__tests__map_channel_playlists_20241109_lockup.snap @@ -7,7 +7,7 @@ Channel( name: "EEVblog", handle: Some("@EEVblog"), subscriber_count: Some(952000), - video_count: Some(2), + video_count: Some(2000), avatar: [ Thumbnail( url: "https://yt3.googleusercontent.com/ytc/AIdro_l17lYcTcRSydZeQK-RuiSfEeH5eX9m4irSNQj6109v5MQ=s72-c-k-c0x00ffffff-no-rj", diff --git a/src/client/snapshots/rustypipe__client__channel__tests__map_channel_videos_20240324_pageheader2.snap b/src/client/snapshots/rustypipe__client__channel__tests__map_channel_videos_20240324_pageheader2.snap index 2d7ebad..ae0a957 100644 --- a/src/client/snapshots/rustypipe__client__channel__tests__map_channel_videos_20240324_pageheader2.snap +++ b/src/client/snapshots/rustypipe__client__channel__tests__map_channel_videos_20240324_pageheader2.snap @@ -7,7 +7,7 @@ Channel( name: "EEVblog", handle: Some("@EEVblog"), subscriber_count: Some(933000), - video_count: Some(19), + video_count: Some(1900), avatar: [ Thumbnail( url: "https://yt3.googleusercontent.com/ytc/AIdro_lagjGDfXbXlQXhznx3CDRitOBdxvebllQd_YP1ag=s72-c-k-c0x00ffffff-no-rj",