fix(engine): add anti-banding x264/x265 params for dark gradients#222
Merged
jrusso1020 merged 1 commit intomainfrom Apr 7, 2026
Merged
fix(engine): add anti-banding x264/x265 params for dark gradients#222jrusso1020 merged 1 commit intomainfrom
jrusso1020 merged 1 commit intomainfrom
Conversation
Add aq-mode=3 (auto-variance adaptive quantization) to CPU H.264/H.265 encoding. This redistributes bits from bright/textured areas to dark flat areas where color banding is most visible in 8-bit yuv420p output. - standard/high presets: aq-mode=3 + aq-strength=0.8 + deblock=1,1 - draft (ultrafast): aq-mode=3 only (deblock too slow for ultrafast) - GPU and VP9 encoders unaffected (have their own AQ implementations) Adds 6 regression tests verifying the params are emitted correctly. Fixes color banding on dark gradients (eval issue #3, prompts 3,5,10,14). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
miguel-heygen
approved these changes
Apr 7, 2026
jrusso1020
added a commit
that referenced
this pull request
Apr 7, 2026
## Description Adds proper BT.709 color space metadata and full→limited range conversion to H.264/H.265 encoding. Chrome captures frames in full-range sRGB (BT.709 primaries), but without explicit color tagging, players guess the wrong color space and range — causing color shifts across iOS/Android/desktop and crushed dark values that compound the gradient banding issue fixed in #222. **What changed:** | Setting | Before | After | |---------|--------|-------| | `color_space` | `bt470bg` (guessed) | `bt709` (explicit) | | `color_primaries` | `unknown` | `bt709` | | `color_transfer` | `unknown` | `bt709` | | `color_range` | `pc` (full, wrong for H.264) | `tv` (limited, correct) | | `time_base` | `1/15360` (varies by platform) | `1/90000` (fixed) | **Approach:** - BT.709 VUI params embedded via x264-params/x265-params (`colorprim=bt709:transfer=bt709:colormatrix=bt709`) — ensures the bitstream itself carries color info - FFmpeg-level metadata flags (`-colorspace:v bt709`, etc.) — belt-and-suspenders - `scale=in_range=pc:out_range=tv` filter converts Chrome's full-range output to TV/limited range - VAAPI path chains the range filter with existing `format=nv12,hwupload` - `-video_track_timescale 90000` for consistent cross-platform A/V timing (same as Remotion) - VP9 and ProRes encoding unaffected ## Testing - Verified via ffprobe: all 5 color metadata fields now correct - Directly tested FFmpeg args produce expected output - 40 engine tests pass (8 new: color metadata h264/h265, range filter CPU, VAAPI filter chain, GPU skip, VP9 skip, timescale) - Builds cleanly, lint + format pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes color banding on dark gradients — eval issue #3, affecting prompts 3, 5, 10, 14.
Root cause: libx264's default
aq-mode=1doesn't allocate enough bits to dark flat gradient areas. With 8-bityuv420p, subtle gradient steps get quantized to the same value, producing visible horizontal bands.Fix: Add
aq-mode=3(auto-variance adaptive quantization) via-x264-params/-x265-paramsto both chunk and streaming encoders. This redistributes bits from bright/textured areas to dark flat areas where banding is most visible.aq-mode=3onlyaq-mode=3:aq-strength=0.8:deblock=1,1aq-mode=3:aq-strength=0.8:deblock=1,1aq-mode=3— auto-variance AQ, designed for flat dark areasaq-strength=0.8— slightly below default to avoid over-softening texturesdeblock=1,1— stronger deblocking smooths quantization band boundariesTesting
#1a1a2e → #0a0a0a) — smooth gradients, no visible bandingNote: pre-commit typecheck failure is pre-existing on main (
linkedomtypes missing incorepackage).