reframe-video 0.6.34 → 0.6.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/assemble.js +138 -0
- package/dist/bin.js +178 -31
- package/dist/browserEntry.js +62 -3
- package/dist/cli.js +93 -14
- package/dist/compile-api.js +20 -0
- package/dist/compile.js +20 -0
- package/dist/diff.js +81 -3
- package/dist/frame.js +81 -3
- package/dist/index.js +1528 -1107
- package/dist/labels.js +80 -2
- package/dist/lint.js +1060 -0
- package/dist/manifest.js +1065 -0
- package/dist/types/compose.d.ts +6 -0
- package/dist/types/devicePreset.d.ts +36 -3
- package/dist/types/dsl.d.ts +4 -3
- package/dist/types/index.d.ts +4 -2
- package/dist/types/ir.d.ts +13 -5
- package/dist/types/manifest.d.ts +92 -0
- package/dist/types/titles.d.ts +71 -0
- package/dist/verifyOverlay.js +1152 -0
- package/guides/edsl-guide.md +58 -0
- package/guides/regen-contract.md +14 -0
- package/package.json +1 -1
- package/skills/reframe/SKILL.md +26 -0
package/dist/types/compose.d.ts
CHANGED
|
@@ -83,6 +83,12 @@ export interface ComposeReport {
|
|
|
83
83
|
}[];
|
|
84
84
|
warnings: string[];
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Which params an overlay may patch on a labeled timeline step, per kind — the
|
|
88
|
+
* single source of truth for both `applyOverlay` (what it accepts) and
|
|
89
|
+
* `sceneManifest` (what it advertises as patchable). Keep them from drifting.
|
|
90
|
+
*/
|
|
91
|
+
export declare const TIMELINE_PATCHABLE: Record<string, string[]>;
|
|
86
92
|
export declare function composeScene(base: SceneIR, ...overlays: OverlayDoc[]): {
|
|
87
93
|
ir: SceneIR;
|
|
88
94
|
report: ComposeReport;
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Device-mockup presets
|
|
2
|
+
* Device-mockup presets — a parametric vector frame (phone/laptop/browser/…) with
|
|
3
3
|
* a CLIPPED screen "content slot". The sibling of motionPreset — that generates
|
|
4
4
|
* a TimelineIR, this generates a NodeIR subtree. Pure primitives + clip, so no
|
|
5
|
-
* assets and fully deterministic (plain JSON, no Date/random).
|
|
6
|
-
* tier — no true perspective.
|
|
5
|
+
* assets and fully deterministic (plain JSON, no Date/random).
|
|
7
6
|
*
|
|
8
7
|
* devicePreset("phone", { id: "hero", content: [ ...your UI nodes ] })
|
|
9
8
|
*
|
|
9
|
+
* Redesigned around three orthogonal layers (all back-compat; the public surface
|
|
10
|
+
* and the stable ids `${id}` / `${id}-screen` / `${id}-content` are unchanged):
|
|
11
|
+
*
|
|
12
|
+
* 1. A `DeviceCtx` resolved once (palette + dims + material + style + a seeded
|
|
13
|
+
* PRNG) and threaded to every part.
|
|
14
|
+
* 2. A small PARTS vocabulary (`slab`, `screenStack`, `phoneNotch`, …) where the
|
|
15
|
+
* material/lighting lives ONCE, so every chassis — and every future chassis —
|
|
16
|
+
* inherits the premium look for free.
|
|
17
|
+
* 3. A `CHASSIS` registry (name → builder) that just ARRANGES parts; adding a
|
|
18
|
+
* device is one entry + one `SCREENS`/`BOUNDS` row, not a new `switch` arm.
|
|
19
|
+
*
|
|
20
|
+
* Material is PREMIUM by default (gradient body, ambient screen glow, soft contact
|
|
21
|
+
* shadow, glass glare) — `material:"flat"` opts back to clean flat fills. `style`
|
|
22
|
+
* picks "glass" (realistic) or "neon" (graphic, additive edge glow). Each instance
|
|
23
|
+
* auto-varies from its `id` (a deterministic seed) within bounded, on-model ranges;
|
|
24
|
+
* pass `seed` to pin or explore. A 2.5D vector tier — no true perspective.
|
|
25
|
+
*
|
|
10
26
|
* Each instance needs a distinct `id` (it prefixes every generated node id);
|
|
11
27
|
* two with the same prefix collide via the scene's duplicate-id validation.
|
|
12
28
|
*
|
|
@@ -18,6 +34,14 @@
|
|
|
18
34
|
import type { NodeIR } from "./ir.js";
|
|
19
35
|
export declare const DEVICE_PRESET_NAMES: readonly ["phone", "tablet", "laptop", "browser", "watch", "monitor", "tv", "foldable", "terminal", "car"];
|
|
20
36
|
export type DevicePresetName = (typeof DEVICE_PRESET_NAMES)[number];
|
|
37
|
+
/** Visual fidelity tier. `premium` (default) layers gradient/glow/shadow on top
|
|
38
|
+
* of the silhouette; `flat` is clean solid fills (lightest, golden-style). */
|
|
39
|
+
export type DeviceMaterial = "premium" | "flat";
|
|
40
|
+
/** Premium aesthetic. `glass` = realistic glass/metal + soft shadow; `neon` =
|
|
41
|
+
* flat body + additive edge glow (graphic, motion-graphics punch). */
|
|
42
|
+
export type DeviceStyle = "glass" | "neon";
|
|
43
|
+
/** Phone front-camera treatment. Defaults to the iOS-style dynamic island. */
|
|
44
|
+
export type DeviceNotch = "island" | "notch" | "punch" | "none";
|
|
21
45
|
export interface DevicePresetOpts {
|
|
22
46
|
/** Id PREFIX for every generated node (default "device"). Make it unique per instance. */
|
|
23
47
|
id?: string;
|
|
@@ -38,6 +62,15 @@ export interface DevicePresetOpts {
|
|
|
38
62
|
content?: NodeIR[];
|
|
39
63
|
/** Browser/terminal address-bar text. */
|
|
40
64
|
url?: string;
|
|
65
|
+
/** Visual tier (default "premium"). */
|
|
66
|
+
material?: DeviceMaterial;
|
|
67
|
+
/** Premium aesthetic (default "glass"). */
|
|
68
|
+
style?: DeviceStyle;
|
|
69
|
+
/** Deterministic variation. Omit ⇒ derived from `id` (each instance differs);
|
|
70
|
+
* same value ⇒ identical; different value ⇒ same family, varied. */
|
|
71
|
+
seed?: number;
|
|
72
|
+
/** Phone front-camera style (default "island"). */
|
|
73
|
+
notch?: DeviceNotch;
|
|
41
74
|
}
|
|
42
75
|
/** The screen's content area (content-local coords: origin 0,0 = screen centre,
|
|
43
76
|
* pre-scale). Author/scroll `content` against these bounds. */
|
package/dist/types/dsl.d.ts
CHANGED
|
@@ -59,9 +59,10 @@ export interface BeatOpts {
|
|
|
59
59
|
nodes?: string[];
|
|
60
60
|
/** Group children in parallel instead of sequence. */
|
|
61
61
|
parallel?: boolean;
|
|
62
|
-
/** Absolute start (
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
/** Absolute start (number), or a timeline label to anchor to (string) — the
|
|
63
|
+
* beat starts at that label's time, `gap` offsetting it. Keep anchor beats in a `par`. */
|
|
64
|
+
at?: number | string;
|
|
65
|
+
/** Relative shift before the beat (with a label `at`, the offset from the label). */
|
|
65
66
|
gap?: number;
|
|
66
67
|
/** Interior time-stretch factor. */
|
|
67
68
|
scale?: number;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ export * from "./ir.js";
|
|
|
2
2
|
export * from "./dsl.js";
|
|
3
3
|
export { validateScene, validateComposition, SceneValidationError, PROPS_BY_TYPE } from "./validate.js";
|
|
4
4
|
export { compileComposition, type CompiledComposition, type ScenePlacement, } from "./composeComposition.js";
|
|
5
|
-
export { composeScene, formatComposeReport, type OverlayDoc, type ComposeReport, } from "./compose.js";
|
|
5
|
+
export { composeScene, formatComposeReport, TIMELINE_PATCHABLE, type OverlayDoc, type ComposeReport, } from "./compose.js";
|
|
6
|
+
export { sceneManifest, lintScene, type SceneManifest, type NodeAddress, type StateAddress, type TimelineAddress, type BeatAddress, type BehaviorAddress, type ManifestSummary, type LintFinding, } from "./manifest.js";
|
|
6
7
|
export { compileScene, type CompiledScene, type PropertySegment, type LabelSpan, type MotionDriver } from "./compile.js";
|
|
7
8
|
export { pathPoint, pathTangentAngle, type Pt } from "./path.js";
|
|
8
9
|
export { cameraTo, cameraFit, cameraMatrix, CAMERA_ID, CAMERA_PROPS } from "./camera.js";
|
|
@@ -11,8 +12,9 @@ export { linearGradient, radialGradient, conicGradient, isGradient } from "./gra
|
|
|
11
12
|
export { glow, dropShadow } from "./effects.js";
|
|
12
13
|
export { row, column, grid, type RowOpts, type GridOpts } from "./layout.js";
|
|
13
14
|
export { photoMontage, videoMontage, type MontageImage, type MontageOpts, type MontageResult, type KenBurns } from "./montage.js";
|
|
15
|
+
export { title, lowerThird, type TitleOpts, type TitleResult, type LowerThirdOpts, type LowerThirdResult } from "./titles.js";
|
|
14
16
|
export { motionPreset, PRESET_NAMES, type PresetName, type PresetRig, type PresetOpts } from "./presets.js";
|
|
15
|
-
export { devicePreset, deviceScreen, deviceScreenCenter, deviceBounds, deviceScreenPoint, DEVICE_PRESET_NAMES, type DevicePresetName, type DevicePresetOpts } from "./devicePreset.js";
|
|
17
|
+
export { devicePreset, deviceScreen, deviceScreenCenter, deviceBounds, deviceScreenPoint, DEVICE_PRESET_NAMES, type DevicePresetName, type DevicePresetOpts, type DeviceMaterial, type DeviceStyle, type DeviceNotch } from "./devicePreset.js";
|
|
16
18
|
export { cursor, cursorTo, cursorPath, cursorClick, cursorDouble, type CursorStyle, type CursorOpts, type CursorToOpts, type CursorPathOpts, type CursorClickOpts } from "./cursor.js";
|
|
17
19
|
export { rig, rigPose, poseTo, ikReach, humanoid, ovalPath, type Bone, type RigOpts, type Pose, type HumanoidOpts } from "./rig.js";
|
|
18
20
|
export { characterPreset, CHARACTER_PRESET_NAMES, type CharacterPresetName, type CharacterPresetOpts } from "./characterPreset.js";
|
package/dist/types/ir.d.ts
CHANGED
|
@@ -243,10 +243,12 @@ export interface VideoProps extends BaseProps {
|
|
|
243
243
|
/** Box-fit into width×height, like the image node. `"fill"` (default) | `"cover"`. */
|
|
244
244
|
fit?: ImageFit;
|
|
245
245
|
/**
|
|
246
|
-
* Scene-time
|
|
247
|
-
*
|
|
246
|
+
* Scene-time at which playback begins. Before it, frame 0 (clipStart) shows; the
|
|
247
|
+
* node's visibility is still controlled by opacity/timeline. Default 0. A NUMBER is
|
|
248
|
+
* an absolute time; a STRING anchors the start to that timeline label's t0 (like
|
|
249
|
+
* `beat.at`), so the clip follows when its shot is retimed (e.g. `start: "shot-2"`).
|
|
248
250
|
*/
|
|
249
|
-
start?: number;
|
|
251
|
+
start?: number | string;
|
|
250
252
|
/** Playback speed multiplier (2 = double speed). Default 1. */
|
|
251
253
|
rate?: number;
|
|
252
254
|
/** Source in-point (seconds) shown at `start`. Default 0. */
|
|
@@ -373,8 +375,14 @@ export type TimelineIR = {
|
|
|
373
375
|
*/
|
|
374
376
|
nodes?: string[];
|
|
375
377
|
parallel?: boolean;
|
|
376
|
-
/**
|
|
377
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Start placement (overrides sequential flow). A NUMBER is an absolute time;
|
|
380
|
+
* a STRING anchors the beat to that timeline label's start (e.g.
|
|
381
|
+
* `at: "shot-2"`), so the beat stays synced when the target is retimed (the
|
|
382
|
+
* same idea as `audio.cues`). With a label anchor, `gap` is the offset from
|
|
383
|
+
* the label. Anchor beats should sit in a `par` branch, not a sequential flow.
|
|
384
|
+
*/
|
|
385
|
+
at?: number | string;
|
|
378
386
|
/** Relative shift: a leading delay before the beat (and everything after). */
|
|
379
387
|
gap?: number;
|
|
380
388
|
/** Interior time-stretch factor (every child offset and duration ×scale). */
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene manifest + addressability lint — make the override namespace queryable.
|
|
3
|
+
*
|
|
4
|
+
* Both override stacks (authoring `composeScene`, runtime `sampleProp`) can only
|
|
5
|
+
* find anything through the node-id / timeline-label namespace. That namespace is
|
|
6
|
+
* the entire edit API, but it's implicit. `sceneManifest` enumerates it — every
|
|
7
|
+
* editable address a human or an AI editor can patch — and `lintScene` flags the
|
|
8
|
+
* surface that ISN'T addressable (motion with no label can't be retimed by an
|
|
9
|
+
* overlay). Pure reads over a CompiledScene; no IR/evaluate changes.
|
|
10
|
+
*/
|
|
11
|
+
import type { CompiledScene } from "./compile.js";
|
|
12
|
+
import type { NodeIR, Size, TimelineIR } from "./ir.js";
|
|
13
|
+
export interface NodeAddress {
|
|
14
|
+
id: string;
|
|
15
|
+
type: NodeIR["type"];
|
|
16
|
+
/** Enclosing group id (absent for a top-level node). */
|
|
17
|
+
parent?: string;
|
|
18
|
+
/** Overlay address for base-prop patches: `nodes.<id>`. */
|
|
19
|
+
address: string;
|
|
20
|
+
/** Props an overlay may set on this node (PROPS_BY_TYPE for its type). */
|
|
21
|
+
editableProps: string[];
|
|
22
|
+
/** Props this node actually animates (has a tween/to segment or a motion path). */
|
|
23
|
+
animatedProps: string[];
|
|
24
|
+
/** State names that override this node (`states.<name>.<id>` addresses). */
|
|
25
|
+
inStates: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface StateAddress {
|
|
28
|
+
name: string;
|
|
29
|
+
address: string;
|
|
30
|
+
touches: {
|
|
31
|
+
id: string;
|
|
32
|
+
props: string[];
|
|
33
|
+
}[];
|
|
34
|
+
}
|
|
35
|
+
export interface TimelineAddress {
|
|
36
|
+
label: string;
|
|
37
|
+
kind: TimelineIR["kind"];
|
|
38
|
+
t0: number;
|
|
39
|
+
t1: number;
|
|
40
|
+
/** Params an overlay may patch on this step (TIMELINE_PATCHABLE for its kind). */
|
|
41
|
+
patchable: string[];
|
|
42
|
+
address: string;
|
|
43
|
+
}
|
|
44
|
+
export interface BeatAddress {
|
|
45
|
+
name: string;
|
|
46
|
+
t0: number;
|
|
47
|
+
t1: number;
|
|
48
|
+
/** Node ids the beat semantically owns (its `nodes` field). */
|
|
49
|
+
ownsNodes: string[];
|
|
50
|
+
address: string;
|
|
51
|
+
}
|
|
52
|
+
export interface BehaviorAddress {
|
|
53
|
+
target: string;
|
|
54
|
+
prop: string;
|
|
55
|
+
kind: string;
|
|
56
|
+
address: string;
|
|
57
|
+
}
|
|
58
|
+
export interface ManifestSummary {
|
|
59
|
+
nodeCount: number;
|
|
60
|
+
/** Labeled timeline steps + named beats (addressable timing). */
|
|
61
|
+
labeledSteps: number;
|
|
62
|
+
/** Motion steps (tween/to/motionPath) with NO label — unaddressable timing. */
|
|
63
|
+
unlabeledMotionSteps: number;
|
|
64
|
+
/** labeled motion steps / total motion steps (1 when there is no motion). */
|
|
65
|
+
motionAddressableRatio: number;
|
|
66
|
+
}
|
|
67
|
+
export interface SceneManifest {
|
|
68
|
+
scene: {
|
|
69
|
+
id: string;
|
|
70
|
+
duration: number;
|
|
71
|
+
fps: number;
|
|
72
|
+
size: Size;
|
|
73
|
+
background?: string;
|
|
74
|
+
};
|
|
75
|
+
nodes: NodeAddress[];
|
|
76
|
+
states: StateAddress[];
|
|
77
|
+
timeline: TimelineAddress[];
|
|
78
|
+
beats: BeatAddress[];
|
|
79
|
+
behaviors: BehaviorAddress[];
|
|
80
|
+
summary: ManifestSummary;
|
|
81
|
+
}
|
|
82
|
+
export interface LintFinding {
|
|
83
|
+
rule: string;
|
|
84
|
+
severity: "warn" | "error";
|
|
85
|
+
message: string;
|
|
86
|
+
/** Present when the finding refers to an existing address. */
|
|
87
|
+
address?: string;
|
|
88
|
+
}
|
|
89
|
+
/** Enumerate a scene's full addressable / editable surface. Pure + deterministic. */
|
|
90
|
+
export declare function sceneManifest(compiled: CompiledScene): SceneManifest;
|
|
91
|
+
/** Flag the surface that ISN'T overlay-addressable. Static, no render. */
|
|
92
|
+
export declare function lintScene(compiled: CompiledScene): LintFinding[];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Title + lower-third generators — the motion-graphic overlay vocabulary for a
|
|
3
|
+
* media piece (titles, name straps), the high-level analog of `photoMontage`.
|
|
4
|
+
*
|
|
5
|
+
* `title()` composes the kinetic-text engine (`splitText` + `textIn`/`textOut`);
|
|
6
|
+
* `lowerThird()` is a name/role strap with an accent bar. Both return
|
|
7
|
+
* `{ nodes, timeline }` (house style) so a caller spreads the nodes into the
|
|
8
|
+
* scene and composes the timeline with `seq`/`par`. Pure + deterministic; stable
|
|
9
|
+
* ids so overlay edits address them.
|
|
10
|
+
*/
|
|
11
|
+
import type { NodeIR, TimelineIR } from "./ir.js";
|
|
12
|
+
import { type FontWeight, type TextBlock, type TextInName, type TextOutName } from "./textFx.js";
|
|
13
|
+
export interface TitleOpts {
|
|
14
|
+
/** The headline text. */
|
|
15
|
+
text: string;
|
|
16
|
+
/** Id PREFIX → glyph ids `${id}-${i}` (default "title"). Make it unique. */
|
|
17
|
+
id?: string;
|
|
18
|
+
/** Anchor (default centre of a 1920×1080 frame). */
|
|
19
|
+
x?: number;
|
|
20
|
+
y?: number;
|
|
21
|
+
fontSize?: number;
|
|
22
|
+
fontWeight?: FontWeight;
|
|
23
|
+
fill?: string;
|
|
24
|
+
letterSpacing?: number;
|
|
25
|
+
/** Entrance preset (default "cascade"). */
|
|
26
|
+
entrance?: TextInName;
|
|
27
|
+
/** Optional exit preset — when set, the title plays in, holds, then exits. */
|
|
28
|
+
exit?: TextOutName;
|
|
29
|
+
/** Duration multiplier (>1 faster). */
|
|
30
|
+
speed?: number;
|
|
31
|
+
/** Deterministic per-glyph variation. */
|
|
32
|
+
seed?: number;
|
|
33
|
+
/** Seconds held before the exit (only used with `exit`). Default 2. */
|
|
34
|
+
hold?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface TitleResult {
|
|
37
|
+
nodes: NodeIR[];
|
|
38
|
+
timeline: TimelineIR;
|
|
39
|
+
/** The laid-out text block — add `textLoop` behaviors or extra tweens off this. */
|
|
40
|
+
block: TextBlock;
|
|
41
|
+
}
|
|
42
|
+
/** A kinetic headline. Labels: `${id}-in` (entrance) and `${id}-out` (exit). */
|
|
43
|
+
export declare function title(opts: TitleOpts): TitleResult;
|
|
44
|
+
export interface LowerThirdOpts {
|
|
45
|
+
/** Main line (e.g. a name). */
|
|
46
|
+
name: string;
|
|
47
|
+
/** Sub line (e.g. a role). Omit for a single-line strap. */
|
|
48
|
+
role?: string;
|
|
49
|
+
/** Id PREFIX → `${id}` group + `${id}-bar`/`${id}-name`/`${id}-role` (default "lt"). */
|
|
50
|
+
id?: string;
|
|
51
|
+
/** Group anchor (default a bottom-left title-safe position). */
|
|
52
|
+
x?: number;
|
|
53
|
+
y?: number;
|
|
54
|
+
/** Accent bar colour (default "#FF4D00"). */
|
|
55
|
+
accent?: string;
|
|
56
|
+
/** Name colour (default "#FFFFFF"). */
|
|
57
|
+
fill?: string;
|
|
58
|
+
/** Role colour (default "#C9C9C9"). */
|
|
59
|
+
subFill?: string;
|
|
60
|
+
/** Name font size (default 48); the role is ~0.58× of it. */
|
|
61
|
+
fontSize?: number;
|
|
62
|
+
/** Seconds the strap holds before it exits. Default 3. */
|
|
63
|
+
hold?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface LowerThirdResult {
|
|
66
|
+
nodes: NodeIR[];
|
|
67
|
+
timeline: TimelineIR;
|
|
68
|
+
}
|
|
69
|
+
/** A name/role strap with an accent bar that grows in, text sliding + fading.
|
|
70
|
+
* Labels: `${id}-in` (entrance) and `${id}-out` (exit). */
|
|
71
|
+
export declare function lowerThird(opts: LowerThirdOpts): LowerThirdResult;
|