Skip to content

fix(engine): keep the rightmost 8 columns of SDR MP4 at widths like 1080 - #5559

Merged
jrusso1020 merged 1 commit into
mainfrom
fix/sdr-gbrp-right-edge
Oct 13, 2026
Merged

jrusso1020 merged 1 commit into
mainfrom
fix/sdr-gbrp-right-edge

Conversation

@jrusso1020

@jrusso1020 jrusso1020 commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds accurate_rnd to the yuv-to-gbrp scale in the SDR colour chains: the MP4/streaming encode filter (sdrCaptureColor.ts) and the SDR jpg frame-extraction filter (videoFrameExtractor.ts).

Why

Since 0.8.81 (#4564), SDR colour goes through format=gbrp. Without accurate_rnd, swscale's yuv-to-gbrp conversion leaves the last 8 columns black when the width is 16n + 8 (1000, 1080, 1112...). So every 1080x1920 portrait MP4 has had an 8 px black strip on the right. The same step in jpg frame extraction blanks the right edge of footage at those widths.

It depends on the ffmpeg version. A 1080-wide white frame through the current filter loses its last 8 columns on ffmpeg 7.1 and 8.0.1, and is correct on 5.1 (the Dockerfile.test image) and 6.1. With accurate_rnd all four are correct. That is why the regression goldens, rendered on 5.1, never showed it, and why #4564's pixel tests (64 px wide) missed it.

Related work

Fixes #5551. Regressed in #4564, whose commit notes accurate_rnd as "redundant" once nearest-neighbour chroma was added.

How

  • One flag on the first scale of each chain: flags=neighbor becomes flags=neighbor+accurate_rnd.
  • It is also the more accurate rounding. On a 1088-wide testsrc2 frame (a width the bug doesn't hit), the worst luma error against a float BT.601-full to BT.709-limited reference drops from 1.85 to 0.90 codes, and the mean error drops from 0.325 to 0.304.

No visible change

This is an engine-only change, with no Studio or player UI.

Test plan

  • Unit tests added. chunkEncoder.test.ts checks that a 1080-wide #C83C28 capture keeps its last 8 columns in the MP4 (within 2 codes). videoFrameExtractor.test.ts checks that a 1080-wide clip's last 8 columns survive jpg extraction (within 5). Fails without the fix: with accurate_rnd removed, both new tests fail; with it, both pass.
  • The existing colour suites from fix(engine): SDR renders keep footage and page colours as in the source #4564 pass: chunkEncoder, streamingEncoder, videoFrameExtractor and runFfmpeg, 404 tests.
  • End to end, with a 1080x1920 solid #C83C28 composition, the luma of the last 10 columns at mid-height:
  • Per-width check with ffmpeg 8.0.1. Without the fix, 1000, 1080 and 1112 lose the last 8 columns, while 720, 1088, 1100 and 1920 are fine. With the fix, all are correct.
  • Producer regression goldens: accurate_rnd changes a small share of pixel values by about a code, so CI's PSNR comparisons will show whether any golden needs regenerating.

🤖 Generated with Claude Code

#4564 routes SDR colour through `format=gbrp`. Without accurate_rnd,
swscale's yuv-to-gbrp conversion leaves the last 8 columns black when the
width is 16n + 8 (1000, 1080, 1112...), so every 1080x1920 portrait MP4
since 0.8.81 has had an 8 px black strip on the right. The same step in
SDR jpg frame extraction blanked the right edge of footage at those widths.

Set accurate_rnd on the yuv-to-gbrp scale in both chains. It is also the
more accurate rounding: on a testsrc2 frame, worst luma error against a
float reference drops from 1.85 to 0.90 codes.

Fixes #5551

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

@jerrai-bot-heygen jerrai-bot-heygen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch adds accurate_rnd only to the SDR BT.601→gbrp conversion in both the encode and JPEG extraction paths; HDR routing and the downstream BT.709 scale remain unchanged. The 1080-wide edge regressions in chunkEncoder.test.ts and videoFrameExtractor.test.ts executed in the hosted engine runtime suite (99 and 200 tests in those files), alongside green lint, format, build, producer integration and Windows checks. The full 1080×1920 end-to-end render and before/after mutation are author-reported, not independently reproduced by this reviewer; remaining regression/accuracy shards were still running. Approval is not merge or publication of 0.8.155. — Jerrai

@jrusso1020
jrusso1020 enabled auto-merge October 13, 2026 21:00
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 2061 (base branch 2061), smooth 1589 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • crop-none-px-r0-nested-z50: tracking 0.05, pressJump 0, drop 40.07, reload 40.12, render 40.03, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0.1, reload 0.12, render 0.03, renderKey -, undo true, teleport true / tracking 0.05, pressJump 0, drop 0.1, reload 0.12, render 0.03, renderKey -, undo true, teleport true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

render: MP4 output drops the rightmost 8 px of a 1080-wide composition (width not a multiple of 16) since 0.8.81; png-sequence and webm are correct

2 participants