From 3bc33fc34cf8f6dd70b683da55208613f2ba7271 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Oct 2026 16:46:14 +0200 Subject: [PATCH] test(audio): ffmpeg transcode to 16 kHz mono PCM, always (red) Red: audio.FFmpeg is undefined. Co-Authored-By: Claude Sonnet 5.5 --- internal/adapters/audio/ffmpeg_test.go | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 internal/adapters/audio/ffmpeg_test.go diff --git a/internal/adapters/audio/ffmpeg_test.go b/internal/adapters/audio/ffmpeg_test.go new file mode 100644 index 0000000..1aaf6d1 --- /dev/null +++ b/internal/adapters/audio/ffmpeg_test.go @@ -0,0 +1,58 @@ +package audio_test + +import ( + "context" + "errors" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "git.d-ma.be/mathias/tapir/internal/adapters/audio" +) + +func TestFFmpegToWAV_AsksForSixteenKilohertzMonoPCMAlways(t *testing.T) { + // Always transcode, even when the input already is 16 kHz mono: a Teams export + // often is, and the point is to not ASSUME (ADR-033). Records the argv. + rec := filepath.Join(t.TempDir(), "argv") + bin := stub(t, `printf '%s\n' "$@" > `+rec+`; : > "$(eval echo \${$#})"`) + + err := (&audio.FFmpeg{Bin: bin}).ToWAV(context.Background(), "/spool/in", filepath.Join(t.TempDir(), "out.wav")) + + require.NoError(t, err) + raw, err := os.ReadFile(rec) + require.NoError(t, err) + argv := strings.Split(strings.TrimSpace(string(raw)), "\n") + joined := " " + strings.Join(argv, " ") + " " + for _, want := range []string{" -ac 1 ", " -ar 16000 ", " -c:a pcm_s16le ", " -vn ", " -i /spool/in "} { + assert.Contains(t, joined, want) + } + assert.True(t, strings.HasSuffix(strings.TrimSpace(joined), "out.wav"), "the output path is the last argument") +} + +func TestFFmpegToWAV_NonzeroExitIsAnErrorCarryingStderr(t *testing.T) { + bin := stub(t, `echo "moov atom not found" >&2; exit 1`) + + err := (&audio.FFmpeg{Bin: bin}).ToWAV(context.Background(), "/in", filepath.Join(t.TempDir(), "o.wav")) + + require.Error(t, err) + assert.Contains(t, err.Error(), "moov atom not found") +} + +func TestFFmpegToWAV_ZeroExitWithNoOutputIsAnError(t *testing.T) { + bin := stub(t, `exit 0`) + + err := (&audio.FFmpeg{Bin: bin}).ToWAV(context.Background(), "/in", filepath.Join(t.TempDir(), "never-written.wav")) + + require.Error(t, err) +} + +func TestFFmpegToWAV_MissingBinaryIsAnError(t *testing.T) { + err := (&audio.FFmpeg{Bin: filepath.Join(t.TempDir(), "no-ffmpeg")}).ToWAV(context.Background(), "/in", "/out.wav") + + require.Error(t, err) + assert.False(t, errors.Is(err, context.Canceled)) +}