mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
## What - Treat GIF as an alpha-capable output format and capture its frames as RGBA PNGs. - Encode transparent GIFs with explicit FFmpeg palette semantics: `reserve_transparent=1` and `alpha_threshold=128`. - Keep page-side shader compositing enabled for GIF while the resulting composite is captured through the RGBA disk-frame path. - Extend the real render harness to verify decoded GIF alpha and compare a GIF shader-transition frame against the existing MP4 golden. - Preserve the existing opaque encoder contract: `needsAlpha=false` continues to use JPEG frames without alpha-only palette filters. ## Why Direct `--format gif` renders silently flattened transparent compositions when frames are captured as JPEG, because the palette encoder receives no alpha plane to preserve. GIF also needs page-side shader compositing. A blanket `needsAlpha` exclusion disabled that path after enabling RGBA capture, while the layered compositor intentionally excludes GIF. That left shader GIFs on the DOM fallback and produced hard cuts instead of the authored WebGL blend. ## How - Centralize output alpha detection in `outputNeedsAlpha`, shared by in-process and distributed planning. - Select PNG or JPEG GIF frame input from the resolved alpha requirement. - Make palette transparency flags explicit and conditional so the legacy opaque path retains its existing arguments. - Add an explicit output-format capability for page-side shader compositing: MP4 keeps its opaque streaming path, GIF uses RGBA PNG disk frames, and WebM/MOV/PNG sequence retain their existing paths. - Add `data-no-timeline` to the static transparency fixture so the artifact regression does not wait for a timeline it intentionally does not register. ## Test plan - [x] RED on base: direct GIF decoded with an opaque corner instead of alpha 0. - [x] RED on the previous PR head: the real GIF shader-transition frame scored 11.05 dB against the existing golden because neither shader compositor was active. - [x] `bun test packages/producer/src/services/render/renderFormat.test.ts packages/producer/src/services/render/stages/encodeStage.test.ts packages/producer/src/services/render/capturePlan.test.ts` — 23 passed. - [x] `bun run --filter @hyperframes/producer typecheck` - [x] `bun run --filter @hyperframes/producer build` - [x] `bun run --filter @hyperframes/producer test:transparency` — WebM, GIF, and PNG sequence alpha assertions passed; GIF shader control/transition frames scored 28.11/26.57 dB against the golden. - [x] `bun run --cwd packages/producer tsx src/regression-harness.ts page-side-shader-compositor-render-compat --sequential` — all 100 visual checkpoints passed, stream parity passed, and audio correlation was 1.000. - [x] Changed-file oxlint, oxfmt check, pre-commit checks, and `git diff --check`.