Skip to content

Commit

Permalink
Add support to use ugoira cli
Browse files Browse the repository at this point in the history
  • Loading branch information
lifegpc authored Sep 22, 2024
1 parent a28a5b6 commit a5442f1
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 59 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ RustyXML = "0.3"
serde = "1"
serde_json = "1"
serde_urlencoded = { version = "*", optional = true }
subprocess = "0.2"
tokio = { version = "1.27", features = ["rt", "macros", "rt-multi-thread", "time"] }
url = "2.3"
urlparse = "0.7"
Expand Down
1 change: 0 additions & 1 deletion src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ pub mod data;
pub mod exif;
pub mod fanbox;
pub mod json;
#[cfg(feature = "avdict")]
pub mod video;
31 changes: 31 additions & 0 deletions src/data/video.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#[cfg(feature = "avdict")]
use crate::avdict::AVDict;
#[cfg(feature = "avdict")]
use crate::avdict::AVDictError;
use crate::data::data::PixivData;
use crate::parser::description::parse_description;
use std::collections::HashMap;

#[cfg(feature = "avdict")]
pub fn get_video_metadata(data: &PixivData) -> Result<AVDict, AVDictError> {
let mut d = AVDict::new();
if data.title.is_some() {
Expand All @@ -24,3 +28,30 @@ pub fn get_video_metadata(data: &PixivData) -> Result<AVDict, AVDictError> {
}
Ok(d)
}

pub fn get_video_metas(data: &PixivData) -> HashMap<String, String> {
let mut m = HashMap::new();
match &data.title {
Some(t) => {
m.insert(String::from("title"), t.clone());
}
None => {}
}
match &data.author {
Some(a) => {
m.insert(String::from("artist"), a.clone());
}
None => {}
}
match &data.description {
Some(desc) => {
let des = match parse_description(desc) {
Some(desc) => desc,
None => desc.to_owned(),
};
m.insert(String::from("comment"), des);
}
None => {}
}
m
}
43 changes: 43 additions & 0 deletions src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::data::fanbox::FanboxData;
use crate::data::json::JSONDataFile;
#[cfg(feature = "ugoira")]
use crate::data::video::get_video_metadata;
use crate::data::video::get_video_metas;
#[cfg(feature = "db")]
use crate::db::open_and_init_database;
use crate::downloader::Downloader;
Expand All @@ -32,6 +33,7 @@ use crate::pixiv_link::PixivID;
use crate::pixiv_web::PixivWebClient;
use crate::task_manager::get_progress_bar;
use crate::task_manager::TaskManager;
use crate::ugoira::convert_ugoira_to_mp4_subprocess;
#[cfg(feature = "ugoira")]
use crate::ugoira::{convert_ugoira_to_mp4, UgoiraFrames};
use crate::utils::get_file_name_from_url;
Expand Down Expand Up @@ -310,6 +312,47 @@ pub async fn download_artwork_ugoira(
let task = tasks.get_mut(0).try_err(gettext("No finished task."))?;
task.await??;
#[cfg(feature = "ugoira")]
let use_cli = helper.ugoira_cli();
#[cfg(not(feature = "ugoira"))]
let use_cli = true;
if use_cli {
if let Some(ubase) = helper.ugoira() {
let file_name = get_file_name_from_url(src).try_err(format!(
"{} {}",
gettext("Failed to get file name from url:"),
src
))?;
let file_name = base.join(file_name);
let metadata = get_video_metas(&datas.clone());
let frames_file_name = base.join(format!("{}_frames.json", id));
std::fs::write(
&frames_file_name,
json::stringify((&ugoira_data["frames"]).clone()),
)
.try_err4(gettext("Failed to write frames info to file:"))?;
let output_file_name = base.join(format!("{}.mp4", id));
convert_ugoira_to_mp4_subprocess(
&ubase,
&file_name,
&output_file_name,
&frames_file_name,
helper.ugoira_max_fps(),
metadata,
helper.force_yuv420p(),
helper.x264_crf(),
Some(helper.x264_profile()),
)
.await?;
log::info!(
"{}",
gettext("Converted <src> -> <dest>")
.replace("<src>", file_name.to_str().unwrap_or("(null)"))
.replace("<dest>", output_file_name.to_str().unwrap_or("(null)"))
.as_str()
);
}
}
#[cfg(feature = "ugoira")]
{
let file_name = get_file_name_from_url(src).try_err(format!(
"{} {}",
Expand Down
2 changes: 0 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::downloader::DownloaderError;
#[cfg(feature = "ugoira")]
use crate::ugoira::UgoiraError;
use tokio::task::JoinError;

Expand All @@ -8,7 +7,6 @@ pub enum PixivDownloaderError {
DownloaderError(DownloaderError),
String(String),
JoinError(JoinError),
#[cfg(feature = "ugoira")]
UgoiraError(UgoiraError),
#[cfg(feature = "server")]
Hyper(hyper::Error),
Expand Down
1 change: 1 addition & 0 deletions src/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ pub mod json;
pub mod rawhandle;
pub mod replace;
pub mod rw_lock;
pub mod subprocess;
pub mod try_err;
pub mod use_or_not;
37 changes: 37 additions & 0 deletions src/ext/subprocess.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use subprocess::{ExitStatus, Popen};

pub struct PopenAwait<'a> {
pub p: &'a mut Popen,
}

impl<'a> std::future::Future for PopenAwait<'a> {
type Output = ExitStatus;
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
match self.get_mut().p.poll() {
Some(e) => std::task::Poll::Ready(e),
None => {
cx.waker().wake_by_ref();
return std::task::Poll::Pending;
}
}
}
}

impl<'a> From<&'a mut Popen> for PopenAwait<'a> {
fn from(value: &'a mut Popen) -> PopenAwait<'a> {
Self { p: value }
}
}

pub trait PopenAsyncExt<'a> {
fn async_wait(&'a mut self) -> PopenAwait<'a>;
}

impl<'a> PopenAsyncExt<'a> for Popen {
fn async_wait(&'a mut self) -> PopenAwait<'a> {
PopenAwait::from(self)
}
}
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ mod settings_list;
mod task_manager;
#[cfg(feature = "server")]
mod tmp_cache;
#[cfg(feature = "ugoira")]
mod ugoira;
mod utils;
mod webclient;
Expand Down
1 change: 0 additions & 1 deletion src/opt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// Author name filters
pub mod author_name_filter;
#[cfg(feature = "ugoira")]
/// libx264 Constant Rate Factor settings
pub mod crf;
/// HTTP Header Map
Expand Down
47 changes: 41 additions & 6 deletions src/opthelper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use crate::server::cors::parse_cors_entries;
#[cfg(feature = "server")]
use crate::server::cors::CorsEntry;
use crate::settings::SettingStore;
#[cfg(feature = "ugoira")]
use crate::ugoira::X264Profile;
use is_terminal::IsTerminal;
#[cfg(feature = "server")]
Expand All @@ -29,7 +28,6 @@ use std::net::Ipv4Addr;
use std::net::SocketAddr;
use std::ops::Deref;
use std::path::PathBuf;
#[cfg(any(feature = "server", feature = "ugoira"))]
use std::str::FromStr;
use std::sync::Arc;
use std::sync::RwLock;
Expand Down Expand Up @@ -205,7 +203,6 @@ impl OptHelper {
self._fanbox_http_headers.get_ref().clone()
}

#[cfg(feature = "ugoira")]
/// Return whether to force yuv420p as output pixel format when converting ugoira(GIF) to video.
pub fn force_yuv420p(&self) -> bool {
match self.opt.get_ref().force_yuv420p {
Expand Down Expand Up @@ -531,7 +528,6 @@ impl OptHelper {
false
}

#[cfg(feature = "ugoira")]
/// The max fps when converting ugoira(GIF) to video.
pub fn ugoira_max_fps(&self) -> f32 {
match self.opt.get_ref().ugoira_max_fps {
Expand All @@ -547,7 +543,6 @@ impl OptHelper {
60f32
}

#[cfg(feature = "ugoira")]
/// The Constant Rate Factor when converting ugoira(GIF) to video.
pub fn x264_crf(&self) -> Option<f32> {
match self.opt.get_ref().x264_crf {
Expand All @@ -563,7 +558,6 @@ impl OptHelper {
None
}

#[cfg(feature = "ugoira")]
/// Return the x264 profile when converting ugoira(GIF) to video.
pub fn x264_profile(&self) -> X264Profile {
match self.opt.get_ref().x264_profile {
Expand Down Expand Up @@ -656,6 +650,47 @@ impl OptHelper {
pub fn log_cfg(&self) -> Option<String> {
return self.settings.get_ref().get_str("log-cfg");
}

/// The path to ugoira cli executable.
pub fn ugoira(&self) -> Option<String> {
match self.opt.get_ref().ugoira.as_ref() {
Some(d) => {
return Some(d.clone());
}
None => {}
}
match self.settings.get_ref().get_str("ugoira") {
Some(s) => Some(s),
None => {
#[cfg(all(feature = "ugoira", any(feature = "docker", windows)))]
return Some(String::from("ugoira"));
#[cfg(all(feature = "ugoira", not(any(feature = "docker", windows))))]
return Some(
crate::utils::get_exe_path_else_current()
.join("ugoira")
.to_string_lossy()
.into_owned(),
);
#[cfg(not(feature = "ugoira"))]
return None;
}
}
}

#[cfg(feature = "ugoira")]
/// Whether to use ugoira cli.
pub fn ugoira_cli(&self) -> bool {
match self.opt.get_ref().ugoira_cli.as_ref() {
Some(d) => {
return d.clone();
}
None => {}
}
match self.settings.get_ref().get_bool("ugoira-cli") {
Some(d) => d,
None => false,
}
}
}

impl Default for OptHelper {
Expand Down
Loading

0 comments on commit a5442f1

Please sign in to comment.