feat: FFmpeg GUI desktop application

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)
This commit is contained in:
sansen
2026-07-29 02:17:57 +08:00
parent 51b768a2ba
commit 79f5fb8ac3
36 changed files with 5216 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
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
}