diff --git a/internal/adapters/audio/ffmpeg_test.go b/internal/adapters/audio/ffmpeg_test.go index 9a4a852..bb8c6c1 100644 --- a/internal/adapters/audio/ffmpeg_test.go +++ b/internal/adapters/audio/ffmpeg_test.go @@ -77,3 +77,35 @@ printf data > "$last"`) assert.Less(t, pw, in, "input options must come BEFORE -i or ffmpeg applies them to the output") assert.Less(t, fw, in) } + +func TestFFmpegToWAV_CapsTheOutputLengthWhenAMaximumIsSet(t *testing.T) { + // The duration limit is a CLAIM in the file's header; a file that lies about it can + // convert to hours of audio (adversarial review F2: a 2 h file claiming 10 s became a + // 120-minute WAV). The cap is an OUTPUT option, after -i, with a minute of slack. + rec := filepath.Join(t.TempDir(), "argv") + bin := stub(t, `printf '%s\n' "$@" > `+rec+` +for a; do last="$a"; done +printf data > "$last"`) + + err := (&audio.FFmpeg{Bin: bin, MaxSeconds: 5400}).ToWAV(context.Background(), "/spool/in", filepath.Join(t.TempDir(), "out.wav")) + + require.NoError(t, err) + raw, err := os.ReadFile(rec) + require.NoError(t, err) + joined := " " + strings.Join(strings.Split(strings.TrimSpace(string(raw)), "\n"), " ") + " " + assert.Contains(t, joined, " -t 5460 ", "limit plus a minute of slack") + assert.Less(t, strings.Index(joined, " -i /spool/in "), strings.Index(joined, " -t 5460 "), "-t after -i is an output cap; before it, an input one") +} + +func TestFFmpegToWAV_WithNoMaximumThereIsNoLengthCap(t *testing.T) { + rec := filepath.Join(t.TempDir(), "argv") + bin := stub(t, `printf '%s\n' "$@" > `+rec+` +for a; do last="$a"; done +printf data > "$last"`) + + require.NoError(t, (&audio.FFmpeg{Bin: bin}).ToWAV(context.Background(), "/spool/in", filepath.Join(t.TempDir(), "out.wav"))) + + raw, err := os.ReadFile(rec) + require.NoError(t, err) + assert.NotContains(t, " "+strings.ReplaceAll(string(raw), "\n", " ")+" ", " -t ") +}