diff --git a/src/render/filter.rs b/src/render/filter.rs index c51aa23..b5a7e5c 100644 --- a/src/render/filter.rs +++ b/src/render/filter.rs @@ -220,10 +220,10 @@ impl Filter { writeln!( complex, "{}asplit=3{}{}{};", - channel('v', input), - vin[0], - vin[1], - vin[2] + channel('a', input), + ain[0], + ain[1], + ain[2] ); // next we cut those audio/videos into before, ff, after @@ -233,16 +233,24 @@ impl Filter { writeln!(complex, "{}atrim=duration={start}{};", ain[0], acut[0]); writeln!( complex, - "{}trim=start={start}:duration={duration}{};", + "{}trim=start={start}:duration={duration},setpts=PTS-STARTPTS{};", vin[1], vcut[1] ); writeln!( complex, - "{}atrim=start={start}:duration={duration}{};", + "{}atrim=start={start}:duration={duration},asetpts=PTS-STARTPTS{};", ain[1], acut[1] ); - writeln!(complex, "{}trim=start={end}{};", vin[2], vcut[2]); - writeln!(complex, "{}atrim=start={end}{};", ain[2], acut[2]); + writeln!( + complex, + "{}trim=start={end},setpts=PTS-STARTPTS{};", + vin[2], vcut[2] + ); + writeln!( + complex, + "{}atrim=start={end},asetpts=PTS-STARTPTS{};", + ain[2], acut[2] + ); // now we speed up the ff part let vff = next_tmp(filter_idx); diff --git a/src/render/mod.rs b/src/render/mod.rs index 521aae7..4fb17cd 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -28,11 +28,11 @@ const OUTRO_LEN: Time = Time { seconds: 5, micros: 0 }; -const TRANSITION: &str = "fadeblack"; const TRANSITION_LEN: Time = Time { seconds: 0, micros: 200_000 }; +const FF_MULTIPLIER: usize = 3; fn cmd() -> Command { let mut cmd = Command::new("busybox"); @@ -208,10 +208,7 @@ impl<'a> Renderer<'a> { .into_bytes() )?; let intro_mp4 = self.target.join("intro.mp4"); - svg2mp4(intro_svg, intro_mp4, Time { - seconds: 3, - micros: 0 - })?; + svg2mp4(intro_svg, intro_mp4, INTRO_LEN)?; // render outro to svg then mp4 let outro_svg = self.target.join("outro.svg"); @@ -220,10 +217,7 @@ impl<'a> Renderer<'a> { outro(source_res).to_string_pretty().into_bytes() )?; let outro_mp4 = self.target.join("outro.mp4"); - svg2mp4(outro_svg, outro_mp4, Time { - seconds: 5, - micros: 0 - })?; + svg2mp4(outro_svg, outro_mp4, OUTRO_LEN)?; // copy logo then render to png let logo_svg = self.target.join("logo.svg"); @@ -284,7 +278,20 @@ impl<'a> Renderer<'a> { }); part2 = rectrim.into(); - // TODO ff + // 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}"); + ffmpeg.add_filter(Filter::FastForward { + input: part2, + ffinput: ff.clone().into(), + start: *ff_st - start, + duration: *ff_end - *ff_st, + multiplier: FF_MULTIPLIER, + output: recff.clone().into() + }); + part2 = recff.into(); + } // TODO fade diff --git a/src/time.rs b/src/time.rs index e799cc8..c77443e 100644 --- a/src/time.rs +++ b/src/time.rs @@ -77,7 +77,7 @@ pub fn format_date_long(d: Date) -> String { format!("{:02}. {month} {:04}", d.day, d.year) } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Time { pub seconds: u32, pub micros: u32