From 39bc3749b4f2d5fe4528c19fb5ce5c6615a59dd1 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 4 May 2026 19:25:49 -0700 Subject: [PATCH] fix(engine): default to codec-based alpha capability instead of relying on tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tag-based alpha detection (alpha_mode / ALPHA_MODE / pix_fmt yuva*) is fundamentally brittle. Failure modes seen in the wild: - case-sensitivity across ffmpeg versions (alpha_mode vs ALPHA_MODE) - older muxers that omit the sidecar tag entirely - mp4-as-webm rewraps that drop the tag - ffprobe reporting yuv420p for VP9-with-alpha because the alpha plane lives in a Matroska BlockAdditional sidecar, not the main pix_fmt Each of those silently strips alpha at extraction time. The bug doesn't surface until the rendered output is missing layers — frustrating to debug, silent in stdout. The previous case-insensitive fix patched one of the failure modes; this commit removes the class. The robust alternative is codec-based: any bitstream that CAN carry alpha (VP9, VP8, ProRes 4444) gets the alpha-aware decoder and PNG output by default, regardless of what the tag says. The cost is a small file-size increase on opaque VP9/VP8 sources (cached PNGs vs JPGs); the benefit is no class of silent alpha loss from tag misdetection. - Adds codecMayHaveAlpha() + decoderForCodec() helpers and exports them. - Updates extractVideoFramesRange to force libvpx-vp9 / libvpx for VP9 / VP8 unconditionally (was: only when metadata.hasAlpha). - Updates resolveFrameFormat to default to PNG for any alpha-capable codec (was: only when metadata.hasAlpha). - +4 unit tests covering the codec table. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/services/videoFrameExtractor.test.ts | 37 +++++++++++++++++++ .../src/services/videoFrameExtractor.ts | 37 +++++++++++++++++-- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/packages/engine/src/services/videoFrameExtractor.test.ts b/packages/engine/src/services/videoFrameExtractor.test.ts index 84635f12b..e83ca1254 100644 --- a/packages/engine/src/services/videoFrameExtractor.test.ts +++ b/packages/engine/src/services/videoFrameExtractor.test.ts @@ -10,6 +10,8 @@ import { extractAllVideoFrames, createFrameLookupTable, resolveProjectRelativeSrc, + codecMayHaveAlpha, + decoderForCodec, type VideoElement, type ExtractedFrames, } from "./videoFrameExtractor.js"; @@ -33,6 +35,41 @@ const HAS_FFMPEG = spawnSync("ffmpeg", ["-version"]).status === 0; //