interface Asset { id: string; url: string; type: string; is_reference?: boolean; /** Duration in seconds for video/audio assets */ duration?: number; } type TimelineElementType = "video" | "image" | "text" | "audio" | "composition"; type MediaElementType = "video" | "image" | "audio"; declare const CANVAS_DIMENSIONS: { readonly landscape: { readonly width: 1920; readonly height: 1080; }; readonly portrait: { readonly width: 1080; readonly height: 1920; }; readonly "landscape-4k": { readonly width: 3840; readonly height: 2160; }; readonly "portrait-4k": { readonly width: 2160; readonly height: 3840; }; readonly square: { readonly width: 1080; readonly height: 1080; }; readonly "square-4k": { readonly width: 2160; readonly height: 2160; }; }; type CanvasResolution = keyof typeof CANVAS_DIMENSIONS; declare const VALID_CANVAS_RESOLUTIONS: readonly CanvasResolution[]; /** * 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.). */ declare function normalizeResolutionFlag(input: string | undefined): CanvasResolution | undefined; /** * True when `input` names a resolution *tier* without nailing an orientation * (`1080p`, `hd`, `4k`, `uhd`). Case-insensitive. * * The `--resolution` CLI flag treats these as "target this size; keep the * composition's orientation" — a portrait 1080×1920 comp with `--resolution * 1080p` should land at 1080×1920, not blow up on aspect mismatch. Explicit * canonical presets (`landscape`, `portrait`, …) and orientation-suffixed * aliases (`1080p-portrait`) stay strict — the user picked an orientation. * * Consumers pair this signal with the composition's dimensions (in a * follow-up pass after HTML parse) to pick the right preset via * `suggestMatchingPreset` — see `adaptAspectAgnosticResolution` in the * compile stage (`@hyperframes/producer`) for the canonical remap. */ declare function isAspectAgnosticResolutionAlias(input: string | undefined): boolean; /** * Public-boundary helper: given a raw `--resolution` / `--output-resolution` * flag value, return the pair every distributed render entrypoint needs to * forward end-to-end so the compile stage can adapt aspect-agnostic aliases * to the composition's orientation: * * - `outputResolution`: normalized {@link CanvasResolution} (or `undefined` * for unknown values — callers own their invalid-input UX). * - `outputResolutionAspectAgnostic`: `true` when the raw input was a * tier-only alias (`1080p` / `hd` / `4k` / `uhd`). Passes through to * `DistributedRenderConfig.outputResolutionAspectAgnostic` so the compile * stage remaps `landscape` → `portrait` / `square` when the composition * dimensions demand it. * * Exported to centralize the two-step pattern (`normalizeResolutionFlag` + * `isAspectAgnosticResolutionAlias`) that would otherwise be duplicated at * every entrypoint that emits a `DistributedRenderConfig` (`hyperframes * cloudrun render`, `hyperframes lambda render` / `render-batch`, the local * CLI). Divergence between those callers is what shipped the portrait-1080p * regression this helper prevents from recurring. */ interface ResolvedResolutionFlag { outputResolution: CanvasResolution | undefined; outputResolutionAspectAgnostic: boolean; } declare function resolveResolutionFlagPair(input: string | undefined): ResolvedResolutionFlag; interface TimelineElementBase { id: string; type: TimelineElementType; name: string; startTime: number; duration: number; zIndex: number; x?: number; y?: number; scale?: number; opacity?: number; } interface TimelineMediaElement extends TimelineElementBase { type: MediaElementType; src: string; mediaStartTime?: number; sourceDuration?: number; isAroll?: boolean; sourceWidth?: number; sourceHeight?: number; volume?: number; hasAudio?: boolean; } interface WaveformData { peaks: number[]; duration: number; sampleRate?: number; } interface TimelineTextElement extends TimelineElementBase { type: "text"; content: string; color?: string; fontSize?: number; textShadow?: boolean; fontFamily?: string; fontWeight?: number; textOutline?: boolean; textOutlineColor?: string; textOutlineWidth?: number; textHighlight?: boolean; textHighlightColor?: string; textHighlightPadding?: number; textHighlightRadius?: number; } interface TimelineCompositionElement extends TimelineElementBase { type: "composition"; src: string; compositionId: string; scale?: number; sourceDuration?: number; variableValues?: Record; sourceWidth?: number; sourceHeight?: number; } type CompositionVariableType = "string" | "number" | "color" | "boolean" | "enum" | "font" | "image"; /** * Runtime list of every valid `CompositionVariableType`. Use this anywhere * a Set/array of valid type strings is needed (lint rules, validators). * The `satisfies` guard turns adding a new variant to the union without * also adding it here into a compile error. */ declare const COMPOSITION_VARIABLE_TYPES: readonly ["string", "number", "color", "boolean", "enum", "font", "image"]; interface CompositionVariableBase { id: string; type: CompositionVariableType; label: string; description?: string; } interface StringVariable extends CompositionVariableBase { type: "string"; default: string; placeholder?: string; maxLength?: number; } interface NumberVariable extends CompositionVariableBase { type: "number"; default: number; min?: number; max?: number; step?: number; unit?: string; } interface ColorVariable extends CompositionVariableBase { type: "color"; default: string; /** Brand role identifier, e.g. "color:primary". */ brandRole?: string; } interface BooleanVariable extends CompositionVariableBase { type: "boolean"; default: boolean; } interface EnumVariable extends CompositionVariableBase { type: "enum"; default: string; options: { value: string; label: string; }[]; } /** * Font variable — value is a `{name, source}` object (object-valued; LOCKED §7). * `default` is the fallback font-family name string. * `source` is the font stylesheet URL (e.g. Google Fonts CSS). * `default_name` / `default_source` are the CSS-level fallbacks when the * brand font is absent. */ interface FontVariable extends CompositionVariableBase { type: "font"; /** Fallback font-family name, e.g. "Inter". */ default: string; /** Font stylesheet URL (e.g. Google Fonts CSS link). */ source?: string; /** CSS font-family name to use when source is unavailable, e.g. "sans-serif". */ default_name?: string; /** Fallback font stylesheet URL (empty string = system font). */ default_source?: string; } /** * Image variable — value is a `{url, …}` object (object-valued; LOCKED §7). * `default` is the fallback image URL string. * `brandRole` is an optional semantic label, e.g. "logo:primary". */ interface ImageVariable extends CompositionVariableBase { type: "image"; /** Fallback image URL. */ default: string; /** Brand role identifier, e.g. "logo:primary". */ brandRole?: string; } type CompositionVariable = StringVariable | NumberVariable | ColorVariable | BooleanVariable | EnumVariable | FontVariable | ImageVariable; interface CompositionSpec { id: string; duration: number; variables: CompositionVariable[]; } type TimelineElement = TimelineMediaElement | TimelineTextElement | TimelineCompositionElement; declare function isTextElement(el: TimelineElement): el is TimelineTextElement; declare function isMediaElement(el: TimelineElement): el is TimelineMediaElement; declare function isCompositionElement(el: TimelineElement): el is TimelineCompositionElement; interface MediaFile { id: string; name: string; type: TimelineElementType; src: string; file?: File; duration?: number; compositionId?: string; sourceWidth?: number; sourceHeight?: number; } declare const TIMELINE_COLORS: Record; declare const DEFAULT_DURATIONS: Record; interface CompositionAPI { id: string; duration: number; seek(time: number): void; getTime(): number; getDuration(): number; } interface PlayerAPI { play(): void; pause(): void; seek(time: number, options?: { keepPlaying?: boolean; }): void; getTime(): number; getDuration(): number; isPlaying(): boolean; getMainTimeline(): unknown; getElementBounds(elementId: string): void; getElementsAtPoint(x: number, y: number): void; setElementPosition(elementId: string, x: number, y: number): void; previewElementPosition(elementId: string, x: number, y: number): void; setElementKeyframes(elementId: string, keyframes: Array<{ id: string; time: number; properties: { x?: number; y?: number; }; }> | null): void; setElementScale(elementId: string, scale: number): void; setElementFontSize(elementId: string, fontSize: number): void; setElementTextContent(elementId: string, content: string): void; setElementTextColor(elementId: string, color: string): void; setElementTextShadow(elementId: string, enabled: boolean): void; setElementTextFontWeight(elementId: string, weight: number): void; setElementTextFontFamily(elementId: string, fontFamily: string): void; setElementTextOutline(elementId: string, enabled: boolean, color?: string, width?: number): void; setElementTextHighlight(elementId: string, enabled: boolean, color?: string, padding?: number, radius?: number): void; setElementVolume(elementId: string, volume: number): void; setStageZoom(scale: number, focusX: number, focusY: number): void; getStageZoom(): { scale: number; focusX: number; focusY: number; }; setStageZoomKeyframes(keyframes: Array<{ id: string; time: number; zoom: { scale: number; focusX: number; focusY: number; }; ease?: string; }> | null): void; getStageZoomKeyframes(): Array<{ id: string; time: number; zoom: { scale: number; focusX: number; focusY: number; }; ease?: string; }>; addElement(data: AddElementData): boolean; removeElement(elementId: string): boolean; updateElementTiming(elementId: string, start?: number, end?: number): boolean; setElementTiming(elementId: string, startTime: number, duration: number, mediaStartTime?: number): void; updateElementSrc(elementId: string, src: string): boolean; updateElementLayer(elementId: string, zIndex: number): boolean; updateElementBasePosition(elementId: string, x?: number, y?: number, scale?: number): boolean; markTimelineDirty(): void; isTimelineDirty(): boolean; rebuildTimeline(): void; ensureTimeline(): void; enableRenderMode(): void; disableRenderMode(): void; renderSeek(time: number, options?: { suppressEvents?: boolean; }): void; getElementVisibility(elementId: string): { visible: boolean; opacity?: number; }; getVisibleElements(): Array<{ id: string; tagName: string; start: number; end: number; }>; getRenderState(): { time: number; duration: number; isPlaying: boolean; renderMode: boolean; timelineDirty: boolean; }; } interface AddElementData { id: string; type: "video" | "image" | "text" | "audio" | "composition"; name?: string; src?: string; content?: string; start: number; end: number; zIndex?: number; x?: number; y?: number; scale?: number; fontSize?: number; color?: string; textShadow?: boolean; fontWeight?: number; textOutline?: boolean; textOutlineColor?: string; textOutlineWidth?: number; textHighlight?: boolean; textHighlightColor?: string; textHighlightPadding?: number; textHighlightRadius?: number; compositionId?: string; sourceWidth?: number; sourceHeight?: number; isAroll?: boolean; } interface ValidationResult { valid: boolean; errors: string[]; warnings: string[]; } interface CompositionAsset { id: string; name: string; type: "composition"; src: string; duration: number; compositionId: string; thumbnail?: string; } interface Keyframe { id: string; time: number; properties: Partial; ease?: string; } interface KeyframeProperties { x: number; y: number; opacity: number; scale: number; scaleX: number; scaleY: number; rotation: number; width: number; height: number; } interface ElementKeyframes { elementId: string; keyframes: Keyframe[]; } interface StageZoom { scale: number; focusX: number; focusY: number; } interface StageZoomKeyframe { id: string; time: number; zoom: StageZoom; ease?: string; } declare function getDefaultStageZoom(resolution: CanvasResolution): StageZoom; export { type AddElementData as A, type BooleanVariable as B, type CompositionVariable as C, DEFAULT_DURATIONS as D, type ElementKeyframes as E, type FontVariable as F, isTextElement as G, normalizeResolutionFlag as H, type ImageVariable as I, resolveResolutionFlagPair as J, type Keyframe as K, type MediaElementType as M, type NumberVariable as N, type PlayerAPI as P, type ResolvedResolutionFlag as R, type StageZoomKeyframe as S, type TimelineElement as T, type ValidationResult as V, type WaveformData as W, type CanvasResolution as a, type Asset as b, CANVAS_DIMENSIONS as c, COMPOSITION_VARIABLE_TYPES as d, type ColorVariable as e, type CompositionAPI as f, type CompositionAsset as g, type CompositionSpec as h, type CompositionVariableBase as i, type CompositionVariableType as j, type EnumVariable as k, type KeyframeProperties as l, type MediaFile as m, type StageZoom as n, type StringVariable as o, TIMELINE_COLORS as p, type TimelineCompositionElement as q, type TimelineElementBase as r, type TimelineElementType as s, type TimelineMediaElement as t, type TimelineTextElement as u, VALID_CANVAS_RESOLUTIONS as v, getDefaultStageZoom as w, isAspectAgnosticResolutionAlias as x, isCompositionElement as y, isMediaElement as z };