Skip to content
Snippets Groups Projects
Unverified Commit a0f1caa3 authored by Dominic Meiser's avatar Dominic Meiser
Browse files

more filter logic

parent fd5d3ab1
No related branches found
No related tags found
No related merge requests found
#![allow(clippy::manual_range_contains)]
#![warn(rust_2018_idioms)]
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
......@@ -27,7 +28,7 @@ struct Args {
course: String
}
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
#[derive(Clone, Copy, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
enum Resolution {
/// 640x360
......
use super::cmd;
use super::{cmd, filter::Filter};
use crate::time::{format_time, Time};
use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
use rational::Rational;
......@@ -45,66 +45,12 @@ impl FfmpegInput {
}
}
pub(crate) enum Filter {
Concat {
inputs: Vec<Cow<'static, str>>,
n: usize,
output: Cow<'static, str>
},
FadeIn {
input: Cow<'static, str>,
start: Time,
duration: Time,
output: Cow<'static, str>
},
FadeOut {
input: Cow<'static, str>,
start: Time,
duration: Time,
output: Cow<'static, str>
},
Overlay {
video_input: Cow<'static, str>,
overlay_input: Cow<'static, str>,
x: Cow<'static, str>,
y: Cow<'static, str>,
output: Cow<'static, str>
},
GenerateSilence {
output: Cow<'static, str>
}
}
impl Filter {
fn is_video_filter(&self) -> bool {
matches!(
self,
Self::Concat { .. }
| Self::FadeIn { .. }
| Self::FadeOut { .. }
| Self::Overlay { .. }
)
}
fn is_audio_filter(&self) -> bool {
matches!(
self,
Self::Concat { .. }
| Self::FadeIn { .. }
| Self::FadeOut { .. }
| Self::GenerateSilence { .. }
)
}
}
pub(crate) struct Ffmpeg {
inputs: Vec<FfmpegInput>,
filters: Vec<Filter>,
output: PathBuf
output: PathBuf,
filter_idx: usize
}
impl Ffmpeg {
......@@ -112,7 +58,9 @@ impl Ffmpeg {
Self {
inputs: Vec::new(),
filters: Vec::new(),
output
output,
filter_idx: 0
}
}
......@@ -152,6 +100,12 @@ impl Ffmpeg {
} else {
cmd.arg("-c:v").arg("copy");
}
if aenc {
cmd.arg("-c:a").arg("aac");
cmd.arg("-b:a").arg("128000");
} else {
cmd.arg("-c:a").arg("copy");
}
unimplemented!()
}
......
use crate::time::{format_time, Time};
use std::{borrow::Cow, fmt::Write as _};
pub(crate) enum Filter {
/// Trim audio and video alike
Trim {
input: Cow<'static, str>,
start: Option<Time>,
duration: Option<Time>,
output: Cow<'static, str>
},
/// Apply an alpha channel on the video. No audio.
Alpha {
input: Cow<'static, str>,
alpha: f32,
output: Cow<'static, str>
},
/// Overlay the one video over the other. The audio is copied.
Overlay {
video_input: Cow<'static, str>,
overlay_input: Cow<'static, str>,
x: Cow<'static, str>,
y: Cow<'static, str>,
output: Cow<'static, str>
},
/// Concatenate audio and video.
Concat {
inputs: Vec<Cow<'static, str>>,
n: usize,
output: Cow<'static, str>
},
/// Fade audio and video.
Fade {
input: Cow<'static, str>,
direction: &'static str,
start: Time,
duration: Time,
output: Cow<'static, str>
},
/// Generate silence. The video is copied.
GenerateSilence {
video: Cow<'static, str>,
output: Cow<'static, str>
}
}
impl Filter {
pub(crate) fn is_video_filter(&self) -> bool {
matches!(
self,
Self::Trim { .. }
| Self::Alpha { .. }
| Self::Concat { .. }
| Self::Fade { .. }
| Self::Overlay { .. }
)
}
pub(crate) fn is_audio_filter(&self) -> bool {
matches!(
self,
Self::Trim { .. }
| Self::Concat { .. }
| Self::Fade { .. }
| Self::GenerateSilence { .. }
)
}
fn append_to_complex_filter(&self, complex: &mut String, filter_idx: &mut usize) {
match self {
Self::Trim {
input,
start,
duration,
output
} => {
let mut args = String::new();
if let Some(start) = start {
write!(args, "start={}", format_time(*start));
}
if let Some(duration) = duration {
if !args.is_empty() {
args += ":";
}
write!(args, "duration={}", format_time(*duration));
}
writeln!(
complex,
"{}trim={args},setpts=PTS-STARTPTS{};",
channel('v', input),
channel('v', output)
);
writeln!(
complex,
"{}atrim={args},asetpts=PTS-STARTPTS{};",
channel('a', input),
channel('a', output)
);
},
Self::Alpha {
input,
alpha,
output
} => {
writeln!(
complex,
"{}format=yuva444p,colorchannelmixer=aa={alpha}{};",
channel('v', input),
channel('v', output)
);
},
Self::Overlay {
video_input,
overlay_input,
x,
y,
output
} => {
writeln!(
complex,
"{}{}overlay=x={x}:y={y}{};",
channel('v', video_input),
channel('v', overlay_input),
channel('v', output)
);
writeln!(
complex,
"{}anull{};",
channel('a', video_input),
channel('a', output)
);
},
Self::Concat { inputs, n, output } => {
for i in inputs {
write!(complex, "{}{}", channel('v', i), channel('a', i));
}
writeln!(
complex,
"concat=n={n}:v=1:a=1{}{};",
channel('v', output),
channel('a', output)
);
},
Self::Fade {
input,
direction,
start,
duration,
output
} => {
let args = format!(
"{direction}:st={}:d={}",
format_time(*start),
format_time(*duration)
);
writeln!(
complex,
"{}fade={args}{};",
channel('v', input),
channel('v', output)
);
writeln!(
complex,
"{}afade=t={args}{};",
channel('a', input),
channel('a', output)
);
},
Self::GenerateSilence { video, output } => {
writeln!(
complex,
"{}null{};",
channel('v', video),
channel('v', output)
);
writeln!(complex, "aevalsrc=0:s=48000{};", channel('a', output));
},
_ => unimplemented!()
}
}
}
fn channel(channel: char, id: &str) -> String {
if id.chars().any(|ch| !ch.is_digit(10)) {
format!("[{channel}_{id}]")
} else {
format!("[{id}:{channel}]")
}
}
#![allow(warnings)]
pub mod ffmpeg;
mod filter;
use crate::{
iotro::intro,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment