feat: add player_from_clients function to specify client order
This commit is contained in:
parent
8152ce6b08
commit
72b5dfec69
1 changed files with 39 additions and 20 deletions
|
|
@ -64,33 +64,52 @@ struct QContentPlaybackContext<'a> {
|
||||||
|
|
||||||
impl RustyPipeQuery {
|
impl RustyPipeQuery {
|
||||||
/// Get YouTube player data (video/audio streams + basic metadata)
|
/// Get YouTube player data (video/audio streams + basic metadata)
|
||||||
#[tracing::instrument(skip(self))]
|
|
||||||
pub async fn player<S: AsRef<str> + Debug>(&self, video_id: S) -> Result<VideoPlayer, Error> {
|
pub async fn player<S: AsRef<str> + Debug>(&self, video_id: S) -> Result<VideoPlayer, Error> {
|
||||||
|
self.player_from_clients(video_id, &[ClientType::Desktop, ClientType::TvHtml5Embed])
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get YouTube player data (video/audio streams + basic metadata) using a list of clients.
|
||||||
|
///
|
||||||
|
/// The clients are used in the given order. If a client cannot fetch the requested video,
|
||||||
|
/// an attempt is made with the next one.
|
||||||
|
pub async fn player_from_clients<S: AsRef<str> + Debug>(
|
||||||
|
&self,
|
||||||
|
video_id: S,
|
||||||
|
clients: &[ClientType],
|
||||||
|
) -> Result<VideoPlayer, Error> {
|
||||||
let video_id = video_id.as_ref();
|
let video_id = video_id.as_ref();
|
||||||
let desktop_res = self.player_from_client(video_id, ClientType::Desktop).await;
|
let mut last_e = Error::Other("no clients".into());
|
||||||
|
// Prefer to output age restriction error (e.g. if video cannot be played
|
||||||
|
// by Desktop because of age restriction and by TvHtml5Embed because it is non-embeddable)
|
||||||
|
let mut age_restricted_e = None;
|
||||||
|
|
||||||
match desktop_res {
|
for client in clients {
|
||||||
Ok(res) => Ok(res),
|
let res = self.player_from_client(video_id, *client).await;
|
||||||
Err(Error::Extraction(e)) => {
|
match res {
|
||||||
if e.switch_client() {
|
Ok(res) => return Ok(res),
|
||||||
let tv_res = self
|
Err(Error::Extraction(e)) => {
|
||||||
.player_from_client(video_id, ClientType::TvHtml5Embed)
|
if e.switch_client() {
|
||||||
.await;
|
if let ExtractionError::Unavailable {
|
||||||
|
reason: UnavailabilityReason::AgeRestricted,
|
||||||
match tv_res {
|
msg,
|
||||||
// Output desktop client error if the tv client is unsupported
|
} = &e
|
||||||
Err(Error::Extraction(ExtractionError::Unavailable {
|
{
|
||||||
reason: UnavailabilityReason::UnsupportedClient,
|
age_restricted_e =
|
||||||
..
|
Some(Error::Extraction(ExtractionError::Unavailable {
|
||||||
})) => Err(Error::Extraction(e)),
|
reason: UnavailabilityReason::AgeRestricted,
|
||||||
_ => tv_res,
|
msg: msg.to_owned(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
last_e = Error::Extraction(e);
|
||||||
|
} else {
|
||||||
|
return Err(Error::Extraction(e));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(Error::Extraction(e))
|
|
||||||
}
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
}
|
||||||
|
Err(age_restricted_e.unwrap_or(last_e))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get YouTube player data (video/audio streams + basic metadata) using the specified client
|
/// Get YouTube player data (video/audio streams + basic metadata) using the specified client
|
||||||
|
|
|
||||||
Reference in a new issue