mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
fix(cli): accept portrait aspects for --resolution alias flag
The aspect-agnostic resolution aliases (`--resolution 1080p` / `hd` / `4k` / `uhd`) previously all normalized to a landscape preset, which rejected portrait 1080x1920 compositions with 'Output resolution incompatible'. Users had to specify the orientation-bearing alias (`1080p-portrait`) or render at native. This threads two new fields (`outputResolutionAspectAgnostic` + `outputResolutionRaw`) through the render pipeline. At the CLI layer we detect whether the user's flag was an aspect-agnostic alias; at the compile stage we re-map the preset to the composition's orientation via the existing `suggestMatchingPreset` sibling-lookup (formerly private). Explicit orientation-bearing aliases and canonical presets stay strict. Field signal: ts=1784176662 (darwin/arm64, CLI 0.7.59, `--resolution 1080p` on a 1080x1920 portrait comp). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> — Via
This commit is contained in:
@@ -43,7 +43,12 @@ import { isVideoFrameFormat } from "@hyperframes/engine";
|
||||
import { resolveRenderPaths } from "./utils/paths.js";
|
||||
import { defaultLogger, type ProducerLogger } from "./logger.js";
|
||||
import { Semaphore } from "./utils/semaphore.js";
|
||||
import { parseFps, normalizeResolutionFlag, type CanvasResolution } from "@hyperframes/core";
|
||||
import {
|
||||
parseFps,
|
||||
normalizeResolutionFlag,
|
||||
isAspectAgnosticResolutionAlias,
|
||||
type CanvasResolution,
|
||||
} from "@hyperframes/core";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -93,9 +98,17 @@ interface RenderInput {
|
||||
* Output resolution preset (e.g. `landscape-4k`). Drives the same
|
||||
* `resolveDeviceScaleFactor` supersampling path the local CLI uses — Chrome
|
||||
* renders at a higher devicePixelRatio so the captured screenshot lands at
|
||||
* the requested dimensions. Aspect ratio must match the composition.
|
||||
* the requested dimensions. Aspect ratio must match the composition unless
|
||||
* `outputResolutionAspectAgnostic` is set (see below).
|
||||
*/
|
||||
outputResolution?: CanvasResolution;
|
||||
/**
|
||||
* True when `outputResolution` was normalized from an aspect-agnostic alias
|
||||
* (`1080p`, `hd`, `4k`, `uhd`). The compile stage will adapt the preset to
|
||||
* the composition's orientation instead of rejecting portrait/square
|
||||
* compositions as an aspect-ratio mismatch.
|
||||
*/
|
||||
outputResolutionAspectAgnostic?: boolean;
|
||||
}
|
||||
|
||||
interface PreparedRenderInput {
|
||||
@@ -151,7 +164,8 @@ export function parseRenderOptions(body: Record<string, unknown>): Omit<RenderIn
|
||||
? body.videoFrameFormat
|
||||
: undefined;
|
||||
|
||||
const { variables, outputResolution } = parseRenderOverrides(body);
|
||||
const { variables, outputResolution, outputResolutionAspectAgnostic } =
|
||||
parseRenderOverrides(body);
|
||||
|
||||
return {
|
||||
outputPath,
|
||||
@@ -165,6 +179,7 @@ export function parseRenderOptions(body: Record<string, unknown>): Omit<RenderIn
|
||||
format,
|
||||
variables,
|
||||
outputResolution,
|
||||
outputResolutionAspectAgnostic,
|
||||
videoFrameFormat,
|
||||
};
|
||||
}
|
||||
@@ -182,15 +197,23 @@ function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||
function parseRenderOverrides(body: Record<string, unknown>): {
|
||||
variables?: Record<string, unknown>;
|
||||
outputResolution?: CanvasResolution;
|
||||
outputResolutionAspectAgnostic?: boolean;
|
||||
} {
|
||||
// Only forward a plain JSON object. Arrays / primitives / null → undefined.
|
||||
const variables = isPlainObject(body.variables) ? body.variables : undefined;
|
||||
// Accept canonical presets and aliases ("4k", "landscape-4k", …).
|
||||
const outputResolution =
|
||||
typeof body.outputResolution === "string"
|
||||
? normalizeResolutionFlag(body.outputResolution)
|
||||
: undefined;
|
||||
return { variables, outputResolution };
|
||||
const rawOutputResolution =
|
||||
typeof body.outputResolution === "string" ? body.outputResolution : undefined;
|
||||
const outputResolution = rawOutputResolution
|
||||
? normalizeResolutionFlag(rawOutputResolution)
|
||||
: undefined;
|
||||
// Preserve the "raw shape was tier-only" signal so the compile stage can
|
||||
// adapt the preset to the composition's orientation. Set only when
|
||||
// normalization succeeded — a bad string doesn't need the flag.
|
||||
const outputResolutionAspectAgnostic = outputResolution
|
||||
? isAspectAgnosticResolutionAlias(rawOutputResolution)
|
||||
: undefined;
|
||||
return { variables, outputResolution, outputResolutionAspectAgnostic };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,6 +233,7 @@ function buildRenderJobConfig(input: RenderInput, log: ProducerLogger) {
|
||||
entryFile: input.entryFile,
|
||||
variables: input.variables,
|
||||
outputResolution: input.outputResolution,
|
||||
outputResolutionAspectAgnostic: input.outputResolutionAspectAgnostic,
|
||||
videoFrameFormat: input.videoFrameFormat,
|
||||
logger: log,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user