feat(producer): true alpha output for webm, mov, and png-sequence

Extends RenderConfig.format with "png-sequence" and patches two correctness
gaps so the existing "webm" / "mov" values actually preserve the alpha
channel end-to-end.

Engine fixes:
- screenshotService.pageScreenshotCapture: drop optimizeForSpeed for PNG
  captures. The fast path uses an alpha-unaware codec that crushes real
  alpha values; kept for opaque jpeg captures where it is harmless.
- frameCapture: replace the inline setDefaultBackgroundColorOverride
  block (which fired pre-navigation and was reset by page.goto) with a
  proper initTransparentBackground() call inside initializeSession,
  after the window.__hf readiness poll. This also injects the
  html/body/[data-composition-id]{background:transparent !important}
  stylesheet so compositions with custom body / #root backgrounds do not
  defeat the override. Wired into both screenshot-mode and beginframe-mode
  branches.

Producer:
- RenderConfig.format extended to "mp4" | "webm" | "mov" | "png-sequence"
  with full JSDoc.
- Streaming encode is bypassed for png-sequence (frames go straight to
  disk). FORMAT_EXT extended.
- New Stage-5 png-sequence branch: mkdir outputPath, copy captured PNGs as
  frame_NNNNNN.png, copy audio.aac sidecar when audio is present.
- Stage-6 mux/faststart and the debug copy are wrapped in !isPngSequence.
- README.md: new "Transparent Video Output" section.

Tests:
- New fixture tests/transparency-regression/ tagged "transparency".
- New tsx script src/transparency-test.ts asserts pixel-level alpha for
  webm + png-sequence outputs. Wired as "test:transparency".
- Default "test" / "test:update" scripts pass --exclude-tags transparency
  so the golden-MP4 harness ignores the new fixture.

Verified locally on macOS arm64: typecheck clean across engine + producer,
producer renderOrchestrator vitest 10/10, transparency-test passes for
both webm and png-sequence with end-to-end pixel assertions.
This commit is contained in:
Youssef Toufik
2026-04-27 20:33:45 +01:00
parent 2935be6bf6
commit fe017b48c7
8 changed files with 537 additions and 97 deletions
@@ -0,0 +1,41 @@
<!doctype html>
<html>
<head>
<style>
html,
body {
margin: 0;
padding: 0;
}
/*
Intentionally NO body / #root background — the alpha pipeline forces
the page background fully transparent. We DO set a background on
.card to verify that *inner* element backgrounds survive the
force-transparent override.
*/
.card {
position: absolute;
left: 50px;
top: 50px;
width: 100px;
height: 100px;
background: rgb(255, 0, 0);
}
</style>
</head>
<body
data-composition-id="transparency-regression"
data-duration="1"
data-width="200"
data-height="200"
>
<div class="card"></div>
<script>
// Minimal seek protocol — the composition is static.
window.__hf = {
duration: 1,
seek: () => {},
};
</script>
</body>
</html>