Repository navigation
fix(engine): exports carry full colour tags with every encoder, SDR and HDR - #5742
Conversation
…ry encoder The SDR conversion filter set the BT.709 matrix on its frames but not the transfer or primaries. Encoders that take colour from the frames rather than from -color_* options (VideoToolbox on macOS) wrote color_space=bt709 with color_transfer and color_primaries unknown. The capture and raw-input SDR filters now end in the tagged BT.709 filter ProRes already uses.
VideoToolbox HDR encodes had the same gap as SDR: given only -color_* options it wrote bt2020nc with transfer and primaries unknown, so players read the export as SDR. Every HDR branch of the streamed and disk encoders now tags the frames through one hdrFrameTagsFilter built from the encoder colour params.
Edit accuracy: accurate 271 (base branch 271), smooth 168 of thoseThe gate passes. Quarantined, measured but not gated (0) |
33a20ef to
bb9759f
Compare
terencecho
left a comment
There was a problem hiding this comment.
Reviewed bb9759fb95300d22aa0b4d89ea06a660d6433e06 against effective base 4e6ee6d2300290b638042ec88ef5afb7a0c27408; no concrete introduced blocker found.
packages/engine/src/utils/hdr.ts:109–112derives frame tags from the existing encoder color parameters, keeping PQ/HLG transfer names aligned rather than restating them.packages/engine/src/services/streamingEncoder.ts:428–447preserves the captured-SDR/raw-SDR/raw-HDR distinction and applies padding/upload after selecting the appropriate frame filter.
Audited: all six changed files end-to-end at both BASE and HEAD, relevant real encoder/compositor/capture callers, preserved codec branches and all 15 behavioral-group pairs; two independent source-only passes completed. The final test-only successor's actual patches were reconciled too.
Verification limits: the new probes isolate -vf using lavfi and software encoders; a VideoToolbox-selected argument-builder row is not an actual VideoToolbox execution. Tests/builds/native codecs/CI were not run or queried. Pixel/range fidelity, hardware metadata propagation and final playback remain unverified; the reported native results are author-supplied evidence, not my reproduction.
— Review by tai (pr-review)
Verdict: APPROVE
Reasoning: The source changes consistently add frame tags while preserving the distinct input conversion paths and existing output metadata. I found no reachable introduced defect in the audited scope; this approval does not claim native validation.
What changes for users
MP4/MOV exports encoded with VideoToolbox (macOS
--gpu, or a macOS FFmpeg without libx264) now carry their full colour description:color_space=bt709butcolor_transferandcolor_primariesunknown, so players guessed and could show a colour cast. Nowbt709,bt709,bt709.bt2020ncbut transfer and primariesunknown, so players treated the export as SDR. Nowbt2020nc,smpte2084(PQ) orarib-std-b67(HLG),bt2020.libx264 and libx265 exports were already fully tagged and are unchanged.
Root cause
The encoders set colour two ways: on the frames through the conversion filters, and through
-color_primaries/-color_trcoutput options (plus x264/x265 params). The SDR conversion only set the frames' matrix (fromscale=out_color_matrix=bt709), and the HDR paths set nothing on the frames. VideoToolbox ignores the output options and writes only what the frames carry. With FFmpeg 8.1.1 on macOS:h264_videotoolboxgiven all four-color_*options writesbt709,unknown,unknown;hevc_videotoolboxwith bt2020/PQ options writesbt2020nc,unknown,unknown.The fix tags the frames on every path, streamed and disk (so HLS and distributed chunks too):
SDR_RGB_TO_TAGGED_BT709_FILTER, the BT.709 conversion plussetparamstags that ProRes already uses for the same reason.hdrFrameTagsFilter(transfer). It's built fromgetHdrEncoderColorParams, so the frame tags and the x265 params share one source.-color_*options stay; they still set the container tags.Verification
--sdrrenders are allbt709,bt709,bt709, rangetv. An HDR render keepsbt2020nc/smpte2084/bt2020. So the report only reproduces with VideoToolbox.h264_videotoolbox:bt709,bt709,bt709(wasbt709,unknown,unknown);hevc_videotoolboxmain10:bt2020nc,smpte2084,bt2020andbt2020nc,arib-std-b67,bt2020(wasbt2020nc,unknown,unknown).-vfthe arg builder produces, with a plain libx264 or 10-bit libx265 given no colour options, which like VideoToolbox writes only the frames' colour, then ffprobes the stream.tsc --noEmitin packages/engine andoxfmt --checkare clean.