feat(transcode): dynamic H.264 level + HW probe + capability reporting
Three related fixes around 4K-source transcoding that left the web player stuck on "preparing session" with no useful diagnostics: 1. Dynamic -level:v derived from output height (hls.go, transcoder.go). The previous fixed "4.0" silently rejected anything taller than 1080p inside libx264 — "frame MB size > level limit", "DPB size > level limit" — and emitted unplayable segments. Helper H264LevelForHeight() now picks 4.0 / 5.0 / 5.1 / 6.0 from the actual encode height. 2. New `unarr probe-hwaccel` diagnostic command. Lists the HW encoders compiled into ffmpeg, the device files / drivers present, and the backend the daemon would actually pick today. Surfaces the canonical gotcha: a host with an RTX 3090 + nvidia-smi but a Homebrew ffmpeg built without --enable-nvenc still falls back to libx264 software. 3. Register payload now includes hwAccel + maxTranscodeHeight so the web side can suggest a smaller alternate quality before the user even tries to play a 4K source on a software-only host. Software-only = 1080p cap, any HW backend = 2160p cap.
This commit is contained in:
parent
01941ed2e4
commit
209ea38ecf
9 changed files with 297 additions and 30 deletions
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/torrentclaw/unarr/internal/config"
|
||||
"github.com/torrentclaw/unarr/internal/engine"
|
||||
"github.com/torrentclaw/unarr/internal/library"
|
||||
"github.com/torrentclaw/unarr/internal/library/mediainfo"
|
||||
"github.com/torrentclaw/unarr/internal/usenet/download"
|
||||
)
|
||||
|
||||
|
|
@ -135,17 +136,29 @@ func runDaemonStart() error {
|
|||
|
||||
userAgent := "unarr/" + Version
|
||||
|
||||
// Probe HW accel + derive a sensible transcode resolution cap. The cap
|
||||
// is what the web side uses to decide whether the user should pre-empt
|
||||
// transcoding by downloading a smaller version (4K source on a software
|
||||
// libx264-only host is the canonical case where pre-download wins).
|
||||
hwAccelPick := engine.DetectHWAccel(context.Background(), cfg.Library.FFmpegPath)
|
||||
maxTranscodeHeight := 1080
|
||||
if hwAccelPick != engine.HWAccelNone {
|
||||
maxTranscodeHeight = 2160
|
||||
}
|
||||
|
||||
// Create daemon config
|
||||
daemonCfg := agent.DaemonConfig{
|
||||
AgentID: cfg.Agent.ID,
|
||||
AgentName: cfg.Agent.Name,
|
||||
Version: Version,
|
||||
DownloadDir: cfg.Download.Dir,
|
||||
StreamPort: cfg.Download.StreamPort,
|
||||
LanIP: engine.LanIP(),
|
||||
TailscaleIP: engine.TailscaleIP(),
|
||||
CanDelete: cfg.Library.AllowDelete,
|
||||
ScanPaths: library.ResolveScanPaths(cfg.Download.Dir, cfg.Organize.MoviesDir, cfg.Organize.TVShowsDir, cfg.Library.ScanPath),
|
||||
AgentID: cfg.Agent.ID,
|
||||
AgentName: cfg.Agent.Name,
|
||||
Version: Version,
|
||||
DownloadDir: cfg.Download.Dir,
|
||||
StreamPort: cfg.Download.StreamPort,
|
||||
LanIP: engine.LanIP(),
|
||||
TailscaleIP: engine.TailscaleIP(),
|
||||
CanDelete: cfg.Library.AllowDelete,
|
||||
ScanPaths: library.ResolveScanPaths(cfg.Download.Dir, cfg.Organize.MoviesDir, cfg.Organize.TVShowsDir, cfg.Library.ScanPath),
|
||||
HWAccel: string(hwAccelPick),
|
||||
MaxTranscodeHeight: maxTranscodeHeight,
|
||||
}
|
||||
|
||||
// Create HTTP client — single communication channel
|
||||
|
|
@ -237,6 +250,18 @@ func runDaemonStart() error {
|
|||
}
|
||||
d.UpdateStreamPort(streamSrv.Port())
|
||||
|
||||
// Warn at startup if transcode is enabled but ffmpeg/ffprobe are missing.
|
||||
// HLS sessions get rejected at runtime (see daemon.go ~line 455), but
|
||||
// surfacing it here gives the operator a chance to install ffmpeg before
|
||||
// a user hits a confusing "rejected" line in the logs.
|
||||
if cfg.Download.Transcode.Enabled {
|
||||
if _, err := mediainfo.ResolveFFmpeg(cfg.Library.FFmpegPath); err != nil {
|
||||
log.Printf("[hls] transcode enabled but ffmpeg/ffprobe not found — install ffmpeg to use HLS")
|
||||
} else if _, err := mediainfo.ResolveFFprobe(cfg.Library.FFprobePath); err != nil {
|
||||
log.Printf("[hls] transcode enabled but ffmpeg/ffprobe not found — install ffmpeg to use HLS")
|
||||
}
|
||||
}
|
||||
|
||||
// Wire sync client callbacks
|
||||
sc := d.SyncClient()
|
||||
sc.GetFreeSlots = manager.FreeSlots
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue