try to fix it enough to render a lecture

This commit is contained in:
Dominic 2023-10-30 22:48:53 +01:00
parent 228e1648f0
commit 85297910ae
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
3 changed files with 52 additions and 32 deletions

View file

@ -10,13 +10,9 @@ edition = "2021"
anyhow = "1.0" anyhow = "1.0"
camino = "1.1" camino = "1.1"
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
#ffmpeg = { package = "ffmpeg-next", version = "6.0" }
indexmap = "1.9" indexmap = "1.9"
rational = "1.4" rational = "1.5"
serde = { version = "1.0.188", features = ["derive"] } serde = { version = "1.0.188", features = ["derive"] }
serde_with = "3.4" serde_with = "3.4"
svgwriter = "0.1" svgwriter = "0.1"
toml = { package = "basic-toml", version = "0.1.4" } toml = { package = "basic-toml", version = "0.1.4" }
[patch.crates-io]
rational = { git = "https://github.com/msrd0/rational", branch = "error" }

View file

@ -1,5 +1,5 @@
use crate::time::{format_time, Time}; 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 { pub(crate) enum Filter {
/// Trim audio and video alike /// Trim audio and video alike
@ -28,8 +28,7 @@ pub(crate) enum Filter {
/// Concatenate audio and video. /// Concatenate audio and video.
Concat { Concat {
inputs: Vec<Cow<'static, str>>, inputs: VecDeque<Cow<'static, str>>,
n: usize,
output: Cow<'static, str> output: Cow<'static, str>
}, },
@ -48,14 +47,14 @@ pub(crate) enum Filter {
output: Cow<'static, str> output: Cow<'static, str>
}, },
/// Fast forward. Too complex to explain. Its magic. /// Fast forward. Will output before, ff, and after parts separately.
FastForward { FastForward {
input: Cow<'static, str>, input: Cow<'static, str>,
ffinput: Cow<'static, str>, ffinput: Cow<'static, str>,
start: Time, start: Time,
duration: Time, duration: Time,
multiplier: usize, 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 { for i in inputs {
write!(complex, "{}{}", channel('v', i), channel('a', i)); write!(complex, "{}{}", channel('v', i), channel('a', i));
} }
writeln!( writeln!(
complex, complex,
"concat=n={n}:v=1:a=1{}{};", "concat=n={}:v=1:a=1{}{};",
inputs.len(),
channel('v', output), channel('v', output),
channel('a', output) channel('a', output)
); );
@ -266,17 +266,23 @@ impl Filter {
channel('v', ffinput) channel('v', ffinput)
); );
// and finally we concatenate everything back together // and finally we place everything into the output
writeln!( for (i, o) in [
complex, (&vcut[0], &output[0]),
"{}{}{voverlay}{aff}{}{}concat=n=3:v=1:a=1{}{};", (&voverlay, &output[1]),
vcut[0], (&vcut[2], &output[2])
acut[0], ] {
vcut[2], write!(complex, "{i}null{};", channel('v', o));
acut[2], }
channel('v', output), writeln!(complex);
channel('a', output) for (i, o) in [
); (&acut[0], &output[0]),
(&aff, &output[1]),
(&acut[2], &output[2])
] {
write!(complex, "{i}anull{};", channel('a', o));
}
writeln!(complex);
} }
} }

View file

@ -15,6 +15,7 @@ use camino::{Utf8Path as Path, Utf8PathBuf as PathBuf};
use rational::Rational; use rational::Rational;
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::VecDeque,
fs::{self, File}, fs::{self, File},
io::Write as _, io::Write as _,
process::{Command, Stdio} process::{Command, Stdio}
@ -226,7 +227,7 @@ impl<'a> Renderer<'a> {
include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/logo.svg")) include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/logo.svg"))
)?; )?;
let logo_png = self.target.join("logo.png"); 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 // copy fastforward then render to png
let fastforward_svg = self.target.join("fastforward.svg"); let fastforward_svg = self.target.join("fastforward.svg");
@ -241,7 +242,7 @@ impl<'a> Renderer<'a> {
svg2png( svg2png(
&fastforward_svg, &fastforward_svg,
&fastforward_png, &fastforward_png,
128 * 1920 / source_res.width() 128 * source_res.width() / 1920
)?; )?;
Ok(()) Ok(())
@ -251,7 +252,13 @@ impl<'a> Renderer<'a> {
let mut output = self.target.join(format!( let mut output = self.target.join(format!(
"{}-{}p.mp4", "{}-{}p.mp4",
self.slug, 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()); let mut ffmpeg = Ffmpeg::new(output.clone());
@ -328,26 +335,37 @@ impl<'a> Renderer<'a> {
}); });
part3 = outrofade.into(); part3 = outrofade.into();
// prepare list for concat
let mut parts = VecDeque::new();
parts.push_back(part2);
// fast-forward the requested parts in reverse order // fast-forward the requested parts in reverse order
project.source.fast.sort(); project.source.fast.sort();
for (i, (ff_st, ff_end)) in project.source.fast.iter().rev().enumerate() { 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 { ffmpeg.add_filter(Filter::FastForward {
input: part2, input: parts.pop_front().unwrap(),
ffinput: ff.clone().into(), ffinput: ff.clone().into(),
start: *ff_st - start, start: *ff_st - start,
duration: *ff_end - *ff_st, duration: *ff_end - *ff_st,
multiplier: FF_MULTIPLIER, 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 // concatenate everything
parts.push_front(part1);
parts.push_back(part3);
let concat = "concat"; let concat = "concat";
ffmpeg.add_filter(Filter::Concat { ffmpeg.add_filter(Filter::Concat {
inputs: vec![part1, part2, part3], inputs: parts,
n: 3,
output: concat.into() output: concat.into()
}); });