mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-08 02:36:10 +00:00
fix(cli): wire aspect-agnostic resolution through cloudrun/lambda/batch + preflight recompute
Addresses R2 CHANGES_REQUESTED from Miga + Rames on PR #2529: 1. Sibling-surface gap (blocker): `hyperframes cloudrun render{,-batch}`, `hyperframes lambda render{,-batch}` all advertised the same tier-only aliases (`1080p` / `hd` / `4k` / `uhd`) but normalized them to `landscape` and never set `outputResolutionAspectAgnostic`. The distributed plumbing PR #2529 added received `undefined` from those callers, so portrait `1080p` still hit the original aspect-mismatch on Cloud Run / Lambda. Fix: introduce `resolveResolutionFlagPair` in `@hyperframes/parsers` (the single source of truth for the two-step normalize + aspect-agnostic detect) and route every distributed entrypoint through a shared `parseOutputResolutionFlag` CLI util so the alias signal now reaches `SerializableDistributedRenderConfig`. Studio Server keeps its canonical-only HTTP contract; that intent is now pinned in tests. 2. Preflight recompute (hardening): the earlier "downgrade aspect-mismatch" preflight cleared un-remapped mismatches, so IG 4:5 (non-preset aspect, no sibling) and portrait-4K comp + `--resolution 1080p` (remap + downsample) both slipped through to fail late in `resolveDeviceScaleFactor`. Now `checkRenderResolutionPreflight` computes the effective preset via `suggestMatchingPreset` (mirroring the compile stage's `adaptAspectAgnosticResolution`) and re-checks against that — only genuinely-fixable mismatches clear early. New tests pin both regressed input classes. 3. Docker forwarding boundary test (Miga's important #2): pinned `1080p` survives verbatim as `--resolution 1080p` in the Docker args so the in-container CLI can re-run `isAspectAgnosticResolutionAlias`. 4. Doc-nit (Miga): parsers/src/types.ts no longer references the nonexistent `resolveResolutionForComposition` — points at the actual remap helpers. Fallow: cloudrun.ts / lambda.ts share 390 lines of pre-existing structural symmetry (parallel AWS + GCP dispatchers), and lambda/render.ts + render-batch.ts declare parallel RenderArgs interfaces. Both re-flagged after threading the aspect-agnostic field through each surface; ignored with justification in .fallowrc.jsonc. lambda.ts's `run` and lambda/render.ts's `waitForCompletion` are pre-existing CRAP-score hotspots untouched by this PR — added under health.ignore. Co-Authored-By: Claude <noreply@anthropic.com> — Via
This commit is contained in:
@@ -1244,6 +1244,47 @@ describe("checkRenderResolutionPreflight", () => {
|
||||
expect(result?.kind).toBe("aspect-mismatch");
|
||||
expect(result?.message).toContain("--resolution portrait");
|
||||
});
|
||||
|
||||
// Rames Δ2 on PR #2529: the earlier "downgrade aspect-mismatch to
|
||||
// undefined" preflight cleared *un-remapped* mismatches, so two input
|
||||
// classes below regressed from an early actionable error to a late throw
|
||||
// deep in `resolveDeviceScaleFactor` (browser + ffmpeg already up).
|
||||
// The fix computes the *effective* preset via `suggestMatchingPreset`
|
||||
// (mirroring the compile stage) and re-checks against that, so only
|
||||
// genuinely-fixable mismatches clear early.
|
||||
|
||||
it("blocks IG 4:5 (non-preset aspect) early with an aspect-aware message", async () => {
|
||||
// 1080×1350 is a 4:5 portrait — no canonical preset shares that aspect,
|
||||
// so `suggestMatchingPreset` returns undefined and `adaptAspectAgnosticResolution`
|
||||
// keeps the original preset. Before the fix, aspect-agnostic downgraded
|
||||
// the mismatch here to undefined; now the preflight surfaces it early.
|
||||
const result = await checkRenderResolutionPreflight(comp(1080, 1350), "landscape", agnostic);
|
||||
expect(result?.kind).toBe("aspect-mismatch");
|
||||
// No sibling preset to suggest → message falls back to the "pick a preset
|
||||
// whose orientation matches" hint (see `buildAspectMismatch` in
|
||||
// `@hyperframes/parsers/outputResolutionCompatibility`).
|
||||
expect(result?.message).toMatch(/preset whose orientation matches|omit --resolution/i);
|
||||
});
|
||||
|
||||
it("blocks a portrait-4K comp + `1080p` downsample early (orientation-flip masks the tier gap)", async () => {
|
||||
// 2160×3840 (portrait 4K) + `--resolution 1080p` — the compile stage
|
||||
// remaps `landscape` → `portrait` (1080×1920), and *then* the preset
|
||||
// is smaller than the composition. The un-remapped preflight let this
|
||||
// slip through as an aspect-mismatch downgrade; the remap-then-check
|
||||
// catches the real failure — downsampling — early.
|
||||
const result = await checkRenderResolutionPreflight(comp(2160, 3840), "landscape", agnostic);
|
||||
expect(result?.kind).toBe("downsampling");
|
||||
});
|
||||
|
||||
it("blocks a portrait 720p comp + `1080p` non-integer upscale early (orientation-flip masks the fractional DPR)", async () => {
|
||||
// 720×1280 (portrait 720p) + `--resolution 1080p` — remap `landscape`
|
||||
// → `portrait` (1080×1920). widthRatio = 1080 / 720 = 1.5, which
|
||||
// `resolveDeviceScaleFactor` rejects. Surfacing it in preflight beats
|
||||
// failing after Chrome + ffmpeg spin up. Same class as Miga's
|
||||
// important note on PR #2529.
|
||||
const result = await checkRenderResolutionPreflight(comp(720, 1280), "landscape", agnostic);
|
||||
expect(result?.kind).toBe("non-integer-scale");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user