Fix pwd no longer being included in ffmpeg binary search (#4749)

* fix(go): fix pwd no longer being included in ffmpeg binary search. Closes #4747

* fix: updates per feedback
This commit is contained in:
Gabe Kangas
2026-01-17 14:23:39 -08:00
committed by GitHub
parent 93868574a5
commit 0ff73d5e1e
2 changed files with 102 additions and 4 deletions
+8 -3
View File
@@ -260,11 +260,16 @@ func ValidatedFfmpegPath(ffmpegPath string) string {
log.Warnln(ffmpegPath, "is an invalid path to ffmpeg will try to use a copy in your path, if possible") log.Warnln(ffmpegPath, "is an invalid path to ffmpeg will try to use a copy in your path, if possible")
} }
// Look for ffmpeg in the system path or in the current working directory. // First, check for ffmpeg in the current working directory.
ffmpegPath, err := exec.LookPath("ffmpeg") if err := VerifyFFMpegPath("./ffmpeg"); err == nil {
if ffmpegPath == "" || (err != nil && !errors.Is(err, exec.ErrDot)) || VerifyFFMpegPath(ffmpegPath) != nil { ffmpegPath = "./ffmpeg"
} else {
// Fall back to looking for ffmpeg in the system path.
ffmpegPath, err = exec.LookPath("ffmpeg")
if err != nil || VerifyFFMpegPath(ffmpegPath) != nil {
log.Fatalln("Unable to locate ffmpeg. Either install it globally on your system or put the ffmpeg binary in the same directory as Owncast. The binary must be named ffmpeg.") log.Fatalln("Unable to locate ffmpeg. Either install it globally on your system or put the ffmpeg binary in the same directory as Owncast. The binary must be named ffmpeg.")
} }
}
// Resolve to an absolute path. // Resolve to an absolute path.
absPath, err := filepath.Abs(ffmpegPath) absPath, err := filepath.Abs(ffmpegPath)
+93
View File
@@ -1,6 +1,9 @@
package utils package utils
import ( import (
"os"
"path/filepath"
"runtime"
"testing" "testing"
) )
@@ -26,3 +29,93 @@ func TestPercentageUtilsTest(t *testing.T) {
t.Error("Incorrect percentage calculation.") t.Error("Incorrect percentage calculation.")
} }
} }
func TestValidatedFfmpegPathPrefersLocalBinary(t *testing.T) {
// Skip on Windows as executable permissions work differently.
if runtime.GOOS == "windows" {
t.Skip("Skipping test on Windows")
}
// Create a temporary directory to act as our working directory.
tempDir, err := os.MkdirTemp("", "ffmpeg-test")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
// Create a fake ffmpeg executable in the temp directory.
fakeFfmpegPath := filepath.Join(tempDir, "ffmpeg")
if err := os.WriteFile(fakeFfmpegPath, []byte("#!/bin/sh\necho fake"), 0o755); err != nil {
t.Fatalf("Failed to create fake ffmpeg: %v", err)
}
// Save the current working directory and change to the temp directory.
originalWd, err := os.Getwd()
if err != nil {
t.Fatalf("Failed to get current working directory: %v", err)
}
if err := os.Chdir(tempDir); err != nil {
t.Fatalf("Failed to change to temp directory: %v", err)
}
defer os.Chdir(originalWd)
// Call ValidatedFfmpegPath with an empty string to trigger auto-detection.
result := ValidatedFfmpegPath("")
// The result should be the absolute path to our local fake ffmpeg,
// not the system ffmpeg in /usr/bin or similar.
expectedPath, err := filepath.Abs("./ffmpeg")
if err != nil {
t.Fatalf("Failed to get absolute path for fake ffmpeg: %v", err)
}
if result != expectedPath {
t.Errorf("Expected local ffmpeg path %q, got %q", expectedPath, result)
}
}
func TestVerifyFFMpegPath(t *testing.T) {
// Test with non-existent path.
err := VerifyFFMpegPath("/nonexistent/path/to/ffmpeg")
if err == nil {
t.Error("Expected error for non-existent path")
}
// Test with a directory instead of a file.
tempDir, err := os.MkdirTemp("", "ffmpeg-dir-test")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)
err = VerifyFFMpegPath(tempDir)
if err == nil {
t.Error("Expected error when path is a directory")
}
// Test with a non-executable file (Unix only).
if runtime.GOOS != "windows" {
nonExecFile := filepath.Join(tempDir, "nonexec")
if err := os.WriteFile(nonExecFile, []byte("test"), 0o644); err != nil {
t.Fatalf("Failed to create non-executable file: %v", err)
}
err = VerifyFFMpegPath(nonExecFile)
if err == nil {
t.Error("Expected error for non-executable file")
}
}
// Test with a valid executable file.
if runtime.GOOS != "windows" {
execFile := filepath.Join(tempDir, "executable")
if err := os.WriteFile(execFile, []byte("#!/bin/sh\necho test"), 0o755); err != nil {
t.Fatalf("Failed to create executable file: %v", err)
}
err = VerifyFFMpegPath(execFile)
if err != nil {
t.Errorf("Expected no error for valid executable, got: %v", err)
}
}
}