perf(engine): webp extraction format + injector MIME routing#434
perf(engine): webp extraction format + injector MIME routing#434jrusso1020 wants to merge 1 commit intoperf/producer-extraction-cachefrom
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
Hi, Bumping CACHE_SCHEMA_VERSION to 2 makes all existing v1 cache entries unreachable, so callers extracting jpg/png will incur full cache misses after upgrade even though the on-disk jpg/png frame layout and lookup logic still match. Severity: remediation recommended | Category: performance How to fix: Preserve v1 keys for jpg/png Agent prompt to fix - you can give this to your LLM of choice:
Found by Qodo. Free code review for open-source maintainers. |

What
Adds
"webp"as a third option forExtractionOptions.formatand makes the producer use it for the SDR frame extraction path.format: "webp"branch in the extractor's ffmpeg args (-c:v libwebp -quality N -lossless 0).image/webpin the data URI.format: "webp"in its oneextractAllVideoFramescall.External callers using
"jpg"or"png"keep working — this PR is additive, not a rename.Why
PR 4 of the 5-PR stack from
hyperframes-notes/producer-render-architecture-review-2026-04-21.md:For the SDR extraction path this shows up in two places in the
RenderPerfSummaryfrom PR 1:tmpPeakBytes— WebP frames are smaller than JPEG at equivalent quality, noticeably on text-heavy content where JPEG's DCT struggles.videoExtractBreakdown.extractMs— libwebp's lossy path isn't dramatically faster than libjpeg-turbo, but the smaller files mean shorter writes to disk, and we amortize that over ~K frames per render.The bigger architectural win the doc describes (unifying an
if (hasAlpha)branch) isn't visible in the SDR extractor today because the producer never branched onhasAlphafor extraction in the first place — but the groundwork this PR lays (WebP handles both opaque and alpha) is what lets future alpha-input work skip the format fork entirely.How
Extractor
-c:v libwebp -quality $q -lossless 0on the WebP branch. libwebp's-qualityis 0-100 with higher-is-better, which is the inverse of JPEG's-q:vscale, so the mapping is just pass-through of theExtractionOptions.qualityparam (default 95).Injector
mimeTypeForFramePathreplaces the inlineframePath.endsWith(".png") ? "image/png" : "image/jpeg"check. Chrome has decoded WebP natively since 2014 so the data URI "just works" in a page-level<img>.Cache schema
Bumped
CACHE_SCHEMA_VERSIONfrom 1 to 2. Reason: v1 cache dirs only hold.jpgor.pngframes; a v2 extraction withformat: "webp"writes.webpframes.lookupCacheEntryfilters by file extension, but the schema bump defends against hash collisions with the old keyspace and makes future format changes explicit.v1 and v2 keys can coexist under the same cache root without cross-serving — an old jpg entry can't be accidentally returned for a webp request because the key itself encodes the version.
Producer
Explicit
format: "webp"inextractAllVideoFrames. No other call sites change.Test plan
videoFrameInjector.test.ts— asserts.webp/.png/.jpg/unknown extensions each produce the correctdata:image/…;base64,prefix.videoFrameExtractor.test.ts:format: "webp"produces.webpfiles on disk and hits the cache on a second call..jpgand continue to pass — the extractor still supports"jpg"and"png".Stack
Built on #433 → #432 → #430. Each PR in the stack adds to
RenderPerfSummary; PR 1'stmpPeakBytesandvideoExtractBreakdown.extractMsare the primary signals for this PR's win.Follow-ups
!hasAlphaand segment-length floor — the last PR in the stack.