add more filters

This commit is contained in:
jb-alvarado 2022-02-21 18:09:41 +01:00
parent 5083c62ec7
commit 83317b4378
4 changed files with 126 additions and 49 deletions

View File

@ -4,15 +4,15 @@ use std::path::Path;
use crate::utils::{is_close, Config, Program};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Filters {
pub audio_chain: Option<String>,
pub video_chain: Option<String>,
pub audio_map: Option<String>,
pub video_map: Option<String>,
struct Filters {
audio_chain: Option<String>,
video_chain: Option<String>,
audio_map: Option<String>,
video_map: Option<String>,
}
impl Filters {
pub fn new() -> Self {
fn new() -> Self {
Filters {
audio_chain: None,
video_chain: None,
@ -32,7 +32,11 @@ impl Filters {
}
}
None => {
self.audio_chain = Some(filter);
if filter.contains("aevalsrc") || filter.contains("anoisesrc") {
self.audio_chain = Some(filter);
} else {
self.audio_chain = Some(format!("[0:a]{filter}"));
}
self.audio_map = Some("[aout1]".to_string());
}
},
@ -45,7 +49,7 @@ impl Filters {
}
}
None => {
self.video_chain = Some(filter);
self.video_chain = Some(format!("[0:v]{filter}"));
self.video_map = Some("[vout1]".to_string());
}
},
@ -142,7 +146,7 @@ fn overlay(node: &mut Program, chain: &mut Filters, config: &Config, last_ad: bo
config.processing.logo_opacity
);
let logo_loop = "loop=loop=-1:size=1:start=0";
let mut logo_chain = format!("[v];movie={},{logo_loop},{opacity}", config.processing.logo);
let mut logo_chain = format!("null[v];movie={},{logo_loop},{opacity}", config.processing.logo);
if last_ad {
logo_chain.push_str(",fade=in:st=0:d=1.0:alpha=1")
@ -161,6 +165,54 @@ fn overlay(node: &mut Program, chain: &mut Filters, config: &Config, last_ad: bo
}
}
fn extend_video(node: &mut Program, chain: &mut Filters) {
let video_streams = node.probe.clone().unwrap().video_streams.unwrap();
if video_streams.len() > 0 {
let video_duration = &video_streams[0].duration;
if video_duration.is_some() {
let duration_float = video_duration.clone().unwrap().parse::<f64>().unwrap();
if node.out - node.seek > duration_float - node.seek + 0.1 {
chain.add_filter(format!("tpad=stop_mode=add:stop_duration={}", (node.out - node.seek) - (duration_float - node.seek)) , "video".into())
}
}
}
}
fn add_audio(node: &mut Program, chain: &mut Filters) {
let audio_streams = node.probe.clone().unwrap().audio_streams.unwrap();
if audio_streams.len() == 0 {
println!("Clip: '{}' has no audio!", node.source);
let audio = format!(
"aevalsrc=0:channel_layout=stereo:duration={}:sample_rate=48000",
node.out - node.seek
);
chain.add_filter(audio, "audio".into());
}
}
fn extend_audio(node: &mut Program, chain: &mut Filters) {
let audio_streams = node.probe.clone().unwrap().audio_streams.unwrap();
if audio_streams.len() > 0 {
let audio_duration = &audio_streams[0].duration;
if audio_duration.is_some() {
let duration_float = audio_duration.clone().unwrap().parse::<f64>().unwrap();
if node.out - node.seek > duration_float- node.seek + 0.1 {
chain.add_filter(format!("apad=whole_dur={}", node.out - node.seek), "audio".into())
}
}
}
}
fn audio_volume(chain: &mut Filters, config: &Config) {
if config.processing.volume != 1.0 {
chain.add_filter(format!("volume={}", config.processing.volume), "audio".into())
}
}
pub fn filter_chains(node: &mut Program, config: &Config, last: bool, next: bool) -> Vec<String> {
let mut filters = Filters::new();
let probe = node.probe.clone();
@ -189,48 +241,48 @@ pub fn filter_chains(node: &mut Program, config: &Config, last: bool, next: bool
&mut filters,
&config,
);
fade(node, &mut filters, "audio".into());
extend_video(node, &mut filters);
fade(node, &mut filters, "video".into());
overlay(node, &mut filters, &config, last, next);
add_audio(node, &mut filters);
extend_audio(node, &mut filters);
fade(node, &mut filters, "audio".into());
audio_volume(&mut filters, &config);
}
None => {
println!("Clip has no media probe object. No filter applied!")
}
}
let mut filter_cmd = vec!["-filter_complex".to_string()];
let mut filter_cmd = vec![];
let mut filter_str: String = "".to_string();
let mut filter_map: Vec<String> = vec![];
if filters.audio_chain.is_some() {
filter_str.push_str(
format!(
"[0:a]{}{};",
filters.audio_chain.unwrap(),
filters.audio_map.clone().unwrap()
)
.as_str(),
);
filter_str.push_str(filters.audio_chain.unwrap().as_str());
filter_str.push_str(filters.audio_map.clone().unwrap().as_str());
filter_map.append(&mut vec!["-map".to_string(), filters.audio_map.unwrap()]);
} else {
filter_map.append(&mut vec!["-map".to_string(), "0:a".to_string()]);
}
if filters.video_chain.is_some() {
filter_str.push_str(
format!(
"[0:v]{}{}",
filters.video_chain.unwrap(),
filters.video_map.clone().unwrap()
)
.as_str(),
);
if filter_str.len() > 10 {
filter_str.push_str(";")
}
filter_str.push_str(filters.video_chain.unwrap().as_str());
filter_str.push_str(filters.video_map.clone().unwrap().as_str());
filter_map.append(&mut vec!["-map".to_string(), filters.video_map.unwrap()]);
} else {
filter_map.append(&mut vec!["-map".to_string(), "0:v".to_string()]);
}
filter_cmd.push(filter_str);
if filter_str.len() > 10 {
filter_cmd.push("-filter_complex".to_string());
filter_cmd.push(filter_str);
}
filter_cmd.append(&mut filter_map);
filter_cmd

View File

@ -9,16 +9,33 @@ use crate::utils::{program, sec_to_time, Config};
pub fn play(config: Config) -> io::Result<()> {
let get_source = program(config.clone());
let dec_settings = config.processing.settings.unwrap();
let mut enc_cmd = vec![
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-i",
"pipe:0",
];
let mut enc_filter: Vec<String> = vec![];
if config.text.add_text && !config.text.over_pre {
let text_filter: String = format!(
"null,zmq=b=tcp\\\\://'{}',drawtext=text='':fontfile='{}'",
config.text.bind_address.replace(":", "\\:"),
config.text.fontfile
);
enc_filter = vec!["-vf".to_string(), text_filter];
}
enc_cmd.append(&mut enc_filter.iter().map(String::as_str).collect());
println!("Encoder CMD: '{:?}'", enc_cmd);
let mut enc_proc = Command::new("ffplay")
.args([
"-hide_banner",
"-nostats",
"-v",
"level+error",
"-i",
"pipe:0",
])
.args(enc_cmd)
.stdin(Stdio::piped())
// .stderr(Stdio::piped())
.spawn()
@ -28,22 +45,23 @@ pub fn play(config: Config) -> io::Result<()> {
// let mut buffer = vec![0; 65376];
if let Some(mut enc_input) = enc_proc.stdin.take() {
for node in get_source {
// println!("Play: {:#?}", node);
for node in get_source {
println!("Node begin: {:?}", sec_to_time(node.begin.unwrap()));
//println!("Play: {:#?}", node.filter);
let cmd = node.cmd.unwrap();
let filter = node.filter.unwrap();
let mut dec_cmd = vec![
"-v",
"level+error",
"-hide_banner",
"-nostats"
];
let mut dec_cmd = vec!["-v", "level+error", "-hide_banner", "-nostats"];
dec_cmd.append(&mut cmd.iter().map(String::as_str).collect());
dec_cmd.append(&mut filter.iter().map(String::as_str).collect());
if filter.len() > 1 {
dec_cmd.append(&mut filter.iter().map(String::as_str).collect());
}
dec_cmd.append(&mut dec_settings.iter().map(String::as_str).collect());
println!("Play: {:?}", dec_cmd);
let mut dec_proc = Command::new("ffmpeg")
.args(dec_cmd)
@ -59,14 +77,20 @@ pub fn play(config: Config) -> io::Result<()> {
let dec_output = dec_proc.wait_with_output()?;
if dec_output.stderr.len() > 0 {
println!("[Encoder] {}", String::from_utf8(dec_output.stderr).unwrap());
println!(
"[Encoder] {}",
String::from_utf8(dec_output.stderr).unwrap()
);
}
}
}
enc_proc.wait()?;
let enc_output = enc_proc.wait_with_output()?;
println!("[Encoder] {}", String::from_utf8(enc_output.stderr).unwrap());
println!(
"[Encoder] {}",
String::from_utf8(enc_output.stderr).unwrap()
);
}
Ok(())

View File

@ -38,7 +38,7 @@ pub struct Args {
pub output: Option<String>,
#[clap(short, long, help = "set audio volume")]
pub volume: Option<String>,
pub volume: Option<f64>,
}
pub fn get_args() -> Args {

View File

@ -60,7 +60,7 @@ pub struct Processing {
pub loud_tp: f32,
pub loud_lra: f32,
pub output_count: u32,
pub volume: String,
pub volume: f64,
pub settings: Option<Vec<String>>,
}
@ -91,6 +91,7 @@ pub struct Text {
pub add_text: bool,
pub over_pre: bool,
pub bind_address: String,
pub fontfile: String,
pub text_from_filename: bool,
pub style: String,
pub regex: String,