mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 10:06:21 +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:
@@ -10,11 +10,8 @@
|
||||
|
||||
import { defineCommand } from "citty";
|
||||
import type { DistributedFormat } from "@hyperframes/aws-lambda/sdk";
|
||||
import {
|
||||
type CanvasResolution,
|
||||
VALID_CANVAS_RESOLUTIONS,
|
||||
normalizeResolutionFlag,
|
||||
} from "@hyperframes/core";
|
||||
import { type CanvasResolution } from "@hyperframes/core";
|
||||
import { parseOutputResolutionFlag } from "../utils/parseOutputResolution.js";
|
||||
import type { Example } from "./_examples.js";
|
||||
import { c } from "../ui/colors.js";
|
||||
import { readAllowedCompositionFpsFromDir } from "../utils/compositionFps.js";
|
||||
@@ -307,6 +304,7 @@ export default defineCommand({
|
||||
process.exit(1);
|
||||
}
|
||||
const { runRender } = await import("./lambda/render.js");
|
||||
const renderResolution = parseOutputResolution(args["output-resolution"]);
|
||||
await runRender({
|
||||
projectDir,
|
||||
stackName,
|
||||
@@ -314,7 +312,8 @@ export default defineCommand({
|
||||
fps: fpsRaw,
|
||||
width,
|
||||
height,
|
||||
outputResolution: parseOutputResolution(args["output-resolution"]),
|
||||
outputResolution: renderResolution.outputResolution,
|
||||
outputResolutionAspectAgnostic: renderResolution.outputResolutionAspectAgnostic,
|
||||
format: parseFormat(args.format),
|
||||
codec: parseCodec(args.codec),
|
||||
quality: parseQuality(args.quality),
|
||||
@@ -362,6 +361,7 @@ export default defineCommand({
|
||||
process.exit(1);
|
||||
}
|
||||
const { runRenderBatch } = await import("./lambda/render-batch.js");
|
||||
const batchResolution = parseOutputResolution(args["output-resolution"]);
|
||||
await runRenderBatch({
|
||||
projectDir,
|
||||
stackName,
|
||||
@@ -370,7 +370,8 @@ export default defineCommand({
|
||||
fps: fpsRaw,
|
||||
width,
|
||||
height,
|
||||
outputResolution: parseOutputResolution(args["output-resolution"]),
|
||||
outputResolution: batchResolution.outputResolution,
|
||||
outputResolutionAspectAgnostic: batchResolution.outputResolutionAspectAgnostic,
|
||||
format: parseFormat(args.format),
|
||||
codec: parseCodec(args.codec),
|
||||
quality: parseQuality(args.quality),
|
||||
@@ -481,12 +482,23 @@ const parseQuality = (raw: unknown): (typeof QUALITIES)[number] | undefined =>
|
||||
const parseChromeSource = (raw: unknown): (typeof CHROME_SOURCES)[number] =>
|
||||
parseEnum(raw, CHROME_SOURCES, "[lambda deploy] --chrome-source", "sparticuz")!;
|
||||
|
||||
function parseOutputResolution(raw: unknown): CanvasResolution | undefined {
|
||||
if (raw == null || raw === "") return undefined;
|
||||
const normalized = normalizeResolutionFlag(String(raw));
|
||||
if (normalized) return normalized;
|
||||
throw new Error(
|
||||
`[lambda render] --output-resolution must be one of ${VALID_CANVAS_RESOLUTIONS.join("|")} ` +
|
||||
`(or an alias: 1080p, 4k, uhd, hd, 1080p-portrait, portrait-1080p, 4k-portrait, 1080p-square, square-1080p, 4k-square); got ${String(raw)}`,
|
||||
);
|
||||
/**
|
||||
* Lambda flavor of the shared {@link parseOutputResolutionFlag} — same wire
|
||||
* contract as the Cloud Run counterpart. Runtime work lives in the shared
|
||||
* util; wire-config-level coverage lives at `./lambda/render.test.ts` /
|
||||
* `./lambda/render-batch.test.ts`, and full input-space coverage at
|
||||
* `../utils/parseOutputResolution.test.ts`.
|
||||
*/
|
||||
function parseOutputResolution(raw: unknown): {
|
||||
outputResolution: CanvasResolution | undefined;
|
||||
outputResolutionAspectAgnostic: boolean;
|
||||
} {
|
||||
return parseOutputResolutionFlag(raw, {
|
||||
surfaceLabel: "[lambda render]",
|
||||
// The Lambda `--output-resolution` help text advertises the full alias
|
||||
// list (tier-only + orientation-suffixed) — keep the error message
|
||||
// faithful to that surface's docs.
|
||||
aliasHint:
|
||||
"1080p, 4k, uhd, hd, 1080p-portrait, portrait-1080p, 4k-portrait, 1080p-square, square-1080p, 4k-square",
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user