use std::sync::Arc;
use derive_more::Display;
use crate::{Id, Stream, VideoInfo};
use crate::video_info::player_response::video_details::VideoDetails;
#[derive(Clone, Debug, Display, PartialEq)]
#[display(fmt =
"Video({}, streams: {})",
"video_info.player_response.video_details.video_id", "streams.len()"
)]
pub struct Video {
pub(crate) video_info: VideoInfo,
pub(crate) streams: Vec<Stream>,
}
impl Video {
#[inline]
#[cfg(all(feature = "download", feature = "regex"))]
pub async fn from_url(url: &url::Url) -> crate::Result<Self> {
crate::VideoFetcher::from_url(url)?
.fetch()
.await?
.descramble()
}
#[inline]
#[cfg(feature = "download")]
pub async fn from_id(id: crate::IdBuf) -> crate::Result<Self> {
crate::VideoFetcher::from_id(id)?
.fetch()
.await?
.descramble()
}
#[inline]
pub fn video_info(&self) -> &VideoInfo {
&self.video_info
}
#[inline]
pub fn streams(&self) -> &Vec<Stream> {
&self.streams
}
#[inline]
pub fn into_streams(self) -> Vec<Stream> {
self.streams
}
#[inline]
pub fn into_parts(self) -> (VideoInfo, Vec<Stream>) {
(self.video_info, self.streams)
}
#[inline]
pub fn video_details(&self) -> Arc<VideoDetails> {
Arc::clone(&self.video_info.player_response.video_details)
}
#[inline]
pub fn id(&self) -> Id<'_> {
self.video_info.player_response.video_details.video_id.as_borrowed()
}
#[inline]
pub fn title(&self) -> &str {
self.video_info.player_response.video_details.title.as_str()
}
#[inline]
pub fn is_age_restricted(&self) -> bool {
self.video_info.is_age_restricted
}
#[inline]
pub fn best_quality(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_video_track && stream.includes_audio_track)
.max_by_key(|stream| stream.quality_label)
}
#[inline]
pub fn worst_quality(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_video_track && stream.includes_audio_track)
.min_by_key(|stream| stream.quality_label)
}
#[inline]
pub fn best_video(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_video_track && !stream.includes_audio_track)
.max_by_key(|stream| stream.width)
}
#[inline]
pub fn worst_video(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_video_track && !stream.includes_audio_track)
.min_by_key(|stream| stream.width)
}
#[inline]
pub fn best_audio(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_audio_track && !stream.includes_video_track)
.max_by_key(|stream| stream.bitrate)
}
#[inline]
pub fn worst_audio(&self) -> Option<&Stream> {
self
.streams
.iter()
.filter(|stream| stream.includes_audio_track && !stream.includes_video_track)
.min_by_key(|stream| stream.bitrate)
}
}