mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Warn if ffmpeg lacks codecs (#4852)
Prefer ffmpeg with codec support if path not explicitly set.
This commit is contained in:
@@ -269,10 +269,15 @@ func (s *Manager) RefreshFFMpeg(ctx context.Context) {
|
|||||||
|
|
||||||
// ensure the paths are valid
|
// ensure the paths are valid
|
||||||
if ffmpegPath != "" {
|
if ffmpegPath != "" {
|
||||||
|
// path was set explicitly
|
||||||
if err := ffmpeg.ValidateFFMpeg(ffmpegPath); err != nil {
|
if err := ffmpeg.ValidateFFMpeg(ffmpegPath); err != nil {
|
||||||
logger.Errorf("invalid ffmpeg path: %v", err)
|
logger.Errorf("invalid ffmpeg path: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := ffmpeg.ValidateFFMpegCodecSupport(ffmpegPath); err != nil {
|
||||||
|
logger.Warn(err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ffmpegPath = ffmpeg.ResolveFFMpeg(configDirectory, stashHomeDir)
|
ffmpegPath = ffmpeg.ResolveFFMpeg(configDirectory, stashHomeDir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,34 +16,55 @@ import (
|
|||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ValidateFFMpeg(ffmpegPath string) error {
|
func ffmpegHelp(ffmpegPath string) (string, error) {
|
||||||
cmd := stashExec.Command(ffmpegPath, "-h")
|
cmd := stashExec.Command(ffmpegPath, "-h")
|
||||||
bytes, err := cmd.CombinedOutput()
|
bytes, err := cmd.CombinedOutput()
|
||||||
output := string(bytes)
|
output := string(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var exitErr *exec.ExitError
|
var exitErr *exec.ExitError
|
||||||
if errors.As(err, &exitErr) {
|
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") {
|
if !strings.Contains(output, "--enable-libopus") {
|
||||||
return fmt.Errorf("ffmpeg is missing libopus support")
|
missingSupport = append(missingSupport, "libopus")
|
||||||
}
|
}
|
||||||
if !strings.Contains(output, "--enable-libvpx") {
|
if !strings.Contains(output, "--enable-libvpx") {
|
||||||
return fmt.Errorf("ffmpeg is missing libvpx support")
|
missingSupport = append(missingSupport, "libvpx")
|
||||||
}
|
}
|
||||||
if !strings.Contains(output, "--enable-libx264") {
|
if !strings.Contains(output, "--enable-libx264") {
|
||||||
return fmt.Errorf("ffmpeg is missing libx264 support")
|
missingSupport = append(missingSupport, "libx264")
|
||||||
}
|
}
|
||||||
if !strings.Contains(output, "--enable-libx265") {
|
if !strings.Contains(output, "--enable-libx265") {
|
||||||
return fmt.Errorf("ffmpeg is missing libx265 support")
|
missingSupport = append(missingSupport, "libx265")
|
||||||
}
|
}
|
||||||
if !strings.Contains(output, "--enable-libwebp") {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +74,7 @@ func LookPathFFMpeg() string {
|
|||||||
if ret != "" {
|
if ret != "" {
|
||||||
// ensure ffmpeg has the correct flags
|
// ensure ffmpeg has the correct flags
|
||||||
if err := ValidateFFMpeg(ret); err != nil {
|
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 = ""
|
ret = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +88,7 @@ func FindFFMpeg(path string) string {
|
|||||||
if ret != "" {
|
if ret != "" {
|
||||||
// ensure ffmpeg has the correct flags
|
// ensure ffmpeg has the correct flags
|
||||||
if err := ValidateFFMpeg(ret); err != nil {
|
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 = ""
|
ret = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,22 +98,50 @@ func FindFFMpeg(path string) string {
|
|||||||
|
|
||||||
// ResolveFFMpeg attempts to resolve the path to the ffmpeg executable.
|
// 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 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.
|
// Returns an empty string if a valid ffmpeg cannot be found.
|
||||||
func ResolveFFMpeg(path string, fallbackPath string) string {
|
func ResolveFFMpeg(path string, fallbackPath string) string {
|
||||||
|
var ret string
|
||||||
// look in the provided path first
|
// look in the provided path first
|
||||||
ret := FindFFMpeg(path)
|
pathFound := FindFFMpeg(path)
|
||||||
if ret != "" {
|
if pathFound != "" {
|
||||||
return ret
|
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
|
// then resolve from the environment
|
||||||
ret = LookPathFFMpeg()
|
envFound := LookPathFFMpeg()
|
||||||
if ret != "" {
|
if envFound != "" {
|
||||||
return ret
|
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
|
// 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
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user