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
|
|
@ -25,6 +25,7 @@ type TranscodeOpts struct {
|
|||
VideoBitrate string // e.g. "5M"
|
||||
AudioBitrate string // e.g. "192k"
|
||||
MaxHeight int // optional downscale cap (e.g. 720)
|
||||
SourceHeight int // probed source height — used to derive a sane H.264 level
|
||||
StartSeconds float64
|
||||
FFmpegPath string
|
||||
}
|
||||
|
|
@ -235,7 +236,16 @@ func buildFFmpegArgs(filePath string, opts TranscodeOpts) []string {
|
|||
// can fail with "VaapiWrapper: failed initializing" on Linux boxes
|
||||
// where VA-API isn't fully wired up. `main` keeps a clean software
|
||||
// decode fallback on every desktop + mobile platform.
|
||||
args = append(args, "-profile:v", "main", "-level:v", "4.0")
|
||||
//
|
||||
// Level is derived from the actual output height — a fixed "4.0"
|
||||
// silently rejects 4K and 1440p sources at the libx264 macroblock
|
||||
// limits and produces unplayable streams. opts.MaxHeight is the
|
||||
// downscale cap when set; falling through means "encode at source".
|
||||
levelHeight := opts.MaxHeight
|
||||
if levelHeight == 0 || (opts.SourceHeight > 0 && opts.SourceHeight < levelHeight) {
|
||||
levelHeight = opts.SourceHeight
|
||||
}
|
||||
args = append(args, "-profile:v", "main", "-level:v", H264LevelForHeight(levelHeight))
|
||||
args = append(args, "-b:v", coalesce(opts.VideoBitrate, "5M"))
|
||||
// Filter chain:
|
||||
// 1. scale (optional) — cap height + force even width.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue