feat(stream): benchmark software encode ceiling at startup

Replace the guessed transcode ceiling (CPU->1080, GPU->2160) with a measured
one. HW encoders still return 2160 instantly. A software-only host runs a
bounded encode benchmark — 3s testsrc2 through the real libx264 superfast
settings at 1080/720/480, top-down — and reports the rung it sustains at
>=1.5x realtime (margin for real decode + busier content).

Fixes risk 2: a weak NAS/old CPU that is ffmpeg-capable but can't keep up
with a 1080p software encode no longer advertises a 1080 ceiling, so
decideStreamPlan routes oversized sources to an external player instead of a
stuttering transcode. Floors at 480; each probe is timeout-bounded so a
wedged ffmpeg can't stall daemon startup.
This commit is contained in:
Deivid Soto 2026-06-03 09:30:03 +02:00
parent 005a4380dd
commit ef3b190e0b
3 changed files with 167 additions and 4 deletions

View file

@ -156,10 +156,15 @@ func runDaemonStart() error {
hwDiag := engine.DetectHWAccelDiagnostic(probeCtx, ffmpegResolved)
log.Println(hwDiag.LogLine())
hwAccelPick := hwDiag.Pick
maxTranscodeHeight := 1080
if hwAccelPick != engine.HWAccelNone {
maxTranscodeHeight = 2160
}
// Measure the real transcode ceiling instead of guessing from the backend.
// HW encoders return 2160 instantly; a software-only host runs a bounded
// encode benchmark so a weak NAS/CPU reports the rung it can actually
// sustain (720/480) and the web side routes oversized sources to an
// external player instead of a stuttering transcode. Own timeout — the 10 s
// probeCtx above is sized for the quick diagnostic, not three encode rungs.
benchCtx, benchCancel := context.WithTimeout(context.Background(), 45*time.Second)
maxTranscodeHeight := engine.BenchmarkMaxTranscodeHeight(benchCtx, ffmpegResolved, hwAccelPick)
benchCancel()
// Create daemon config
daemonCfg := agent.DaemonConfig{