implement default format fallback
This commit is contained in:
parent
144ae00e7d
commit
2c23c8c6a1
2 changed files with 32 additions and 2 deletions
11
src/dl.rs
11
src/dl.rs
|
|
@ -70,7 +70,16 @@ pub async fn download(url: &str) -> Result<String, DownloadError> {
|
||||||
let info = YtDlp::load_info(url).await?;
|
let info = YtDlp::load_info(url).await?;
|
||||||
let av = match info.best_av_format() {
|
let av = match info.best_av_format() {
|
||||||
Some(av) => av,
|
Some(av) => av,
|
||||||
None => return Err(DownloadError::NoFormatFound),
|
None => {
|
||||||
|
event!(Level::WARN, "no best format found for {}, reverting to default", url);
|
||||||
|
match info.default_format() {
|
||||||
|
Some(format) => format,
|
||||||
|
None => {
|
||||||
|
event!(Level::ERROR, "no formats found for {}", url);
|
||||||
|
return Err(DownloadError::NoFormatFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let output_path = make_download_path(&info, &av)?;
|
let output_path = make_download_path(&info, &av)?;
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ pub struct YtDlpInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl YtDlpInfo {
|
impl YtDlpInfo {
|
||||||
|
const H_LIMIT: u16 = 720;
|
||||||
|
|
||||||
pub fn parse(json: &[u8]) -> Result<YtDlpInfo, serde_json::Error> {
|
pub fn parse(json: &[u8]) -> Result<YtDlpInfo, serde_json::Error> {
|
||||||
let mut info: YtDlpInfo = serde_json::from_slice(json)?;
|
let mut info: YtDlpInfo = serde_json::from_slice(json)?;
|
||||||
for format in &mut info.formats {
|
for format in &mut info.formats {
|
||||||
|
|
@ -88,6 +90,18 @@ impl YtDlpInfo {
|
||||||
Ok(info)
|
Ok(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_format(&self) -> Option<&YtDlpFormat> {
|
||||||
|
match self
|
||||||
|
.formats
|
||||||
|
.iter()
|
||||||
|
.filter(|f| f.height.is_some_and(|h| h <= Self::H_LIMIT))
|
||||||
|
.last()
|
||||||
|
{
|
||||||
|
Some(format) => Some(format),
|
||||||
|
None => self.formats.last(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn best_av_format(&self) -> Option<&YtDlpFormat> {
|
pub fn best_av_format(&self) -> Option<&YtDlpFormat> {
|
||||||
let format = self
|
let format = self
|
||||||
.formats
|
.formats
|
||||||
|
|
@ -141,6 +155,7 @@ pub enum YtDlpError {
|
||||||
SpawnError(SpawnError),
|
SpawnError(SpawnError),
|
||||||
ErrorMessage(String), // keep it separate type if we ever plan to parse yt-dlp errors
|
ErrorMessage(String), // keep it separate type if we ever plan to parse yt-dlp errors
|
||||||
JsonError,
|
JsonError,
|
||||||
|
NoFormats,
|
||||||
NoFilePresent,
|
NoFilePresent,
|
||||||
}
|
}
|
||||||
// ^(?:ERROR: \[.*\] \S* )(.*$) - regex for matching yt-dlp's youtube errors
|
// ^(?:ERROR: \[.*\] \S* )(.*$) - regex for matching yt-dlp's youtube errors
|
||||||
|
|
@ -167,6 +182,7 @@ impl fmt::Display for YtDlpError {
|
||||||
YTE::SpawnError(e) => write!(f, "{}", e),
|
YTE::SpawnError(e) => write!(f, "{}", e),
|
||||||
YTE::ErrorMessage(msg) => write!(f, "yt-dlp error - {}", msg),
|
YTE::ErrorMessage(msg) => write!(f, "yt-dlp error - {}", msg),
|
||||||
YTE::JsonError => write!(f, "json parsing error"),
|
YTE::JsonError => write!(f, "json parsing error"),
|
||||||
|
YTE::NoFormats => write!(f, "no formats were parsed"),
|
||||||
YTE::NoFilePresent => write!(f, "downloaded file doesn't exists"),
|
YTE::NoFilePresent => write!(f, "downloaded file doesn't exists"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +195,12 @@ impl YtDlp {
|
||||||
pub async fn load_info(url: &str) -> Result<YtDlpInfo, YtDlpError> {
|
pub async fn load_info(url: &str) -> Result<YtDlpInfo, YtDlpError> {
|
||||||
let output = spawn("python", &["-m", "yt_dlp", url, "-j"]).await?;
|
let output = spawn("python", &["-m", "yt_dlp", url, "-j"]).await?;
|
||||||
|
|
||||||
Ok(YtDlpInfo::parse(&output.stdout)?)
|
let info = YtDlpInfo::parse(&output.stdout)?;
|
||||||
|
if info.formats.is_empty() {
|
||||||
|
return Err(YtDlpError::NoFormats);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download(url: &str, format_id: &str, output_path: &str) -> Result<(), YtDlpError> {
|
pub async fn download(url: &str, format_id: &str, output_path: &str) -> Result<(), YtDlpError> {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue