package probe import ( "context" "os/exec" "path/filepath" "testing" ) // TestAvailable never skips: the answer is a plain bool and must not panic on a // host without ffprobe. func TestAvailable(t *testing.T) { _ = Available() } // TestFile probes a fixture generated on the fly. It skips cleanly when ffprobe // or ffmpeg is missing, so the suite passes on a machine with neither. func TestFile(t *testing.T) { if !Available() { t.Skip("ffprobe not on PATH; skipping probe test") } ffmpeg, err := exec.LookPath("ffmpeg") if err != nil { t.Skip("ffmpeg not on PATH; cannot generate a fixture") } path := filepath.Join(t.TempDir(), "clip.mp4") // One second of H.264 video and AAC audio in an MP4. gen := exec.Command(ffmpeg, "-v", "error", "-y", "-f", "lavfi", "-i", "testsrc=size=64x48:rate=10:duration=1", "-f", "lavfi", "-i", "sine=frequency=440:duration=1", "-c:v", "libx264", "-c:a", "aac", "-shortest", path, ) if out, err := gen.CombinedOutput(); err != nil { t.Skipf("ffmpeg cannot produce a fixture here: %v\n%s", err, out) } info, err := File(context.Background(), path) if err != nil { t.Fatalf("File: %v", err) } if info.VCodec != "h264" { t.Errorf("VCodec = %q, want h264", info.VCodec) } if info.ACodec != "aac" { t.Errorf("ACodec = %q, want aac", info.ACodec) } if info.Width != 64 || info.Height != 48 { t.Errorf("dimensions = %dx%d, want 64x48", info.Width, info.Height) } if info.DurationMS < 500 || info.DurationMS > 2000 { t.Errorf("DurationMS = %d, want ~1000", info.DurationMS) } } // TestFileAudioOnly confirms an audio file reports no video codec, so a client // does not mistake an mp3 for a video with a missing track. func TestFileAudioOnly(t *testing.T) { if !Available() { t.Skip("ffprobe not on PATH; skipping probe test") } ffmpeg, err := exec.LookPath("ffmpeg") if err != nil { t.Skip("ffmpeg not on PATH; cannot generate a fixture") } path := filepath.Join(t.TempDir(), "tone.m4a") gen := exec.Command(ffmpeg, "-v", "error", "-y", "-f", "lavfi", "-i", "sine=frequency=440:duration=1", "-c:a", "aac", path, ) if out, err := gen.CombinedOutput(); err != nil { t.Skipf("ffmpeg cannot produce a fixture here: %v\n%s", err, out) } info, err := File(context.Background(), path) if err != nil { t.Fatalf("File: %v", err) } if info.VCodec != "" { t.Errorf("VCodec = %q, want empty for audio-only", info.VCodec) } if info.ACodec != "aac" { t.Errorf("ACodec = %q, want aac", info.ACodec) } } // TestFileMissing confirms a missing file is an error, not a silent zero Info. func TestFileMissing(t *testing.T) { if !Available() { t.Skip("ffprobe not on PATH; skipping probe test") } if _, err := File(context.Background(), filepath.Join(t.TempDir(), "nope.mp4")); err == nil { t.Fatal("File on a missing path: want error, got nil") } }