mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
refactor: dedupe resolution presets and clean up 4k stack
This commit is contained in:
@@ -28,6 +28,34 @@ export const CANVAS_DIMENSIONS = {
|
||||
"portrait-4k": { width: 2160, height: 3840 },
|
||||
} as const;
|
||||
|
||||
export const VALID_CANVAS_RESOLUTIONS = Object.keys(
|
||||
CANVAS_DIMENSIONS,
|
||||
) as readonly CanvasResolution[];
|
||||
|
||||
const RESOLUTION_ALIASES: Record<string, CanvasResolution> = {
|
||||
"1080p": "landscape",
|
||||
hd: "landscape",
|
||||
"1080p-portrait": "portrait",
|
||||
"portrait-1080p": "portrait",
|
||||
"4k": "landscape-4k",
|
||||
uhd: "landscape-4k",
|
||||
"4k-portrait": "portrait-4k",
|
||||
};
|
||||
|
||||
/**
|
||||
* Map a user-facing resolution string (canonical name or alias) to a
|
||||
* `CanvasResolution`. Returns undefined for unknown values so callers
|
||||
* can produce their own "invalid" UX (CLI exit, route validation, etc.).
|
||||
*/
|
||||
export function normalizeResolutionFlag(input: string | undefined): CanvasResolution | undefined {
|
||||
if (!input) return undefined;
|
||||
const lowered = input.toLowerCase();
|
||||
if ((VALID_CANVAS_RESOLUTIONS as readonly string[]).includes(lowered)) {
|
||||
return lowered as CanvasResolution;
|
||||
}
|
||||
return RESOLUTION_ALIASES[lowered];
|
||||
}
|
||||
|
||||
export interface TimelineElementBase {
|
||||
id: string;
|
||||
type: TimelineElementType;
|
||||
|
||||
@@ -12,6 +12,25 @@ describe("@hyperframes/core public API exports", () => {
|
||||
expect(core.CANVAS_DIMENSIONS["portrait-4k"]).toEqual({ width: 2160, height: 3840 });
|
||||
});
|
||||
|
||||
it("exports VALID_CANVAS_RESOLUTIONS derived from CANVAS_DIMENSIONS", () => {
|
||||
expect(core.VALID_CANVAS_RESOLUTIONS).toEqual([
|
||||
"landscape",
|
||||
"portrait",
|
||||
"landscape-4k",
|
||||
"portrait-4k",
|
||||
]);
|
||||
});
|
||||
|
||||
it("exports normalizeResolutionFlag with alias support", () => {
|
||||
expect(core.normalizeResolutionFlag("4k")).toBe("landscape-4k");
|
||||
expect(core.normalizeResolutionFlag("uhd")).toBe("landscape-4k");
|
||||
expect(core.normalizeResolutionFlag("1080p")).toBe("landscape");
|
||||
expect(core.normalizeResolutionFlag("landscape-4k")).toBe("landscape-4k");
|
||||
expect(core.normalizeResolutionFlag("UHD")).toBe("landscape-4k");
|
||||
expect(core.normalizeResolutionFlag("8k")).toBeUndefined();
|
||||
expect(core.normalizeResolutionFlag(undefined)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("exports TIMELINE_COLORS", () => {
|
||||
expect(core.TIMELINE_COLORS).toBeDefined();
|
||||
expect(core.TIMELINE_COLORS.video).toBeDefined();
|
||||
|
||||
@@ -36,6 +36,8 @@ export type {
|
||||
|
||||
export {
|
||||
CANVAS_DIMENSIONS,
|
||||
VALID_CANVAS_RESOLUTIONS,
|
||||
normalizeResolutionFlag,
|
||||
TIMELINE_COLORS,
|
||||
DEFAULT_DURATIONS,
|
||||
COMPOSITION_VARIABLE_TYPES,
|
||||
|
||||
@@ -3,6 +3,9 @@ import { streamSSE } from "hono/streaming";
|
||||
import { existsSync, readFileSync, mkdirSync, unlinkSync, readdirSync, statSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type { StudioApiAdapter, RenderJobState } from "../types.js";
|
||||
import { VALID_CANVAS_RESOLUTIONS, type CanvasResolution } from "../../core.types.js";
|
||||
|
||||
const VALID_RESOLUTIONS = new Set<string>(VALID_CANVAS_RESOLUTIONS);
|
||||
|
||||
export function registerRenderRoutes(api: Hono, adapter: StudioApiAdapter): void {
|
||||
// Scoped job store — not shared across createStudioApi() calls
|
||||
@@ -59,9 +62,8 @@ export function registerRenderRoutes(api: Hono, adapter: StudioApiAdapter): void
|
||||
const quality = ["draft", "standard", "high"].includes(body.quality ?? "")
|
||||
? (body.quality as string)
|
||||
: "standard";
|
||||
const VALID_RESOLUTIONS = new Set(["landscape", "portrait", "landscape-4k", "portrait-4k"]);
|
||||
const outputResolution = VALID_RESOLUTIONS.has(body.resolution ?? "")
|
||||
? (body.resolution as "landscape" | "portrait" | "landscape-4k" | "portrait-4k")
|
||||
? (body.resolution as CanvasResolution)
|
||||
: undefined;
|
||||
|
||||
const now = new Date();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { CanvasResolution } from "../core.types.js";
|
||||
|
||||
/** Resolved info about a single project. */
|
||||
export interface ResolvedProject {
|
||||
id: string;
|
||||
@@ -65,12 +67,10 @@ export interface StudioApiAdapter {
|
||||
quality: string;
|
||||
jobId: string;
|
||||
/**
|
||||
* Optional output resolution preset (e.g. "landscape-4k"). When set, the
|
||||
* producer supersamples the composition via Chrome `deviceScaleFactor`.
|
||||
* The composition's authored dimensions are unchanged. See the
|
||||
* `resolveDeviceScaleFactor` constraints in the producer.
|
||||
* Optional output resolution preset. See `resolveDeviceScaleFactor` in
|
||||
* the producer for the integer-scale + aspect + HDR constraints.
|
||||
*/
|
||||
outputResolution?: "landscape" | "portrait" | "landscape-4k" | "portrait-4k";
|
||||
outputResolution?: CanvasResolution;
|
||||
}): RenderJobState;
|
||||
|
||||
/** Optional: generate a JPEG thumbnail via Puppeteer or similar. */
|
||||
|
||||
Reference in New Issue
Block a user