mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 23:03:09 +00:00
refactor(producer): extract HDR compositing helpers and rename media metadata (#373)
## Summary
Four behavior-preserving refactors that reduce complexity in `renderOrchestrator.ts` and clarify the engine ffprobe utility surface. Lands after the correctness fixes (Chunks 1–5) so the refactored code is already correct.
## Why
`Chunk 7` of `plans/hdr-followups.md`. The HDR composite block had grown a ~200 LOC inline closure with 14 captured deps, a repeated capture-options spread, a `extractVideoMetadata` name that now also handles still images, and per-frame re-creation of debug helpers.
## What changed
**7A — Hoist `compositeToBuffer` into a module-scoped helper.** Extract the inline HDR closure into a top-level `compositeHdrFrame()` that takes an `HdrCompositeContext` struct. Construct the context once at the top of the HDR render block and pass it through. Removes a deeply-nested closure from the middle of the orchestrator.
**7B — `buildHdrCaptureOptions()` helper.** Factor the repeated `{ ...captureOptions, skipReadinessVideoIds: ... }` spread into a named helper at the call site.
**7C — Rename `extractVideoMetadata` → `extractMediaMetadata`.** Reflects that the helper handles still images (PNG/JPEG/WebP) in addition to video. Update all callers in engine + producer (`videoFrameExtractor`, `htmlCompiler`, regression-harness, producer ffprobe re-export, tests). Re-export the old name as a deprecated alias from `@hyperframes/engine` for backward compatibility, plus the producer re-export shim.
**7D — Hoist debug counters to module scope.** `countNonZeroAlpha` and `countNonZeroRgb48` are now module-scoped so they aren't re-created per frame and so the closure has fewer captures.
Also touches the `hdr-regression` and `hdr-hlg-regression` README + `meta.json` files reviewed during this refactor.
## Test plan
- [x] `bunx tsc --noEmit -p packages/producer && bunx tsc --noEmit -p packages/engine` clean.
- [x] Engine tests: 313 pass, 0 fail (1218 expect calls).
- [x] `bunx oxlint` + `bunx oxfmt --check` clean on 8 changed source files.
- [x] Diff is structural only — no behavioral changes.
## Stack
Chunk 7 of `plans/hdr-followups.md`. Lands after the correctness fixes (Chunks 1–5) per the suggested merge order.
This commit is contained in:
@@ -9,7 +9,7 @@ import { spawn } from "child_process";
|
||||
import { existsSync, mkdirSync, readdirSync, rmSync } from "fs";
|
||||
import { isAbsolute, join } from "path";
|
||||
import { parseHTML } from "linkedom";
|
||||
import { extractVideoMetadata, type VideoMetadata } from "../utils/ffprobe.js";
|
||||
import { extractMediaMetadata, type VideoMetadata } from "../utils/ffprobe.js";
|
||||
import {
|
||||
analyzeCompositionHdr,
|
||||
isHdrColorSpace as isHdrColorSpaceUtil,
|
||||
@@ -158,7 +158,7 @@ export async function extractVideoFramesRange(
|
||||
const videoOutputDir = join(outputDir, videoId);
|
||||
if (!existsSync(videoOutputDir)) mkdirSync(videoOutputDir, { recursive: true });
|
||||
|
||||
const metadata = await extractVideoMetadata(videoPath);
|
||||
const metadata = await extractMediaMetadata(videoPath);
|
||||
const framePattern = `frame_%05d.${format}`;
|
||||
const outputPattern = join(videoOutputDir, framePattern);
|
||||
|
||||
@@ -411,7 +411,7 @@ export async function extractAllVideoFrames(
|
||||
// Phase 2: Probe color spaces and normalize if mixed HDR/SDR
|
||||
const videoColorSpaces = await Promise.all(
|
||||
resolvedVideos.map(async ({ videoPath }) => {
|
||||
const metadata = await extractVideoMetadata(videoPath);
|
||||
const metadata = await extractMediaMetadata(videoPath);
|
||||
return metadata.colorSpace;
|
||||
}),
|
||||
);
|
||||
@@ -457,7 +457,7 @@ export async function extractAllVideoFrames(
|
||||
if (signal?.aborted) break;
|
||||
const entry = resolvedVideos[i];
|
||||
if (!entry) continue;
|
||||
const metadata = await extractVideoMetadata(entry.videoPath);
|
||||
const metadata = await extractMediaMetadata(entry.videoPath);
|
||||
if (!metadata.isVFR) continue;
|
||||
|
||||
let segDuration = entry.video.end - entry.video.start;
|
||||
@@ -503,7 +503,7 @@ export async function extractAllVideoFrames(
|
||||
// Fallback: if no data-duration/data-end was specified (end is Infinity or 0),
|
||||
// probe the actual video file to get its natural duration.
|
||||
if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
|
||||
const metadata = await extractVideoMetadata(videoPath);
|
||||
const metadata = await extractMediaMetadata(videoPath);
|
||||
const sourceDuration = metadata.durationSeconds - video.mediaStart;
|
||||
videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
|
||||
video.end = video.start + videoDuration;
|
||||
|
||||
Reference in New Issue
Block a user