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:
redzic 2021-10-08 18:47:08 -05:00 committed by GitHub
parent f5c3b3c85a
commit 9b1a00775b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 40 additions and 43 deletions

24
Cargo.lock generated
View file

@ -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",

View file

@ -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(&params, self.q_regex()) let index = list_index(&params, 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;

View file

@ -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)]

View file

@ -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();

View file

@ -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.