try to fix it enough to render a lecture
This commit is contained in:
parent
228e1648f0
commit
85297910ae
3 changed files with 52 additions and 32 deletions
|
@ -10,13 +10,9 @@ edition = "2021"
|
|||
anyhow = "1.0"
|
||||
camino = "1.1"
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
#ffmpeg = { package = "ffmpeg-next", version = "6.0" }
|
||||
indexmap = "1.9"
|
||||
rational = "1.4"
|
||||
rational = "1.5"
|
||||
serde = { version = "1.0.188", features = ["derive"] }
|
||||
serde_with = "3.4"
|
||||
svgwriter = "0.1"
|
||||
toml = { package = "basic-toml", version = "0.1.4" }
|
||||
|
||||
[patch.crates-io]
|
||||
rational = { git = "https://github.com/msrd0/rational", branch = "error" }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::time::{format_time, Time};
|
||||
use std::{borrow::Cow, fmt::Write as _};
|
||||
use std::{borrow::Cow, collections::VecDeque, fmt::Write as _};
|
||||
|
||||
pub(crate) enum Filter {
|
||||
/// Trim audio and video alike
|
||||
|
@ -28,8 +28,7 @@ pub(crate) enum Filter {
|
|||
|
||||
/// Concatenate audio and video.
|
||||
Concat {
|
||||
inputs: Vec<Cow<'static, str>>,
|
||||
n: usize,
|
||||
inputs: VecDeque<Cow<'static, str>>,
|
||||
output: Cow<'static, str>
|
||||
},
|
||||
|
||||
|
@ -48,14 +47,14 @@ pub(crate) enum Filter {
|
|||
output: Cow<'static, str>
|
||||
},
|
||||
|
||||
/// Fast forward. Too complex to explain. Its magic.
|
||||
/// Fast forward. Will output before, ff, and after parts separately.
|
||||
FastForward {
|
||||
input: Cow<'static, str>,
|
||||
ffinput: Cow<'static, str>,
|
||||
start: Time,
|
||||
duration: Time,
|
||||
multiplier: usize,
|
||||
output: Cow<'static, str>
|
||||
output: [Cow<'static, str>; 3]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,13 +151,14 @@ impl Filter {
|
|||
);
|
||||
},
|
||||
|
||||
Self::Concat { inputs, n, output } => {
|
||||
Self::Concat { inputs, output } => {
|
||||
for i in inputs {
|
||||
write!(complex, "{}{}", channel('v', i), channel('a', i));
|
||||
}
|
||||
writeln!(
|
||||
complex,
|
||||
"concat=n={n}:v=1:a=1{}{};",
|
||||
"concat=n={}:v=1:a=1{}{};",
|
||||
inputs.len(),
|
||||
channel('v', output),
|
||||
channel('a', output)
|
||||
);
|
||||
|
@ -266,17 +266,23 @@ impl Filter {
|
|||
channel('v', ffinput)
|
||||
);
|
||||
|
||||
// and finally we concatenate everything back together
|
||||
writeln!(
|
||||
complex,
|
||||
"{}{}{voverlay}{aff}{}{}concat=n=3:v=1:a=1{}{};",
|
||||
vcut[0],
|
||||
acut[0],
|
||||
vcut[2],
|
||||
acut[2],
|
||||
channel('v', output),
|
||||
channel('a', output)
|
||||
);
|
||||
// and finally we place everything into the output
|
||||
for (i, o) in [
|
||||
(&vcut[0], &output[0]),
|
||||
(&voverlay, &output[1]),
|
||||
(&vcut[2], &output[2])
|
||||
] {
|
||||
write!(complex, "{i}null{};", channel('v', o));
|
||||
}
|
||||
writeln!(complex);
|
||||
for (i, o) in [
|
||||
(&acut[0], &output[0]),
|
||||
(&aff, &output[1]),
|
||||
(&acut[2], &output[2])
|
||||
] {
|
||||
write!(complex, "{i}anull{};", channel('a', o));
|
||||
}
|
||||
writeln!(complex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
|
|||
use rational::Rational;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::VecDeque,
|
||||
fs::{self, File},
|
||||
io::Write as _,
|
||||
process::{Command, Stdio}
|
||||
|
@ -226,7 +227,7 @@ impl<'a> Renderer<'a> {
|
|||
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/logo.svg"))
|
||||
)?;
|
||||
let logo_png = self.target.join("logo.png");
|
||||
svg2png(&logo_svg, &logo_png, 150 * 1920 / source_res.width())?;
|
||||
svg2png(&logo_svg, &logo_png, 150 * source_res.width() / 1920)?;
|
||||
|
||||
// copy fastforward then render to png
|
||||
let fastforward_svg = self.target.join("fastforward.svg");
|
||||
|
@ -241,7 +242,7 @@ impl<'a> Renderer<'a> {
|
|||
svg2png(
|
||||
&fastforward_svg,
|
||||
&fastforward_png,
|
||||
128 * 1920 / source_res.width()
|
||||
128 * source_res.width() / 1920
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -251,7 +252,13 @@ impl<'a> Renderer<'a> {
|
|||
let mut output = self.target.join(format!(
|
||||
"{}-{}p.mp4",
|
||||
self.slug,
|
||||
project.source.metadata.as_ref().unwrap().source_res.width()
|
||||
project
|
||||
.source
|
||||
.metadata
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.source_res
|
||||
.height()
|
||||
));
|
||||
let mut ffmpeg = Ffmpeg::new(output.clone());
|
||||
|
||||
|
@ -328,26 +335,37 @@ impl<'a> Renderer<'a> {
|
|||
});
|
||||
part3 = outrofade.into();
|
||||
|
||||
// prepare list for concat
|
||||
let mut parts = VecDeque::new();
|
||||
parts.push_back(part2);
|
||||
|
||||
// fast-forward the requested parts in reverse order
|
||||
project.source.fast.sort();
|
||||
for (i, (ff_st, ff_end)) in project.source.fast.iter().rev().enumerate() {
|
||||
let recff = format!("recff{i}");
|
||||
let recff = [
|
||||
format!("recff{i}b").into(),
|
||||
format!("recff{i}ff").into(),
|
||||
format!("recff{i}a").into()
|
||||
];
|
||||
ffmpeg.add_filter(Filter::FastForward {
|
||||
input: part2,
|
||||
input: parts.pop_front().unwrap(),
|
||||
ffinput: ff.clone().into(),
|
||||
start: *ff_st - start,
|
||||
duration: *ff_end - *ff_st,
|
||||
multiplier: FF_MULTIPLIER,
|
||||
output: recff.clone().into()
|
||||
output: recff.clone()
|
||||
});
|
||||
part2 = recff.into();
|
||||
parts.push_front(recff[2].clone());
|
||||
parts.push_front(recff[1].clone());
|
||||
parts.push_front(recff[0].clone());
|
||||
}
|
||||
|
||||
// concatenate everything
|
||||
parts.push_front(part1);
|
||||
parts.push_back(part3);
|
||||
let concat = "concat";
|
||||
ffmpeg.add_filter(Filter::Concat {
|
||||
inputs: vec![part1, part2, part3],
|
||||
n: 3,
|
||||
inputs: parts,
|
||||
output: concat.into()
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue