Wails v2 + Vue3 + Go project with: - Encode/Remux/Subtitle burn with hardware acceleration - Real-time progress with ffmpeg stderr parsing (\r delimiter handling) - Task queue with cancel support - Per-task log viewer with color-coded output - Custom frameless window with resize support - Dark/light theme toggle - Hardware encoder detection (NVENC/QSV/AMF)
64 lines
1.2 KiB
Go
64 lines
1.2 KiB
Go
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
|
|
}
|