feat(transcode): tonemap HDR sources to SDR (zscale-gated)

HDR (HDR10/HLG/Dolby Vision) transcoded to SDR came out washed-out and
desaturated because the filter chain never tonemapped. buildHLSFFmpegArgsAt now
inserts a zscale linearise -> hable tonemap -> BT.709 chain after the scale and
before format=, but only when the source is HDR and the ffmpeg build has zscale
(FFmpegSupportsZscale, cached). Builds without zimg keep the old behaviour
(plays, just desaturated) instead of erroring.

It's a CPU filter, valid for every encoder here: the decode hwaccel deliberately
leaves frames in system memory (no -hwaccel_output_format), so zscale runs ahead
of format=/hwupload exactly like the existing scale filter. Verified on a real
4K HDR10 file — vivid colour and deep blacks vs the washed-out baseline.
This commit is contained in:
Deivid Soto 2026-05-31 23:01:09 +02:00
parent 445da233c0
commit e4373454ba
6 changed files with 211 additions and 5 deletions

View file

@ -14,6 +14,10 @@ type TranscodeRuntime struct {
// browser-friendly. Useful when the user explicitly turns transcoding
// off in config.
Disabled bool
// TonemapHDR enables HDR→SDR tonemapping of HDR sources during transcode.
// Set only when the ffmpeg build has zscale (FFmpegSupportsZscale); without
// it the tonemap filter would error and break playback, so it stays off.
TonemapHDR bool
}
// qualityCap maps a session's Quality label to a (MaxHeight, VideoBitrate)