@open-take/compositor 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pascal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ //#region rolldown:runtime
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all) __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true
7
+ });
8
+ };
9
+
10
+ //#endregion
11
+ export { __export };
@@ -0,0 +1,482 @@
1
+ import { __export } from "./chunk-Cl8Af3a2.js";
2
+
3
+ //#region src/types.d.ts
4
+ type Pt = {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ type BBox = {
9
+ x: number;
10
+ y: number;
11
+ w: number;
12
+ h: number;
13
+ };
14
+ /** Editorial zoom intent for an action (set by the planner/agent). */
15
+ type ZoomIntent = "auto" | "never" | "always";
16
+ /** Fields common to every captured action. `x,y` is the anchor / start
17
+ * point (cursor target), viewport CSS px. */
18
+ type CaptureEventBase = {
19
+ /** anchor point (click target / field / drag start), viewport CSS px */
20
+ x: number;
21
+ y: number;
22
+ /** element bounding box, viewport CSS px — the ground-truth edge */
23
+ box?: BBox;
24
+ /** ms from recording start (when the cursor arrives / action begins) */
25
+ tMs: number;
26
+ /** selector / note, kept for editability */
27
+ sel?: string;
28
+ note?: string;
29
+ /** selective-zoom intent from the plan (default auto = heuristic) */
30
+ zoom?: ZoomIntent;
31
+ };
32
+ /** A click (or a type's focus-click): an instantaneous action at a point. */
33
+ type CaptureClick = CaptureEventBase & {
34
+ kind?: "click";
35
+ };
36
+ /** Typing into a focused field: the cursor parks and the zoom holds for
37
+ * `durationMs` while the text appears in the recording. */
38
+ type CaptureType = CaptureEventBase & {
39
+ kind: "type";
40
+ /** what was typed (editability) */
41
+ text: string;
42
+ /** ms the typing occupies on screen (ground-truth wall time) */
43
+ durationMs: number;
44
+ };
45
+ /** A drag: a path from the anchor (`x,y`) to `to`, optionally via `path`,
46
+ * with the button held for `durationMs`. */
47
+ type CaptureDrag = CaptureEventBase & {
48
+ kind: "drag";
49
+ /** drag end point, viewport CSS px */
50
+ to: {
51
+ x: number;
52
+ y: number;
53
+ };
54
+ /** full polyline incl. ends, viewport CSS px (freehand strokes) */
55
+ path?: {
56
+ x: number;
57
+ y: number;
58
+ }[];
59
+ /** ms the drag occupies on screen (ground-truth wall time) */
60
+ durationMs: number;
61
+ /** how the stroke was paced and BAKED into the ink: "smooth" (accel-in /
62
+ * decel-out — a natural hand-draw) or "linear" (constant speed). The
63
+ * compositor cursor must replay the SAME easing to stay locked to the ink.
64
+ * Absent ⇒ linear (legacy captures). */
65
+ ease?: "linear" | "smooth";
66
+ };
67
+ /** A scroll: the content pans for `durationMs`. The cursor holds (no travel),
68
+ * full-view (no zoom). `dy` is the signed pixels scrolled (editability). */
69
+ type CaptureScroll = CaptureEventBase & {
70
+ kind: "scroll";
71
+ /** signed pixels scrolled (positive = down) */
72
+ dy: number;
73
+ /** ms the scroll occupies on screen (ground-truth wall time) */
74
+ durationMs: number;
75
+ };
76
+ /** A hover: the cursor travels to `x,y` and dwells for `durationMs` so a
77
+ * tooltip / menu / hover-state reveals. Like a click that doesn't click. */
78
+ type CaptureHover = CaptureEventBase & {
79
+ kind: "hover";
80
+ /** ms the dwell occupies on screen (ground-truth wall time) */
81
+ durationMs: number;
82
+ };
83
+ /** A key press / shortcut: keyboard-driven, so the cursor holds (no travel).
84
+ * Holds for `durationMs` while the effect plays out; if a reveal element was
85
+ * located, `box` carries its bbox so the zoom can frame it. */
86
+ type CapturePress = CaptureEventBase & {
87
+ kind: "press";
88
+ /** the chord pressed, e.g. "Enter" / "Meta+k" (editability) */
89
+ keys: string;
90
+ /** ms the hold occupies on screen (ground-truth wall time) */
91
+ durationMs: number;
92
+ };
93
+ type CaptureEvent = CaptureClick | CaptureType | CaptureDrag | CaptureScroll | CaptureHover | CapturePress;
94
+ type CaptureLog = {
95
+ video: {
96
+ width: number;
97
+ height: number;
98
+ fps?: number | string;
99
+ durationS?: number;
100
+ };
101
+ viewport: {
102
+ w: number;
103
+ h: number;
104
+ };
105
+ start?: {
106
+ x: number;
107
+ y: number;
108
+ };
109
+ /** the ordered ground-truth actions (click / type / drag) */
110
+ events: CaptureEvent[];
111
+ tEndMs?: number;
112
+ };
113
+ type ZoomDecision = {
114
+ /** selective: not every action zooms. Edit this to tune/remove. */
115
+ enabled: boolean;
116
+ /** absolute stage scale to reach (bbox-fit, capped) */
117
+ scale: number;
118
+ /** video-px point to frame (bbox center), pre-clamp */
119
+ center: Pt;
120
+ /** when the zoom-in begins (ms) */
121
+ inAtMs: number;
122
+ /** Optional "glide": a slow camera drift WHILE the zoom is held, as a velocity
123
+ * in video-px per second {x,y}. The held centre pans from `center` by
124
+ * `glide · holdSeconds` across the hold window (then the next beat ramps from
125
+ * there / it zooms out from there). Adds life vs a dead-static hold (Screen
126
+ * Studio's glide). Absent/0 ⇒ a still hold. Clamped to the video at read time,
127
+ * so a drift just stops at the edge. Keep it gentle (tens of px/s). */
128
+ glide?: Pt;
129
+ /** why this decision (for the human/agent reading the composition) */
130
+ reason: string;
131
+ };
132
+ type CompEvent = {
133
+ kind: "click" | "type" | "drag" | "scroll" | "hover" | "press";
134
+ tMs: number;
135
+ /** anchor point (click / focus / drag start / hover) in video-px. For a
136
+ * scroll/press the cursor does not move; this is its resting point. */
137
+ point: Pt;
138
+ /** element bbox in video-px (if known) */
139
+ bbox?: BBox;
140
+ label?: string;
141
+ zoom: ZoomDecision;
142
+ /** how long the action plays out after `tMs` (type/drag/scroll/hover/press);
143
+ * 0 for a click. The cursor parks and the zoom holds for this long. */
144
+ durationMs?: number;
145
+ /** typed text (kind=type), for editability */
146
+ text?: string;
147
+ /** chord pressed (kind=press), for editability */
148
+ keys?: string;
149
+ /** drag end point, video-px (kind=drag) */
150
+ to?: Pt;
151
+ /** drag polyline incl. ends, video-px (kind=drag) — the cursor path */
152
+ path?: Pt[];
153
+ /** drag stroke easing baked into the ink (kind=drag): "smooth" or "linear".
154
+ * The cursor replays it so it stays locked to the ink. Absent ⇒ linear. */
155
+ ease?: "linear" | "smooth";
156
+ };
157
+ type FramingConfig = {
158
+ /** video occupies this fraction of the frame at rest (inset for the backdrop) */
159
+ insetFrac: number;
160
+ cornerRadius: number;
161
+ shadow: {
162
+ color: string;
163
+ blur: number;
164
+ offset: Pt;
165
+ };
166
+ /** backdrop behind the framed video. `type` defaults to "gradient" (from→to);
167
+ * "solid" fills `from` only. `angle` (deg, CSS-like: 0 = upward) rotates the
168
+ * gradient; absent ⇒ the legacy top-left→bottom-right diagonal (pixel-identical). */
169
+ background: {
170
+ from: string;
171
+ to: string;
172
+ type?: "gradient" | "solid";
173
+ angle?: number;
174
+ };
175
+ };
176
+ type CursorConfig = {
177
+ /** Fallback travel duration (ms) when `travelWidthsPerSec` is unset/0. A FIXED
178
+ * duration makes cursor speed scale with distance (short=slow, long=fast),
179
+ * which reads inconsistent; prefer the distance-aware speed below. */
180
+ travelMs: number;
181
+ /** Distance-aware travel speed, as a fraction of the source video WIDTH per
182
+ * second (resolution-independent). A travel leg's duration is
183
+ * `clamp(distance / (widthsPerSec·videoWidth), travelMinMs, travelMaxMs)`, so
184
+ * the cursor holds a roughly CONSTANT on-screen speed regardless of distance —
185
+ * the premium-recorder feel (measured ~0.30 widths/s on the reference). Set 0
186
+ * to fall back to the fixed `travelMs`. */
187
+ travelWidthsPerSec: number;
188
+ /** Floor for a distance-aware travel (ms) so short hops aren't an instant snap. */
189
+ travelMinMs: number;
190
+ /** Ceiling for a distance-aware travel (ms) so a full-width jump stays a glide,
191
+ * not a multi-second crawl. */
192
+ travelMaxMs: number;
193
+ scale: number;
194
+ arcFrac: number;
195
+ arcMax: number;
196
+ rippleMs: number;
197
+ /** ms to hold a zoom after the action settles, before zooming back out */
198
+ holdMs: number;
199
+ /** ms for the zoom-OUT ramp (back to rest) */
200
+ zoomOutMs: number;
201
+ /** ms for the zoom-IN ramp (into a target). Decoupled from travelMs so the
202
+ * zoom can be slower/gentler than the cursor (a cinematic ~1s zoom). */
203
+ zoomInMs: number;
204
+ /** Easing for the zoom/pan stage ramps (scale + center together), as
205
+ * cubic-bezier control points. Absent ⇒ symmetric smootherstep — whose broad
206
+ * near-constant-velocity middle reads a bit linear, esp. on the zoom-OUT
207
+ * settle. A decel-biased curve gives a softer landing into rest. */
208
+ zoomEase?: [number, number, number, number];
209
+ /** Spring easing for the zoom/pan stage ramps, as a `bounce` amount ∈ [0,~0.6):
210
+ * 0 = critically damped (a soft physical ease-out), higher = more overshoot/
211
+ * snap (the "silky" settle a premium screen-recorder has; ~0.06 for zoom). When
212
+ * set, this WINS over `zoomEase` (see math.ts stageEasing). Absent ⇒ use
213
+ * `zoomEase`/smootherstep. The segment duration stays zoomInMs/zoomOutMs;
214
+ * bounce only shapes the curve. NB: large bounce can undershoot rest on the
215
+ * zoom-OUT (momentary backdrop dead-space) — keep it small for zoom. */
216
+ zoomSpring?: number;
217
+ /** ms to delay the synthetic cursor along a DRAG stroke, compensating for the
218
+ * capture pipeline latency: the captured ink appears ~this long after the pen
219
+ * actually moved, so without the delay the (exact-time) cursor leads the ink.
220
+ * Tune so the cursor tip sits on the ink front mid-stroke. */
221
+ dragLagMs: number;
222
+ /** easing for a travel move, as cubic-bezier control points [x1,y1,x2,y2].
223
+ * Default is a symmetric ease-in-out — measured from a reference recording, whose
224
+ * cursor accelerates and decelerates evenly (a slow start, fast middle, soft
225
+ * landing). Drag strokes ignore this (they ease the stroke in lockstep with
226
+ * the captured ink — see math.ts). */
227
+ travelEase: [number, number, number, number];
228
+ };
229
+ /** Camera motion blur (temporal supersampling — what a real shutter does). The
230
+ * renderer samples the composition camera at `samples` sub-times within each
231
+ * output frame and averages them, so a fast zoom/pan/cursor smears in the
232
+ * motion direction (a camera/shutter motion blur). It smears the
233
+ * backdrop-reveal on a zoom-OUT into a soft gradient instead of a hard
234
+ * single-frame pop. The captured video's frames repeat across sub-samples, so
235
+ * the recording's own content is NOT blurred — only the camera move + cursor. */
236
+ type MotionBlurConfig = {
237
+ /** sub-frames sampled per output frame. 1 ⇒ OFF (no supersampling, no cost). */
238
+ samples: number;
239
+ /** fraction of the frame interval the shutter is open (0..1). Blur strength;
240
+ * 0 ⇒ OFF. ~0.5 = a 180° shutter, 1 = 360°. */
241
+ shutter: number;
242
+ };
243
+ /** One caption window on a review copy: the pill reads `text` from `fromMs`
244
+ * (inclusive) to `toMs` (exclusive) on the composition timeline. */
245
+ type ReviewBadge = {
246
+ fromMs: number;
247
+ toMs: number;
248
+ text: string;
249
+ };
250
+ /** Render-time decoration for review copies and A/B variant reels: burned-in
251
+ * beat badges, a REVIEW watermark, and a per-variant corner label. Drawn by the
252
+ * scene in SCREEN space (fixed, outside the composition camera) so the text is
253
+ * legible at any zoom. This is a render input only — it is never written into
254
+ * the editable `*.composition.json` artifact (render strips it) and the
255
+ * validator ignores it. Text renders in the headless Chrome, so any script
256
+ * (incl. CJK) works without ffmpeg font filters. */
257
+ type ReviewDecor = {
258
+ /** top-right watermark, e.g. "REVIEW" — marks a copy as not-for-posting */
259
+ watermark?: string;
260
+ /** bottom-left caption pill, swapping per timeline window */
261
+ badges?: ReviewBadge[];
262
+ /** constant bottom-left variant label for A/B reels, e.g. "B · tight ×1.8" */
263
+ label?: string;
264
+ };
265
+ type TakeComposition = {
266
+ output: {
267
+ width: number;
268
+ height: number;
269
+ fps: number;
270
+ };
271
+ source: {
272
+ videoUrl: string;
273
+ videoWidth: number;
274
+ videoHeight: number;
275
+ viewport: {
276
+ w: number;
277
+ h: number;
278
+ };
279
+ };
280
+ framing: FramingConfig;
281
+ cursor: CursorConfig;
282
+ /** camera motion blur; absent ⇒ off (renders exactly as before). */
283
+ motionBlur?: MotionBlurConfig;
284
+ /** cursor start, video-px */
285
+ start: Pt;
286
+ events: CompEvent[];
287
+ durationMs: number;
288
+ /** render-time review decoration (badges/watermark/label); never persisted */
289
+ review?: ReviewDecor;
290
+ };
291
+ /** True when motion blur is configured to actually do something (so the OFF
292
+ * path stays byte-identical to the pre-motion-blur renderer). */
293
+ declare function motionBlurActive(mb: MotionBlurConfig | undefined): mb is MotionBlurConfig;
294
+ declare const DEFAULT_FRAMING: FramingConfig;
295
+ declare const DEFAULT_MOTION_BLUR: MotionBlurConfig;
296
+ declare const DEFAULT_CURSOR: CursorConfig; //#endregion
297
+ //#region src/presets.d.ts
298
+
299
+ //# sourceMappingURL=types.d.ts.map
300
+ declare const ZOOM_LEVELS: {
301
+ readonly light: 1.25;
302
+ readonly medium: 1.5;
303
+ readonly tight: 1.8;
304
+ readonly close: 2.2;
305
+ };
306
+ type ZoomLevelName = keyof typeof ZOOM_LEVELS;
307
+ /** Name a scale if it sits within tolerance of a preset; else null (custom). */
308
+ declare function zoomLevelName(scale: number, tol?: number): ZoomLevelName | null;
309
+ type MotionPreset = Pick<CursorConfig, "travelWidthsPerSec" | "holdMs" | "zoomInMs" | "zoomOutMs">;
310
+ declare const MOTION: Record<"calm" | "natural" | "brisk", MotionPreset>;
311
+ type MotionName = keyof typeof MOTION;
312
+ declare function motionName(cursor: CursorConfig): MotionName | null;
313
+ type LookPreset = Pick<FramingConfig, "background" | "cornerRadius" | "shadow">;
314
+ declare const LOOKS: Record<string, LookPreset>;
315
+ type LookName = keyof typeof LOOKS;
316
+ declare function lookName(framing: FramingConfig): string | null;
317
+ declare const FINISH: Record<"smooth" | "crisp" | "heavy", MotionBlurConfig | undefined>;
318
+ type FinishName = keyof typeof FINISH;
319
+ declare function finishName(mb: MotionBlurConfig | undefined): FinishName | null;
320
+
321
+ //#endregion
322
+ //#region src/ffmpeg.d.ts
323
+ //# sourceMappingURL=presets.d.ts.map
324
+ declare function resolveFfmpeg(): Promise<string>;
325
+ declare function resolveFfprobe(): Promise<string>;
326
+
327
+ //#endregion
328
+ //#region src/plan.d.ts
329
+ //# sourceMappingURL=ffmpeg.d.ts.map
330
+ type PlanOpts = {
331
+ output?: {
332
+ width?: number;
333
+ height?: number;
334
+ fps?: number;
335
+ };
336
+ framing?: Partial<FramingConfig>;
337
+ cursor?: Partial<CursorConfig>;
338
+ /** element should fill this fraction of the frame when zoomed (default 0.55) */
339
+ fillFrac?: number;
340
+ /** hard cap on zoom (default 1.5 — a gentle workhorse; lower than
341
+ * the old 2.0 reads more premium. Small targets still zoom, just not as hard;
342
+ * raise per-beat in the composition when a tiny element needs it.) */
343
+ maxScale?: number;
344
+ /** require fit-scale to exceed rest*this to bother zooming (default 1.3) */
345
+ zoomRatio?: number;
346
+ /** never zoom the first (orienting) action by default (Finding 1) */
347
+ zoomFirst?: boolean;
348
+ };
349
+ declare function planComposition(log: CaptureLog, opts?: PlanOpts): TakeComposition;
350
+
351
+ //#endregion
352
+ //#region src/render.d.ts
353
+ //# sourceMappingURL=plan.d.ts.map
354
+ type RenderTakeOpts = {
355
+ /** input capture video (webm or mp4) */
356
+ videoPath: string;
357
+ /** output polished mp4 path */
358
+ outPath: string;
359
+ /** provide a capture log (auto-planned) ... */
360
+ log?: CaptureLog;
361
+ /** ... or a ready-made composition (editable artifact) */
362
+ composition?: TakeComposition;
363
+ planOpts?: PlanOpts;
364
+ logProgress?: boolean;
365
+ /** Chrome binary for the headless render. Pass the same Chrome-for-Testing
366
+ * the capture path uses so a single browser serves both stages (no second
367
+ * download). revideo forwards this to puppeteer.launch's executablePath;
368
+ * if unset, revideo's bundled puppeteer resolves its own. */
369
+ chromePath?: string;
370
+ /** the capture log, for cross-checking that an edited composition didn't
371
+ * drift an action's capture-locked tMs (see validateComposition). Optional —
372
+ * the structural checks run regardless. */
373
+ captureLog?: CaptureLog;
374
+ /** skip the pre-render structural validation. Default false — we validate and
375
+ * refuse to render an errored composition (a render is expensive; catch a bad
376
+ * hand-edit in milliseconds instead). */
377
+ skipValidate?: boolean;
378
+ /** progress callback (0..1) forwarded from revideo's renderer. */
379
+ onProgress?: (progress: number) => void;
380
+ /** render only this window of the composition timeline, in SECONDS — the
381
+ * windowed-render path behind A/B variant reels (a 4s window instead of the
382
+ * whole take). With motion blur OFF, frames are identical to the same span
383
+ * of a full render (the timeline is deterministic). With blur active the
384
+ * content matches but not bit-exactly: the tmix shutter windows are phased
385
+ * from the CLIP start, and the first frame's trailing window is truncated.
386
+ * Forwarded to revideo's projectSettings.range. */
387
+ rangeSec?: [number, number];
388
+ /** write the editable `<out>.composition.json` sibling (default true). Review
389
+ * copies and A/B reels are disposable — they skip the sibling. */
390
+ writeCompositionSibling?: boolean;
391
+ };
392
+ declare function renderTake(opts: RenderTakeOpts): Promise<{
393
+ mp4Path: string;
394
+ compositionPath: string;
395
+ }>;
396
+
397
+ //#endregion
398
+ //#region src/validate.d.ts
399
+ //# sourceMappingURL=render.d.ts.map
400
+ type CompositionIssue = {
401
+ severity: "error" | "warn";
402
+ /** dotted/indexed field path, e.g. "events[3].zoom.scale" */
403
+ path: string;
404
+ message: string;
405
+ /** a concrete suggested correction the agent can apply */
406
+ fix?: string;
407
+ };
408
+ type ValidateOpts = {
409
+ /** soft ceiling on zoom scale — above it the pixels visibly soften (warn).
410
+ * Default 2.5 (the planner caps auto-zoom at 1.5; manual edits get headroom). */
411
+ maxScale?: number;
412
+ /** the ground-truth capture log. When given, action `tMs` is checked against
413
+ * it (capture-lock). Omit to skip that check. */
414
+ captureLog?: CaptureLog;
415
+ };
416
+ declare function validateComposition(comp: TakeComposition, opts?: ValidateOpts): CompositionIssue[];
417
+ /** Format issues for a human/agent log. Errors first. */
418
+ declare function formatIssues(issues: CompositionIssue[]): string;
419
+
420
+ //#endregion
421
+ //#region src/math.d.ts
422
+ //# sourceMappingURL=validate.d.ts.map
423
+ declare namespace math_d_exports {
424
+ export { StageKeyframes, bboxFitScale, buildLegs, buildStageKeyframes, clampCenter, cubicBezier, cursorPos, gradientEndpoints, isDragging, keyvalN, keyvalP, panEasing, restStageScale, smoother, springEase, stageEasing };
425
+ }
426
+ declare function smoother(t: number): number;
427
+ declare function cubicBezier(x1: number, y1: number, x2: number, y2: number): (x: number) => number;
428
+ declare function springEase(bounce: number): (p: number) => number;
429
+ declare function stageEasing(cursor: TakeComposition["cursor"]): (u: number) => number;
430
+ declare function panEasing(cursor: TakeComposition["cursor"]): (u: number) => number;
431
+ declare function gradientEndpoints(angleDeg: number | undefined, oW: number, oH: number): {
432
+ x0: number;
433
+ y0: number;
434
+ x1: number;
435
+ y1: number;
436
+ };
437
+ type KF<T> = [number, T];
438
+ declare function keyvalN(t: number, kfs: KF<number>[], ease?: (u: number) => number, easeDown?: (u: number) => number): number;
439
+ declare function keyvalP(t: number, kfs: KF<Pt>[], ease?: (u: number) => number): Pt;
440
+ /**
441
+ * Scale (absolute, video-px → output-px) that fits `bbox` into `fillFrac`
442
+ * of the output frame, capped at `maxScale` and floored at `restScale`.
443
+ * Wide/long elements naturally get a gentler scale because the limiting
444
+ * dimension dominates min().
445
+ */
446
+ declare function bboxFitScale(bbox: BBox, outW: number, outH: number, fillFrac: number, maxScale: number, restScale: number): number;
447
+ /** Stage scale at rest: video inset into the frame (leaves backdrop margin). */
448
+ declare function restStageScale(videoW: number, videoH: number, outW: number, outH: number, insetFrac: number): number;
449
+ /**
450
+ * Clamp a desired video-px center so the scaled video still covers the output
451
+ * frame (the viewport crop stays inside the source video) when zoomed in. When
452
+ * the content does not cover an axis (zoomed out / inset), centre that axis.
453
+ *
454
+ * In the composition-camera model the whole composition
455
+ * (backdrop + inset screen) is zoomed by one camera; this keeps the camera crop
456
+ * within the screen so a zoom fills the frame (no backdrop margin) without ever
457
+ * panning past the recording's edge.
458
+ */
459
+ declare function clampCenter(center: Pt, scale: number, videoW: number, videoH: number, outW: number, outH: number): Pt;
460
+ type StageKeyframes = {
461
+ z: KF<number>[];
462
+ c: KF<Pt>[];
463
+ T: number;
464
+ };
465
+ declare function buildStageKeyframes(comp: TakeComposition): StageKeyframes;
466
+ type Leg = {
467
+ t0: number;
468
+ t1: number;
469
+ a: Pt;
470
+ b: Pt;
471
+ drag?: boolean;
472
+ path?: Pt[];
473
+ ease?: "linear" | "smooth";
474
+ };
475
+ declare function buildLegs(comp: TakeComposition): Leg[];
476
+ declare function cursorPos(t: number, legs: Leg[], comp: TakeComposition): Pt;
477
+ /** True while a drag is mid-stroke (button held) — for the pressed cursor. */
478
+ declare function isDragging(t: number, legs: Leg[]): boolean;
479
+
480
+ //#endregion
481
+ export { BBox, CaptureClick, CaptureDrag, CaptureEvent, CaptureEventBase, CaptureHover, CaptureLog, CapturePress, CaptureScroll, CaptureType, CompEvent, CompositionIssue, CursorConfig, DEFAULT_CURSOR, DEFAULT_FRAMING, DEFAULT_MOTION_BLUR, FINISH, FinishName, FramingConfig, LOOKS, LookName, LookPreset, MOTION, MotionBlurConfig, MotionName, MotionPreset, PlanOpts, Pt, RenderTakeOpts, ReviewBadge, ReviewDecor, TakeComposition, ValidateOpts, ZOOM_LEVELS, ZoomDecision, ZoomIntent, ZoomLevelName, finishName, formatIssues, lookName, math_d_exports as math, motionBlurActive, motionName, planComposition, renderTake, resolveFfmpeg, resolveFfprobe, validateComposition, zoomLevelName };
482
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/presets.ts","../src/ffmpeg.ts","../src/plan.ts","../src/render.ts","../src/validate.ts","../src/math.ts"],"sourcesContent":null,"mappings":"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"}