From 85297910ae0b93f644ddc00f4779d18d13cc624f Mon Sep 17 00:00:00 2001 From: Dominic Date: Mon, 30 Oct 2023 22:48:53 +0100 Subject: [PATCH] try to fix it enough to render a lecture --- Cargo.toml | 6 +----- src/render/filter.rs | 42 ++++++++++++++++++++++++------------------ src/render/mod.rs | 36 +++++++++++++++++++++++++++--------- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ae1ba4c..cb16d6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/src/render/filter.rs b/src/render/filter.rs index b5a7e5c..a846c7d 100644 --- a/src/render/filter.rs +++ b/src/render/filter.rs @@ -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>, - n: usize, + inputs: VecDeque>, 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); } } diff --git a/src/render/mod.rs b/src/render/mod.rs index 6accb37..ec0677c 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -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() });