unarr/internal/library/mediainfo/ffmpeg.go
Deivid Soto ca7de23a56
Some checks failed
Release / release (push) Failing after 0s
Release / docker (push) Has been skipped
Release / virustotal (push) Failing after 0s
feat(stream)!: retire WebRTC, HLS-only, bump 0.9.4
Drops the custom WebRTC DataChannel pipeline + pion deps + WSS signaling
client + wire framing. Every in-browser playback now uses HLS over HTTP
from the daemon (Tailscale/LAN/UPnP). Browser P2P never re-enabled.

Wire renames (incompatible with web < 2026-05-26): agent.WebRTCSession
=> agent.StreamSession, SyncResponse.WebRTCSessions (JSON: webrtcSessions)
=> StreamSessions (JSON: streamSessions). MIN_AGENT_VERSION is bumped
to 0.9.4 on the web side so older agents see an upgrade card.

Also fixes the libx264 'VBV bitrate > level limit' abort by clamping
the encoder bitrate to the effective output height instead of the
requested label (carried over from the prior 0.9.3 unreleased work).

The seed_file vertical (mode=seed_file handler + engine.SeedFile) was
retired with the in-browser P2P player. [downloads.webrtc] config block
deleted; existing TOML files with the section still parse fine.
2026-05-26 18:04:35 +02:00

79 lines
2.4 KiB
Go

package mediainfo
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
)
// ResolveFFmpeg finds the ffmpeg binary. Search order mirrors ResolveFFprobe
// so the same operator setup works for both:
// 1. Explicit path (--ffmpeg flag / library.ffmpeg_path config)
// 2. FFMPEG_PATH env var
// 3. "ffmpeg" on PATH
// 4. Adjacent to the current executable (release tarball bundles ffmpeg
// next to the unarr binary — this is the preferred install path)
// 5. Previously downloaded in the unarr cache dir
// 6. Auto-download static binary as last resort (~50MB, slow start)
//
// ffmpeg is required for the HLS streaming pipeline; ffprobe alone can't
// transcode HEVC/MKV to browser-friendly H.264/MP4 fragments.
func ResolveFFmpeg(explicit string) (string, error) {
if explicit != "" {
if _, err := os.Stat(explicit); err == nil {
return explicit, nil
}
return "", fmt.Errorf("ffmpeg not found at explicit path: %s", explicit)
}
if envPath := os.Getenv("FFMPEG_PATH"); envPath != "" {
if _, err := os.Stat(envPath); err == nil {
return envPath, nil
}
}
if p, err := exec.LookPath("ffmpeg"); err == nil {
return p, nil
}
if exePath, err := os.Executable(); err == nil {
name := "ffmpeg"
if runtime.GOOS == "windows" {
name = "ffmpeg.exe"
}
adjacent := filepath.Join(filepath.Dir(exePath), name)
if _, err := os.Stat(adjacent); err == nil {
return adjacent, nil
}
}
if cached, err := FFmpegCachePath(); err == nil {
if _, err := os.Stat(cached); err == nil {
return cached, nil
}
}
if p, err := DownloadFFmpeg(); err == nil {
return p, nil
}
if isDocker() {
return "", fmt.Errorf(
"ffmpeg not found and auto-download failed (read-only filesystem?).\n" +
"Options:\n" +
" • Use the official image: torrentclaw/unarr (includes ffmpeg)\n" +
" • Set FFMPEG_PATH env var to point to a pre-installed ffmpeg binary\n" +
" • Add to config.toml: [library]\\nffmpeg_path = \"/path/to/ffmpeg\"",
)
}
return "", fmt.Errorf(
"ffmpeg not found and auto-download failed.\n" +
"Options:\n" +
" • Install ffmpeg: sudo apt install ffmpeg (or brew install ffmpeg)\n" +
" • Use the unarr release tarball — ffmpeg is bundled next to the binary\n" +
" • Set FFMPEG_PATH env var to point to the ffmpeg binary\n" +
" • Add to config.toml: [library]\\nffmpeg_path = \"/path/to/ffmpeg\"",
)
}