Add new option: x264-crf ( #330

Fix typo in x264-profile option handle
This commit is contained in:
2023-03-14 12:57:59 +00:00
committed by GitHub
parent ed3df5a337
commit 66eaae2a32
7 changed files with 94 additions and 5 deletions

View File

@@ -360,6 +360,12 @@ pub async fn download_artwork(
if !profile.is_auto() {
options.set("profile", profile.as_str(), None)?;
}
match helper.x264_crf() {
Some(crf) => {
options.set("crf", format!("{}", crf), None)?;
}
None => {}
}
let frames = UgoiraFrames::from_json(&ugoira_data["frames"])?;
let output_file_name = base.join(format!("{}.mp4", id));
convert_ugoira_to_mp4(

8
src/opt/crf.rs Normal file
View File

@@ -0,0 +1,8 @@
use json::JsonValue;
pub fn check_crf(obj: &JsonValue) -> bool {
match obj.as_f32() {
Some(crf) => crf >= -1f32,
None => false,
}
}

View File

@@ -1,5 +1,8 @@
/// Author name filters
pub mod author_name_filter;
#[cfg(feature = "ugoira")]
/// libx264 Constant Rate Factor settings
pub mod crf;
/// Proxy settings
pub mod proxy;
pub mod size;

View File

@@ -439,6 +439,22 @@ impl OptHelper {
false
}
#[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 {
Some(r) => {
return Some(r);
}
None => {}
}
if self.settings.get_ref().have("x264-crf") {
let v = self.settings.get_ref().get("x264-crf").unwrap();
return v.as_f32();
}
None
}
#[cfg(feature = "ugoira")]
/// Return the x264 profile when converting ugoira(GIF) to video.
pub fn x264_profile(&self) -> X264Profile {
@@ -449,7 +465,7 @@ impl OptHelper {
None => {}
}
if self.settings.get_ref().have("x264-profile") {
let v = self.settings.get_ref().get("server").unwrap();
let v = self.settings.get_ref().get("x264-profile").unwrap();
return X264Profile::from_str(v.as_str().unwrap()).unwrap();
}
X264Profile::default()

View File

@@ -13,6 +13,8 @@ use std::convert::TryFrom;
use std::env;
#[cfg(feature = "server")]
use std::net::SocketAddr;
#[cfg(feature = "ugoira")]
use std::num::ParseFloatError;
use std::num::ParseIntError;
use std::num::TryFromIntError;
use std::str::FromStr;
@@ -113,6 +115,9 @@ pub struct CommandOpts {
pub user_agent: Option<String>,
/// Urls want to download
pub urls: Option<Vec<String>>,
#[cfg(feature = "ugoira")]
/// The Constant Rate Factor when converting ugoira(GIF) to video.
pub x264_crf: Option<f32>,
}
impl CommandOpts {
@@ -151,6 +156,8 @@ impl CommandOpts {
download_base: None,
user_agent: None,
urls: None,
#[cfg(feature = "ugoira")]
x264_crf: None,
}
}
@@ -260,6 +267,20 @@ pub fn parse_bool<T: AsRef<str>>(s: Option<T>) -> Result<Option<bool>, String> {
}
}
#[cfg(feature = "ugoira")]
/// Parse [f32] from string
pub fn parse_f32<T: AsRef<str>>(s: Option<T>) -> Result<Option<f32>, ParseFloatError> {
match s {
Some(s) => {
let s = s.as_ref();
let s = s.trim();
let c = s.parse::<f32>()?;
Ok(Some(c))
}
None => Ok(None),
}
}
/// Prase [i64] from string
pub fn parse_i64<T: AsRef<str>>(s: Option<T>) -> Result<Option<i64>, ParseIntError> {
match s {
@@ -533,6 +554,13 @@ pub fn parse_cmd() -> Option<CommandOpts> {
"DIR",
);
opts.optopt("", "user-agent", gettext("The User-Agent header."), "UA");
#[cfg(feature = "ugoira")]
opts.optopt(
"",
"x264-crf",
gettext("The Constant Rate Factor when converting ugoira(GIF) to video."),
"float",
);
let result = match opts.parse(&argv[1..]) {
Ok(m) => m,
Err(err) => {
@@ -830,6 +858,30 @@ pub fn parse_cmd() -> Option<CommandOpts> {
}
re.as_mut().unwrap().download_base = result.opt_str("download-base");
re.as_mut().unwrap().user_agent = result.opt_str("user-agent");
#[cfg(feature = "ugoira")]
match parse_optional_opt(&result, "x264-crf", -1f32, parse_f32) {
Ok(r) => match r {
Some(crf) => {
if crf < -1f32 {
println!("{}", gettext("x264-crf can not less than -1."));
return None;
} else {
re.as_mut().unwrap().x264_crf.replace(crf);
}
}
None => {}
},
Err(e) => {
println!(
"{} {}",
("Failed to parse <opt>:")
.replace("<opt>", "x264-crf")
.as_str(),
e
);
return None;
}
}
re
}

View File

@@ -7,6 +7,8 @@ use crate::retry_interval::check_retry_interval;
use crate::settings::SettingDes;
use crate::settings::JsonValueType;
use crate::opt::author_name_filter::check_author_name_filters;
#[cfg(feature = "ugoira")]
use crate::opt::crf::check_crf;
use crate::opt::proxy::check_proxy;
use crate::opt::size::parse_u32_size;
#[cfg(feature = "server")]
@@ -55,6 +57,8 @@ pub fn get_settings_list() -> Vec<SettingDes> {
SettingDes::new("db", gettext("Database settings."), JsonValueType::Object, Some(check_db_config)).unwrap(),
SettingDes::new("download-base", gettext("The base directory to save downloaded files."), JsonValueType::Str, None).unwrap(),
SettingDes::new("user-agent", gettext("The User-Agent header."), JsonValueType::Str, None).unwrap(),
#[cfg(feature = "ugoira")]
SettingDes::new("x264-crf", gettext("The Constant Rate Factor when converting ugoira(GIF) to video."), JsonValueType::Number, Some(check_crf)).unwrap(),
]
}

View File

@@ -164,7 +164,7 @@ UgoiraError convert_ugoira_to_mp4(const char* src, const char* dest, const Ugoir
int err = UGOIRA_OK;
int zip_err = 0;
zip_t* zip = NULL;
int dcrf = 18;
float dcrf = 18.0;
AVDictionaryEntry* tmp_ent = NULL;
if (max_fps <= 0) {
return RERR(UGOIRA_INVALID_MAX_FPS);
@@ -174,8 +174,8 @@ UgoiraError convert_ugoira_to_mp4(const char* src, const char* dest, const Ugoir
}
tmp_ent = av_dict_get(opts, "crf", NULL, 0);
if (tmp_ent) {
int tmp = 0;
if (sscanf(tmp_ent->value, "%i", &tmp) != 1) {
float tmp = 0;
if (sscanf(tmp_ent->value, "%f", &tmp) != 1) {
return RERR(UGOIRA_INVALID_CRF);
}
dcrf = tmp;
@@ -331,7 +331,7 @@ UgoiraError convert_ugoira_to_mp4(const char* src, const char* dest, const Ugoir
} else {
av_opt_set(eoc->priv_data, "preset", "slow", 0);
}
av_opt_set_int(eoc->priv_data, "crf", dcrf, 0);
av_opt_set_double(eoc->priv_data, "crf", dcrf, 0);
if (opts) {
tmp = av_dict_get(opts, "level", NULL, 0);
}