You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(producer): enable webm in distributed mode via concat-copy (#951)
* feat(producer): enable webm in distributed mode via concat-copy
PR 8.2 of the WebM distributed-rendering plan (v1.5 backlog #1; see
DISTRIBUTED-RENDERING-PLAN.md §7.2). Wires libvpx-vp9 webm through the
distributed pipeline now that PR 8.1 proved concat-copy works.
Architectural decision: Path A (concat-copy) — based on PR 8.1's smoke
test result (9/9 tests pass for both yuv420p and yuva420p VP9 streams).
The simpler architecture wins; no re-encode in assemble, no encode-
parallelism loss.
Changes:
- plan.ts:
- DistributedRenderConfig.format and PlanResult.format now include
"webm" — type-level acceptance matches the runtime gate.
- rejectUnsupportedDistributedFormat() no longer trips on webm. HDR
mp4 remains the only refused configuration.
- resolveEncoderTriple() returns libvpx-vp9-software + yuva420p +
preset="good" for format="webm". yuva420p preserves alpha — the
format's main reason for existing for web delivery.
- codec= remains rejected for non-mp4 formats (mov is always ProRes
4444; webm is always libvpx-vp9). The error message lists all four
distributed-supported formats.
- FormatNotSupportedInDistributedError docstring updated to reflect
the new reality (only HDR is unsupported).
- freezePlan.ts: LockedRenderConfig.encoder gains "libvpx-vp9-software".
Mirrors libx265-software / prores-software / png-sequence in shape;
the chunk worker reads this discriminant to decide encode args.
- renderChunk.ts: drops the now-incorrect cast that excluded webm from
buildSyntheticRenderJob's format input; tightens the preset-format
cast to include webm.
- assemble.ts: docstring + comment updates. The mp4/mov concat-copy
path is format-agnostic — webm uses the exact same code (applyFaststart
is a no-op for webm via the existing chunkEncoder.ts gate;
muxVideoWithAudio already routes webm to libopus audio).
- planFormatBanlist.test.ts: webm-rejection tests removed; replaced with
"accepts webm" tests + a HDR+webm combo test that verifies HDR is the
trip regardless of format.
- plan.test.ts: new describe block pins the webm wiring contract:
format="webm" produces an encoder=libvpx-vp9-software /
pixelFormat=yuva420p planDir with closedGop=true and gopSize=chunkSize.
- webm-concat-copy.test.ts (smoke): extended with a yuva420p variant
that proves the alpha pixel format the distributed pipeline actually
emits also round-trips through concat-copy. 9/9 tests pass locally.
§8 format support matrix in DISTRIBUTED-RENDERING-PLAN.md is intentionally
left unchanged at this PR — it flips to ✓ in PR 8.4 once the end-to-end
fixture (PR 8.3) is green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(producer): include webm in plan-time needsAlpha + strengthen alpha smoke
PR review feedback from Miguel and Vai on #951 caught a real bug:
`plan.ts`'s `needsAlpha` disjunction excluded `"webm"`, so the plan
stage froze `forceScreenshot: false` into the `LockedRenderConfig`
even though distributed webm uses `yuva420p`. Every chunk worker
captured opaque RGB via BeginFrame (which doesn't preserve alpha on
Linux headless-shell), and libvpx-vp9 encoded uniformly-opaque alpha
that the encoder then dropped — producing un-keyable webm.
Two changes:
1. **plan.ts**: include `"webm"` in `needsAlpha`. Matches the
in-process renderer's logic at `renderOrchestrator.ts:1469`
(`const needsAlpha = isWebm || isMov || isPngSequence`); the two
sites must stay in sync since the distributed pipeline's PSNR
regression compares against the in-process baseline.
2. **Smoke test (yuva420p describe)**: source frames now use a real
alpha gradient (`geq=a='X*255/W'` on top of `testsrc2`) instead of
`testsrc2 + format=rgba` which was uniformly opaque. The decode-
pix_fmt assertion is dropped (ffprobe reports `yuv420p` for
VP9-with-alpha because the alpha lives in a Matroska
`BlockAdditional` sidecar) and replaced with two stronger checks:
- `TAG:ALPHA_MODE=1` is present on the stream — proves the
encoder was actually configured for alpha
- alpha plane variance after `-c:v libvpx-vp9 -i ... -pix_fmt rgba
-vf extractplanes=a,signalstats` — proves the alpha sub-stream
round-trips through concat-copy with spatially-varying content,
not uniform/dropped alpha
- decode-test gate is now exit-code-only (was `exitCode || stderr`
which would flake on chatty ffmpeg `-v error` builds emitting
non-fatal DTS/container notes)
These checks would have caught the `needsAlpha` bug before review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(aws-lambda): widen narrow format types to include webm
CI on PR #951 was failing at typecheck/build because the producer's
`DistributedRenderConfig.format` widened to include webm in this PR
but the aws-lambda package's narrow `"mp4" | "mov" | "png-sequence"`
type literals in `events.ts`, `handler.ts`, and `validateConfig.ts`
hadn't kept up. `renderToLambda.ts:87` passed `config.format` (now
including webm) into a parameter typed against the narrow union,
producing TS2345.
This widening originally landed in PR #952 (test fixture PR) but
needs to be atomic with the producer's widening here to keep each
PR independently typecheck-clean.
Also refactor `formatExtension` from a switch dispatch to a
`Record<DistributedFormat, string>` lookup. Adding the webm case
tipped the switch's CRAP to the 30.0 fallow threshold; the lookup
table drops cyclomatic from 5 to 1 with the same compile-time
exhaustiveness guarantee (TS errors on missing entries when
`DistributedFormat` adds a new format). The runtime
`_exhaustive: never` throw was only protecting against a string
slipping past TS; `validateConfig.ts`'s `ALLOWED_FORMATS` already
gates untrusted input at the SDK boundary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments