feat(music): friendly cross-platform ffmpeg-missing error

This commit is contained in:
2026-06-16 08:24:58 +02:00
parent f3211f0d45
commit bc99b6e8a6
2 changed files with 28 additions and 2 deletions
+15 -2
View File
@@ -1,6 +1,7 @@
package music package music
import ( import (
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@@ -104,7 +105,7 @@ func ResolveFFmpegWithConfig(configuredPath string) (string, error) {
} }
path, err := exec.LookPath("ffmpeg") path, err := exec.LookPath("ffmpeg")
if err != nil { if err != nil {
return "", err return "", ffmpegMissingErr("ffmpeg")
} }
return path, nil return path, nil
} }
@@ -122,11 +123,23 @@ func ResolveFFprobeWithConfig(configuredPath string) (string, error) {
} }
path, err := exec.LookPath("ffprobe") path, err := exec.LookPath("ffprobe")
if err != nil { if err != nil {
return "", err return "", ffmpegMissingErr("ffprobe")
} }
return path, nil return path, nil
} }
// ffmpegMissingErr renders an actionable, cross-platform "tool not found"
// message. Only the music builder needs ffmpeg/ffprobe; every other builder
// runs with zero external dependencies.
func ffmpegMissingErr(tool string) error {
return fmt.Errorf(`%[1]s not found on PATH.
Windows: winget install Gyan.FFmpeg
macOS: brew install ffmpeg
Linux: apt install ffmpeg (or your distro's package manager)
Only the music builder needs %[1]s; set SOW_%[2]s to a full path to override.`,
tool, strings.ToUpper(tool))
}
func IsMusicAssetPath(rel string) bool { func IsMusicAssetPath(rel string) bool {
rel = filepath.ToSlash(strings.TrimSpace(rel)) rel = filepath.ToSlash(strings.TrimSpace(rel))
return rel == "envi/music" || strings.HasPrefix(rel, "envi/music/") return rel == "envi/music" || strings.HasPrefix(rel, "envi/music/")
+13
View File
@@ -402,3 +402,16 @@ func TestResolveFFprobeEnv(t *testing.T) {
t.Fatalf("expected '/custom/ffprobe', got %q", path) t.Fatalf("expected '/custom/ffprobe', got %q", path)
} }
} }
func TestFFmpegMissingErrHasInstallHints(t *testing.T) {
msg := ffmpegMissingErr("ffmpeg").Error()
for _, want := range []string{"ffmpeg", "winget", "brew", "apt", "SOW_FFMPEG"} {
if !strings.Contains(msg, want) {
t.Errorf("ffmpeg error missing %q; got:\n%s", want, msg)
}
}
probe := ffmpegMissingErr("ffprobe").Error()
if !strings.Contains(probe, "SOW_FFPROBE") {
t.Errorf("ffprobe error should mention SOW_FFPROBE; got:\n%s", probe)
}
}