Skip to content

Commit

Permalink
Warn if ffmpeg lacks codecs (#4852)
Browse files Browse the repository at this point in the history
Prefer ffmpeg with codec support if path not explicitly set.
  • Loading branch information
WithoutPants authored May 20, 2024
1 parent 1ffca39 commit 769540b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 17 deletions.
5 changes: 5 additions & 0 deletions internal/manager/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,15 @@ func (s *Manager) RefreshFFMpeg(ctx context.Context) {

// ensure the paths are valid
if ffmpegPath != "" {
// path was set explicitly
if err := ffmpeg.ValidateFFMpeg(ffmpegPath); err != nil {
logger.Errorf("invalid ffmpeg path: %v", err)
return
}

if err := ffmpeg.ValidateFFMpegCodecSupport(ffmpegPath); err != nil {
logger.Warn(err)
}
} else {
ffmpegPath = ffmpeg.ResolveFFMpeg(configDirectory, stashHomeDir)
}
Expand Down
83 changes: 66 additions & 17 deletions pkg/ffmpeg/ffmpeg.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,55 @@ import (
"github.com/stashapp/stash/pkg/logger"
)

func ValidateFFMpeg(ffmpegPath string) error {
func ffmpegHelp(ffmpegPath string) (string, error) {
cmd := stashExec.Command(ffmpegPath, "-h")
bytes, err := cmd.CombinedOutput()
output := string(bytes)
if err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
return fmt.Errorf("error running ffmpeg: %v", output)
return "", fmt.Errorf("error running ffmpeg: %v", output)
}

return fmt.Errorf("error running ffmpeg: %v", err)
return "", fmt.Errorf("error running ffmpeg: %v", err)
}

return output, nil
}

func ValidateFFMpeg(ffmpegPath string) error {
_, err := ffmpegHelp(ffmpegPath)
return err
}

func ValidateFFMpegCodecSupport(ffmpegPath string) error {
output, err := ffmpegHelp(ffmpegPath)
if err != nil {
return err
}

var missingSupport []string

if !strings.Contains(output, "--enable-libopus") {
return fmt.Errorf("ffmpeg is missing libopus support")
missingSupport = append(missingSupport, "libopus")
}
if !strings.Contains(output, "--enable-libvpx") {
return fmt.Errorf("ffmpeg is missing libvpx support")
missingSupport = append(missingSupport, "libvpx")
}
if !strings.Contains(output, "--enable-libx264") {
return fmt.Errorf("ffmpeg is missing libx264 support")
missingSupport = append(missingSupport, "libx264")
}
if !strings.Contains(output, "--enable-libx265") {
return fmt.Errorf("ffmpeg is missing libx265 support")
missingSupport = append(missingSupport, "libx265")
}
if !strings.Contains(output, "--enable-libwebp") {
return fmt.Errorf("ffmpeg is missing libwebp support")
missingSupport = append(missingSupport, "libwebp")
}

if len(missingSupport) > 0 {
return fmt.Errorf("ffmpeg missing codec support: %v", missingSupport)
}

return nil
}

Expand All @@ -53,7 +74,7 @@ func LookPathFFMpeg() string {
if ret != "" {
// ensure ffmpeg has the correct flags
if err := ValidateFFMpeg(ret); err != nil {
logger.Warnf("ffmpeg found in PATH (%s), but it is missing required flags: %v", ret, err)
logger.Warnf("ffmpeg found (%s), could not be executed: %v", ret, err)
ret = ""
}
}
Expand All @@ -67,7 +88,7 @@ func FindFFMpeg(path string) string {
if ret != "" {
// ensure ffmpeg has the correct flags
if err := ValidateFFMpeg(ret); err != nil {
logger.Warnf("ffmpeg found (%s), but it is missing required flags: %v", ret, err)
logger.Warnf("ffmpeg found (%s), could not be executed: %v", ret, err)
ret = ""
}
}
Expand All @@ -77,22 +98,50 @@ func FindFFMpeg(path string) string {

// ResolveFFMpeg attempts to resolve the path to the ffmpeg executable.
// It first looks in the provided path, then resolves from the environment, and finally looks in the fallback path.
// It will prefer an ffmpeg binary that has the required codec support.
// Returns an empty string if a valid ffmpeg cannot be found.
func ResolveFFMpeg(path string, fallbackPath string) string {
var ret string
// look in the provided path first
ret := FindFFMpeg(path)
if ret != "" {
return ret
pathFound := FindFFMpeg(path)
if pathFound != "" {
err := ValidateFFMpegCodecSupport(pathFound)
if err == nil {
return pathFound
}

logger.Warnf("ffmpeg found (%s), but it is missing required flags: %v", pathFound, err)
ret = pathFound
}

// then resolve from the environment
ret = LookPathFFMpeg()
if ret != "" {
return ret
envFound := LookPathFFMpeg()
if envFound != "" {
err := ValidateFFMpegCodecSupport(envFound)
if err == nil {
return envFound
}

logger.Warnf("ffmpeg found (%s), but it is missing required flags: %v", envFound, err)
if ret == "" {
ret = envFound
}
}

// finally, look in the fallback path
ret = FindFFMpeg(fallbackPath)
fallbackFound := FindFFMpeg(fallbackPath)
if fallbackFound != "" {
err := ValidateFFMpegCodecSupport(fallbackFound)
if err == nil {
return fallbackFound
}

logger.Warnf("ffmpeg found (%s), but it is missing required flags: %v", fallbackFound, err)
if ret == "" {
ret = fallbackFound
}
}

return ret
}

Expand Down

0 comments on commit 769540b

Please sign in to comment.