package ffmpeg import ( "os" "os/exec" "path/filepath" "runtime" ) // BinPaths holds paths to ffmpeg and ffprobe binaries. type BinPaths struct { FFmpeg string FFprobe string } // Detect finds ffmpeg and ffprobe binaries. // Priority: 1. build/bin/ (bundled) 2. PATH func Detect() (BinPaths, error) { exeDir, err := os.Executable() if err != nil { exeDir = "." } else { exeDir = filepath.Dir(exeDir) } bundled := BinPaths{ FFmpeg: binPath(exeDir, "ffmpeg"), FFprobe: binPath(exeDir, "ffprobe"), } // Check bundled first if fileExists(bundled.FFmpeg) && fileExists(bundled.FFprobe) { return bundled, nil } // Fall back to PATH return findOnPath() } func binPath(baseDir, name string) string { ext := "" if runtime.GOOS == "windows" { ext = ".exe" } return filepath.Join(baseDir, "build", "bin", name+ext) } func fileExists(path string) bool { _, err := os.Stat(path) return err == nil } func findOnPath() (BinPaths, error) { ffmpeg, err := exec.LookPath("ffmpeg") if err != nil { return BinPaths{}, err } ffprobe, err := exec.LookPath("ffprobe") if err != nil { return BinPaths{}, err } return BinPaths{FFmpeg: ffmpeg, FFprobe: ffprobe}, nil }