fix: use desktop client by default for fetching player
This commit is contained in:
parent
ca1338b6b7
commit
dc0eb1d4cc
2 changed files with 51 additions and 15 deletions
|
|
@ -61,9 +61,9 @@ impl RustyPipeQuery {
|
||||||
/// Get YouTube player data (video/audio streams + basic metadata)
|
/// Get YouTube player data (video/audio streams + basic metadata)
|
||||||
pub async fn player<S: AsRef<str>>(&self, video_id: S) -> Result<VideoPlayer, Error> {
|
pub async fn player<S: AsRef<str>>(&self, video_id: S) -> Result<VideoPlayer, Error> {
|
||||||
let video_id = video_id.as_ref();
|
let video_id = video_id.as_ref();
|
||||||
let android_res = self.player_from_client(video_id, ClientType::Android).await;
|
let desktop_res = self.player_from_client(video_id, ClientType::Desktop).await;
|
||||||
|
|
||||||
match android_res {
|
match desktop_res {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(Error::Extraction(e)) => {
|
Err(Error::Extraction(e)) => {
|
||||||
if e.switch_client() {
|
if e.switch_client() {
|
||||||
|
|
@ -72,7 +72,7 @@ impl RustyPipeQuery {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match tv_res {
|
match tv_res {
|
||||||
// Output android client error if the tv client is unsupported
|
// Output desktop client error if the tv client is unsupported
|
||||||
Err(Error::Extraction(ExtractionError::VideoClientUnsupported(_))) => {
|
Err(Error::Extraction(ExtractionError::VideoClientUnsupported(_))) => {
|
||||||
Err(Error::Extraction(e))
|
Err(Error::Extraction(e))
|
||||||
}
|
}
|
||||||
|
|
@ -152,25 +152,31 @@ impl MapResponse<VideoPlayer> for response::Player {
|
||||||
response::player::PlayabilityStatus::Ok { live_streamability } => {
|
response::player::PlayabilityStatus::Ok { live_streamability } => {
|
||||||
live_streamability.is_some()
|
live_streamability.is_some()
|
||||||
}
|
}
|
||||||
response::player::PlayabilityStatus::Unplayable { reason } => {
|
response::player::PlayabilityStatus::Unplayable {
|
||||||
for word in reason.split_whitespace() {
|
reason,
|
||||||
|
error_screen,
|
||||||
|
} => {
|
||||||
|
let mut msg = reason;
|
||||||
|
if let Some(error_screen) = error_screen {
|
||||||
|
msg.push_str(" - ");
|
||||||
|
msg.push_str(&error_screen.player_error_message_renderer.subreason);
|
||||||
|
}
|
||||||
|
|
||||||
|
for word in msg.split_whitespace() {
|
||||||
match word {
|
match word {
|
||||||
// reason: "This video requires payment to watch."
|
// reason: "This video requires payment to watch."
|
||||||
"payment" => return Err(ExtractionError::VideoUnavailable("DRM", reason)),
|
"payment" => return Err(ExtractionError::VideoUnavailable("DRM", msg)),
|
||||||
// reason: "The uploader has not made this video available in your country."
|
// reason: "The uploader has not made this video available in your country."
|
||||||
"country" => return Err(ExtractionError::VideoGeoblocked),
|
"country" => return Err(ExtractionError::VideoGeoblocked),
|
||||||
// reason (Android): "This video can only be played on newer versions of Android or other supported devices."
|
// reason (Android): "This video can only be played on newer versions of Android or other supported devices."
|
||||||
// reason (TV client): "Playback on other websites has been disabled by the video owner."
|
// reason (TV client): "Playback on other websites has been disabled by the video owner."
|
||||||
"Android" | "websites" => {
|
"Android" | "websites" => {
|
||||||
return Err(ExtractionError::VideoClientUnsupported(reason))
|
return Err(ExtractionError::VideoClientUnsupported(msg))
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(ExtractionError::VideoUnavailable(
|
return Err(ExtractionError::VideoUnavailable("being unplayable", msg));
|
||||||
"being unplayable",
|
|
||||||
reason,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
response::player::PlayabilityStatus::LoginRequired { reason } => {
|
response::player::PlayabilityStatus::LoginRequired { reason } => {
|
||||||
// reason (age restriction): "Sign in to confirm your age"
|
// reason (age restriction): "Sign in to confirm your age"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ pub(crate) struct Player {
|
||||||
pub response_context: ResponseContext,
|
pub response_context: ResponseContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")]
|
#[serde(tag = "status", rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
pub(crate) enum PlayabilityStatus {
|
pub(crate) enum PlayabilityStatus {
|
||||||
|
|
@ -24,20 +25,49 @@ pub(crate) enum PlayabilityStatus {
|
||||||
Ok { live_streamability: Option<Empty> },
|
Ok { live_streamability: Option<Empty> },
|
||||||
/// Video cant be played because of DRM / Geoblock
|
/// Video cant be played because of DRM / Geoblock
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Unplayable { reason: String },
|
Unplayable {
|
||||||
|
#[serde(default)]
|
||||||
|
reason: String,
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde_as(deserialize_as = "DefaultOnError")]
|
||||||
|
error_screen: Option<ErrorScreen>,
|
||||||
|
},
|
||||||
/// Age limit / Private video
|
/// Age limit / Private video
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
LoginRequired { reason: String },
|
LoginRequired {
|
||||||
|
#[serde(default)]
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
LiveStreamOffline { reason: String },
|
LiveStreamOffline {
|
||||||
|
#[serde(default)]
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
/// Video was censored / deleted
|
/// Video was censored / deleted
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Error { reason: String },
|
Error {
|
||||||
|
#[serde(default)]
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub(crate) struct Empty {}
|
pub(crate) struct Empty {}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct ErrorScreen {
|
||||||
|
pub player_error_message_renderer: ErrorMessage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct ErrorMessage {
|
||||||
|
#[serde_as(as = "Text")]
|
||||||
|
pub subreason: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
|
||||||
Reference in a new issue