Set log level in FFmpeg + small fixes (#376)
* Small fixes/cleanup * Set log level to fatal in ffmpeg * Update dependencies
This commit is contained in:
parent
f5c3b3c85a
commit
9b1a00775b
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -257,9 +257,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitstream-io"
|
name = "bitstream-io"
|
||||||
|
@ -299,9 +299,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.70"
|
version = "1.0.71"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
|
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
]
|
]
|
||||||
|
@ -440,9 +440,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.2.0"
|
version = "3.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "377c9b002a72a0b2c1a18c62e2f3864bdfea4a015e3683a96e24aa45dd6c02d1"
|
checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -770,9 +770,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.22.2"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3bb9a13fa32bc5aeb64150cd3f32d6cf4c748f8f8a417cce5d2eb976a8370ba"
|
checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cc",
|
"cc",
|
||||||
|
@ -1008,9 +1008,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.9"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
@ -1365,9 +1365,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.78"
|
version = "1.0.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4eac2e6c19f5c3abc0c229bea31ff0b9b091c7b14990e8924b92902a303a0c0"
|
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{into_vec, list_index_of_regex, regex};
|
use crate::{into_vec, list_index, regex};
|
||||||
use itertools::chain;
|
use itertools::chain;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -321,13 +321,13 @@ impl Encoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns regex used for matching q/crf arguments in command line
|
/// Returns function pointer used for matching q/crf arguments in command line
|
||||||
fn q_regex(self) -> &'static Regex {
|
fn q_match_fn(self) -> fn(&str) -> bool {
|
||||||
match &self {
|
match self {
|
||||||
Self::aom | Self::vpx => regex!(r"--cq-level=.+"),
|
Self::aom | Self::vpx => |p| p.starts_with("--cq-level="),
|
||||||
Self::rav1e => regex!(r"--quantizer"),
|
Self::rav1e => |p| p == "--quantizer",
|
||||||
Self::svt_av1 => regex!(r"(--qp|-q|--crf)"),
|
Self::svt_av1 => |p| matches!(p, "--qp" | "-q" | "--crf"),
|
||||||
Self::x264 | Self::x265 => regex!(r"--crf"),
|
Self::x264 | Self::x265 => |p| p == "--crf",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ impl Encoder {
|
||||||
|
|
||||||
/// Returns changed q/crf in command line arguments
|
/// Returns changed q/crf in command line arguments
|
||||||
pub fn man_command(self, params: Vec<String>, q: usize) -> Vec<String> {
|
pub fn man_command(self, params: Vec<String>, q: usize) -> Vec<String> {
|
||||||
let index = list_index_of_regex(¶ms, self.q_regex())
|
let index = list_index(¶ms, self.q_match_fn())
|
||||||
.unwrap_or_else(|| panic!("No match found for params: {:#?}", params));
|
.unwrap_or_else(|| panic!("No match found for params: {:#?}", params));
|
||||||
|
|
||||||
let mut new_params = params;
|
let mut new_params = params;
|
||||||
|
|
|
@ -24,7 +24,6 @@ use crate::{
|
||||||
use chunk::Chunk;
|
use chunk::Chunk;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use regex::Regex;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::hash_map::DefaultHasher,
|
collections::hash_map::DefaultHasher,
|
||||||
|
@ -145,19 +144,16 @@ fn init_done(done: DoneJson) -> &'static DoneJson {
|
||||||
DONE_JSON.get_or_init(|| done)
|
DONE_JSON.get_or_init(|| done)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_index_of_regex(params: &[impl AsRef<str>], re: &Regex) -> Option<usize> {
|
pub fn list_index(params: &[impl AsRef<str>], is_match: fn(&str) -> bool) -> Option<usize> {
|
||||||
assert!(
|
assert!(!params.is_empty(), "received empty list of parameters");
|
||||||
!params.is_empty(),
|
|
||||||
"List index of regex got empty list of params"
|
|
||||||
);
|
|
||||||
|
|
||||||
for (i, cmd) in params.iter().enumerate() {
|
params.iter().enumerate().find_map(|(idx, s)| {
|
||||||
if re.is_match(cmd.as_ref()) {
|
if is_match(s.as_ref()) {
|
||||||
return Some(i);
|
Some(idx)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, strum::EnumString, strum::IntoStaticStr)]
|
#[derive(Serialize, Deserialize, Debug, strum::EnumString, strum::IntoStaticStr)]
|
||||||
|
|
|
@ -23,6 +23,7 @@ use flexi_logger::{Duplicate, FileSpec, Logger};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use path_abs::PathAbs;
|
use path_abs::PathAbs;
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
cmp,
|
cmp,
|
||||||
cmp::{Ordering, Reverse},
|
cmp::{Ordering, Reverse},
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
|
@ -92,6 +93,7 @@ impl EncodeArgs {
|
||||||
/// Initialize logging routines and create temporary directories
|
/// Initialize logging routines and create temporary directories
|
||||||
pub fn initialize(&mut self) -> anyhow::Result<()> {
|
pub fn initialize(&mut self) -> anyhow::Result<()> {
|
||||||
ffmpeg_next::init()?;
|
ffmpeg_next::init()?;
|
||||||
|
ffmpeg_next::util::log::set_level(ffmpeg_next::util::log::level::Level::Fatal);
|
||||||
|
|
||||||
info!("File hash: {}", hash_path(self.input.as_path()));
|
info!("File hash: {}", hash_path(self.input.as_path()));
|
||||||
|
|
||||||
|
@ -336,7 +338,6 @@ impl EncodeArgs {
|
||||||
let [cmd, arg] = self.encoder.help_command();
|
let [cmd, arg] = self.encoder.help_command();
|
||||||
String::from_utf8(Command::new(cmd).arg(arg).output().unwrap().stdout).unwrap()
|
String::from_utf8(Command::new(cmd).arg(arg).output().unwrap().stdout).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let valid_params = valid_params(&help_text);
|
let valid_params = valid_params(&help_text);
|
||||||
let invalid_params = invalid_params(&video_params, &valid_params);
|
let invalid_params = invalid_params(&video_params, &valid_params);
|
||||||
|
|
||||||
|
@ -400,9 +401,7 @@ impl EncodeArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
let encoder_bin = self.encoder.bin();
|
let encoder_bin = self.encoder.bin();
|
||||||
let settings_valid = which::which(&encoder_bin).is_ok();
|
if which::which(encoder_bin).is_err() {
|
||||||
|
|
||||||
if !settings_valid {
|
|
||||||
bail!(
|
bail!(
|
||||||
"Encoder {} not found. Is it installed in the system path?",
|
"Encoder {} not found. Is it installed in the system path?",
|
||||||
encoder_bin
|
encoder_bin
|
||||||
|
@ -565,7 +564,7 @@ impl EncodeArgs {
|
||||||
fn create_vs_chunk(
|
fn create_vs_chunk(
|
||||||
&self,
|
&self,
|
||||||
index: usize,
|
index: usize,
|
||||||
vs_script: PathBuf,
|
vs_script: &Path,
|
||||||
frame_start: usize,
|
frame_start: usize,
|
||||||
mut frame_end: usize,
|
mut frame_end: usize,
|
||||||
) -> Chunk {
|
) -> Chunk {
|
||||||
|
@ -614,16 +613,18 @@ impl EncodeArgs {
|
||||||
.map(|(start, end)| (*start, *end))
|
.map(|(start, end)| (*start, *end))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let vs_script = match &self.input {
|
let vs_script: Cow<Path> = match &self.input {
|
||||||
Input::VapourSynth(path) => path.clone(),
|
Input::VapourSynth(path) => Cow::Borrowed(path.as_ref()),
|
||||||
Input::Video(path) => create_vs_file(&self.temp, path, self.chunk_method).unwrap(),
|
Input::Video(path) => {
|
||||||
|
Cow::Owned(create_vs_file(&self.temp, path, self.chunk_method).unwrap())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let chunk_queue: Vec<Chunk> = chunk_boundaries
|
let chunk_queue: Vec<Chunk> = chunk_boundaries
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, (frame_start, frame_end))| {
|
.map(|(index, (frame_start, frame_end))| {
|
||||||
self.create_vs_chunk(index, vs_script.clone(), *frame_start, *frame_end)
|
self.create_vs_chunk(index, &vs_script, *frame_start, *frame_end)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
Target Quality has a really simple goal, instead of guessing what the CQ/CRF value to choose for desired level of video quality we set quality level we wan, quality goal is set in value of VMAF score we want to achieve and let the algorithm find CRF/CQ value that will result in that score, for each segment. Which simultaneously achieve 3 things, if compared to usual, single value CRF/CQ encode.
|
Target Quality has a really simple goal, instead of guessing what the CQ/CRF value to choose for desired level of video quality we set quality level we want, quality goal is set in value of VMAF score we want to achieve and let the algorithm find CRF/CQ value that will result in that score, for each segment. Which simultaneously achieve 3 things, if compared to usual, single value CRF/CQ encode.
|
||||||
|
|
||||||
- Ensuring better level of visual consistency than default rate controls
|
- Ensuring better level of visual consistency than default rate controls
|
||||||
- Give enough bitrate to complex segments to match target quality.
|
- Give enough bitrate to complex segments to match target quality.
|
||||||
|
|
Loading…
Reference in a new issue