diff --git a/internal/worker/command_ffmpeg.go b/internal/worker/command_ffmpeg.go index 55c6d316..b60ff275 100644 --- a/internal/worker/command_ffmpeg.go +++ b/internal/worker/command_ffmpeg.go @@ -214,6 +214,9 @@ func (p *CreateVideoParams) getInputGlob() ([]string, func(), error) { } cliArgs := []string{ + // FFmpeg needs the input frame rate as well, otherwise it'll default to 25 + // FPS, and mysteriously drop frames when rendering a 24 FPS shot. + "-r", strconv.FormatFloat(p.fps, 'f', -1, 64), "-pattern_type", "glob", "-i", crosspath.ToSlash(p.inputGlob), } diff --git a/internal/worker/command_ffmpeg_test.go b/internal/worker/command_ffmpeg_test.go index bf3a6bd0..1de4dacf 100644 --- a/internal/worker/command_ffmpeg_test.go +++ b/internal/worker/command_ffmpeg_test.go @@ -42,10 +42,11 @@ func TestCmdFramesToVideoSimplePosix(t *testing.T) { cliArgs := []string{ "-v", "quiet", // exe - "-report", // argsBefore + "-report", // argsBefore + "-r", "10", // input frame rate "-pattern_type", "glob", "-i", "path/to/renders/*.png", // inputGlob "-c:v", "hevc", "-crf", "31", "-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2", // args - "-r", "10", // fps + "-r", "10", // output frame rate "path/to/renders/preview.mkv", // outputFile } mocks.cli.EXPECT().CommandContext(gomock.Any(), "/path/to/ffmpeg", cliArgs).Return(nil)