mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
feat(cli): split cloud render --resolution into --aspect-ratio + --resolution (#1143)
Aligns the `hyperframes cloud render` CLI with the v3 API's decomposed
shape (ef#38182). Replaces the flat 6-value `--resolution` flag with two
independent flags:
- `--resolution`: tier ∈ {1080p, 4k}; default 1080p; 4k bills at 1.5x
- `--aspect-ratio`: ratio ∈ {16:9, 9:16, 1:1}; default 16:9
Regenerates `packages/cli/src/cloud/_gen/{types,client}.ts` from the
updated `experiment-framework/openapi/external-api.json`. Threads
`aspectRatio` through `SubmitOptions` and `buildRenderBody` so it lands
in the request body as `aspect_ratio`.
Old flag values (`landscape`, `portrait-4k`, etc.) now reject at the CLI
layer via `parseEnumFlag`, matching the API surface's rejection. The
six legacy combinations map to the same effective output in the new
shape — see the migration table in ef#38182's PR body.
Deferred (will follow in a separate PR): 720p, 4:5, 5:4, and `auto`.
These need producer-side capability + controller-side composition-dim
inference; out of scope for an API/CLI shape refactor.
This commit is contained in:
@@ -79,17 +79,15 @@ export interface CreateHyperframesRenderRequest {
|
||||
*/
|
||||
format?: "mp4" | "webm" | "mov";
|
||||
/**
|
||||
* Optional resolution preset. If omitted, the composition's own declared
|
||||
* dimensions are used.
|
||||
* Output resolution tier. Defaults to '1080p'. Pass '4k' for 4K renders
|
||||
* (billed at 1.5x).
|
||||
*/
|
||||
resolution?:
|
||||
| "landscape"
|
||||
| "portrait"
|
||||
| "landscape-4k"
|
||||
| "portrait-4k"
|
||||
| "square"
|
||||
| "square-4k"
|
||||
| null;
|
||||
resolution?: HyperframesResolution;
|
||||
/**
|
||||
* Output aspect ratio. Defaults to '16:9' (landscape). Pass '9:16' for
|
||||
* portrait or '1:1' for square.
|
||||
*/
|
||||
aspect_ratio?: HyperframesAspectRatio;
|
||||
/**
|
||||
* Entry HTML file relative to the project root (e.g. compositions/intro.html).
|
||||
* Defaults to index.html when omitted.
|
||||
@@ -135,6 +133,15 @@ export interface DeleteHyperframesRenderResponse {
|
||||
render_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output aspect ratio. Only the three ratios already supported end-to-end by
|
||||
* the render pipeline are exposed today: ``16:9`` (landscape), ``9:16``
|
||||
* (portrait), ``1:1`` (square). ``auto`` and other social-media ratios (4:5,
|
||||
* 5:4) are reserved for a follow-up PR that wires composition-dim inference at
|
||||
* the controller boundary.
|
||||
*/
|
||||
export type HyperframesAspectRatio = "16:9" | "9:16" | "1:1";
|
||||
|
||||
/**
|
||||
* Detailed HyperFrames render resource.
|
||||
*/
|
||||
@@ -181,16 +188,13 @@ export interface HyperframesRenderDetail {
|
||||
*/
|
||||
format: "mp4" | "webm" | "mov";
|
||||
/**
|
||||
* Resolution preset, if one was set.
|
||||
* Resolution tier, if one was set.
|
||||
*/
|
||||
resolution?:
|
||||
| "landscape"
|
||||
| "portrait"
|
||||
| "landscape-4k"
|
||||
| "portrait-4k"
|
||||
| "square"
|
||||
| "square-4k"
|
||||
| null;
|
||||
resolution?: HyperframesResolution | null;
|
||||
/**
|
||||
* Aspect ratio, if one was set.
|
||||
*/
|
||||
aspect_ratio?: HyperframesAspectRatio | null;
|
||||
/**
|
||||
* Composition entry file path.
|
||||
*/
|
||||
@@ -215,6 +219,13 @@ export interface HyperframesRenderDetail {
|
||||
*/
|
||||
export type HyperframesRenderStatus = "queued" | "rendering" | "completed" | "failed";
|
||||
|
||||
/**
|
||||
* Output resolution tier. Pricing diverges only at 4K (1.5x multiplier). The
|
||||
* render-pipeline value set is intentionally narrow at launch; 720p and other
|
||||
* tiers will follow once the producer/CLI surface catches up.
|
||||
*/
|
||||
export type HyperframesResolution = "1080p" | "4k";
|
||||
|
||||
export interface StandardAPIError {
|
||||
/**
|
||||
* Machine-readable error code
|
||||
|
||||
@@ -58,14 +58,8 @@ import { isAbsolute, resolve as resolvePath } from "node:path";
|
||||
|
||||
const VALID_QUALITY = ["draft", "standard", "high"] as const;
|
||||
const VALID_FORMAT = ["mp4", "webm", "mov"] as const;
|
||||
const VALID_RESOLUTION = [
|
||||
"landscape",
|
||||
"portrait",
|
||||
"landscape-4k",
|
||||
"portrait-4k",
|
||||
"square",
|
||||
"square-4k",
|
||||
] as const;
|
||||
const VALID_RESOLUTION = ["1080p", "4k"] as const;
|
||||
const VALID_ASPECT_RATIO = ["16:9", "9:16", "1:1"] as const;
|
||||
|
||||
const FORMAT_EXT: Record<string, string> = { mp4: ".mp4", webm: ".webm", mov: ".mov" };
|
||||
|
||||
@@ -96,8 +90,11 @@ export default defineCommand({
|
||||
format: { type: "string", description: "mp4 | webm | mov (default: mp4)" },
|
||||
resolution: {
|
||||
type: "string",
|
||||
description:
|
||||
"Resolution preset: landscape | portrait | landscape-4k | portrait-4k | square | square-4k",
|
||||
description: "Resolution tier: 1080p | 4k (default: 1080p; 4k is billed at 1.5x)",
|
||||
},
|
||||
"aspect-ratio": {
|
||||
type: "string",
|
||||
description: "Aspect ratio: 16:9 | 9:16 | 1:1 (default: 16:9)",
|
||||
},
|
||||
composition: {
|
||||
type: "string",
|
||||
@@ -185,6 +182,9 @@ export default defineCommand({
|
||||
const resolution = parseEnumFlag(args.resolution, VALID_RESOLUTION, {
|
||||
flag: "--resolution",
|
||||
});
|
||||
const aspectRatio = parseEnumFlag(args["aspect-ratio"], VALID_ASPECT_RATIO, {
|
||||
flag: "--aspect-ratio",
|
||||
});
|
||||
const pollIntervalMs = parsePollIntervalMs(args["poll-interval"]);
|
||||
const maxWaitMs = parseMaxWaitMs(args["max-wait"]);
|
||||
validateIdempotencyKey(args["idempotency-key"]);
|
||||
@@ -214,6 +214,7 @@ export default defineCommand({
|
||||
quality,
|
||||
format,
|
||||
resolution,
|
||||
aspectRatio,
|
||||
composition: args.composition,
|
||||
variables,
|
||||
title: args.title,
|
||||
@@ -443,6 +444,7 @@ interface SubmitOptions {
|
||||
quality: "draft" | "standard" | "high" | undefined;
|
||||
format: "mp4" | "webm" | "mov" | undefined;
|
||||
resolution: CreateHyperframesRenderRequest["resolution"] | undefined;
|
||||
aspectRatio: CreateHyperframesRenderRequest["aspect_ratio"] | undefined;
|
||||
composition: string | undefined;
|
||||
variables: Record<string, unknown> | undefined;
|
||||
title: string | undefined;
|
||||
@@ -470,6 +472,7 @@ function buildRenderBody(opts: SubmitOptions): CreateHyperframesRenderRequest {
|
||||
if (opts.quality !== undefined) body.quality = opts.quality;
|
||||
if (opts.format !== undefined) body.format = opts.format;
|
||||
if (opts.resolution !== undefined) body.resolution = opts.resolution;
|
||||
if (opts.aspectRatio !== undefined) body.aspect_ratio = opts.aspectRatio;
|
||||
if (opts.composition !== undefined) body.composition = opts.composition;
|
||||
if (opts.variables !== undefined) body.variables = opts.variables;
|
||||
if (opts.title !== undefined) body.title = opts.title;
|
||||
|
||||
Reference in New Issue
Block a user