@scenerok/sdk 0.8.0 → 0.10.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.
Files changed (43) hide show
  1. package/README.md +63 -1
  2. package/dist/describe.d.ts +87 -0
  3. package/dist/describe.d.ts.map +1 -0
  4. package/dist/describe.js +210 -0
  5. package/dist/duration.d.ts +9 -3
  6. package/dist/duration.d.ts.map +1 -1
  7. package/dist/duration.js +22 -5
  8. package/dist/frame-rate.d.ts +30 -0
  9. package/dist/frame-rate.d.ts.map +1 -0
  10. package/dist/frame-rate.js +73 -0
  11. package/dist/index.d.ts +9 -6
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +7 -4
  14. package/dist/ir-builder.d.ts +61 -8
  15. package/dist/ir-builder.d.ts.map +1 -1
  16. package/dist/ir-builder.js +714 -256
  17. package/dist/ir.d.ts +203 -2
  18. package/dist/ir.d.ts.map +1 -1
  19. package/dist/ir.js +4 -2
  20. package/dist/media.d.ts +49 -5
  21. package/dist/media.d.ts.map +1 -1
  22. package/dist/media.js +223 -33
  23. package/dist/motion-tracks.d.ts +10 -0
  24. package/dist/motion-tracks.d.ts.map +1 -0
  25. package/dist/motion-tracks.js +150 -0
  26. package/dist/motion.d.ts +34 -0
  27. package/dist/motion.d.ts.map +1 -1
  28. package/dist/motion.js +51 -11
  29. package/dist/plugins/invoke.d.ts.map +1 -1
  30. package/dist/plugins/invoke.js +5 -2
  31. package/dist/timeline.d.ts +3 -0
  32. package/dist/timeline.d.ts.map +1 -1
  33. package/dist/timeline.js +101 -41
  34. package/dist/types.d.ts +214 -28
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js +8 -9
  37. package/package.json +2 -2
  38. package/skills/scenerok/SKILL.md +5 -2
  39. package/skills/scenerok/references/catalog-index.json +1 -1
  40. package/skills/scenerok/references/editing-actions.md +43 -1
  41. package/skills/scenerok/references/sdk-guide.md +149 -49
  42. package/skills/scenerok/references/vidscript-guide.md +49 -13
  43. package/skills/scenerok/references/vidscript-strict.md +1 -1
package/dist/timeline.js CHANGED
@@ -1,29 +1,60 @@
1
- import { isAutoPlayheadKey, toSeconds } from './duration.js';
2
- import { assertSchedulable, bindTransitions, createIrBuilder, inferAutoDuration, scheduleAt, setGrid, } from './ir-builder.js';
3
- const INTERNAL = Symbol('scenerok.timeline.internal');
4
- function parseTimeKey(key) {
1
+ import { Duration, isAutoPlayheadKey, toSeconds } from './duration.js';
2
+ import { exactFpsOf } from './frame-rate.js';
3
+ import { assertSchedulable, bindTransitions, hostCanvas, inferAutoDuration, lowerTimeline, TIMELINE_RECORD, } from './ir-builder.js';
4
+ import { composeCrop, makeClipEffect, makeMask } from './media.js';
5
+ function fpsOf(record) {
6
+ return record.options.fps ?? hostCanvas().fps;
7
+ }
8
+ function parseTimeKey(key, fps) {
5
9
  if (isAutoPlayheadKey(key))
6
10
  return 'auto';
7
11
  if (typeof key === 'symbol') {
8
12
  throw new TypeError('Timeline keys must be numbers, Duration, time strings, or "-"');
9
13
  }
10
- return toSeconds(key);
14
+ // Property keys arrive as strings: `t[1.5]` is "1.5", `t[s(2)]` is "2s".
15
+ return toSeconds(key, fps);
11
16
  }
12
- function createRangeBinder(internal, start) {
13
- return new Proxy({}, {
14
- set(_target, endKey, value) {
15
- assertSchedulable(value);
16
- const endParsed = parseTimeKey(endKey);
17
- if (endParsed === 'auto') {
18
- throw new TypeError('End time cannot be auto-playhead "-"');
19
- }
20
- scheduleAt(internal.state, start, endParsed, value);
21
- return true;
17
+ function lower(record) {
18
+ const state = lowerTimeline(record, hostCanvas());
19
+ // Bind transition fromId/toId now that all clips are present.
20
+ bindTransitions(state.ir);
21
+ // JSON clone — works in isolated-vm (no structuredClone) and strips non-JSON.
22
+ return JSON.parse(JSON.stringify(state.ir));
23
+ }
24
+ /** The group-placement methods, on a timeline or on a view of one. */
25
+ function viewMethods(timeline, current) {
26
+ const next = (patch) => makeView(timeline, { ...current, ...patch });
27
+ return {
28
+ place: (opts) => next({ placement: { ...current.placement, ...opts } }),
29
+ opacity: (value) => next({ placement: { ...current.placement, opacity: value } }),
30
+ resize: (width, height) => next({ placement: { ...current.placement, width, height } }),
31
+ filter: (name, params) => next({ effects: [...current.effects, makeClipEffect(name, params)] }),
32
+ crop: (x, y, width, height) => next({ cropRect: composeCrop(current.cropRect, x, y, width, height) }),
33
+ mask: (matte, options) => {
34
+ if (current.maskSpec)
35
+ throw new Error('mask() is already applied to this value; one matte per value');
36
+ return next({ maskSpec: makeMask(matte, options) });
22
37
  },
23
- get() {
24
- return undefined;
38
+ };
39
+ }
40
+ function makeView(timeline, current) {
41
+ return {
42
+ __sdk: true,
43
+ kind: 'timeline',
44
+ timeline,
45
+ placement: { ...current.placement },
46
+ effects: [...current.effects],
47
+ ...(current.cropRect ? { cropRect: current.cropRect } : {}),
48
+ ...(current.maskSpec ? { maskSpec: current.maskSpec } : {}),
49
+ get duration() {
50
+ return timeline.duration;
25
51
  },
26
- });
52
+ get options() {
53
+ return timeline.options;
54
+ },
55
+ toIR: () => timeline.toIR(),
56
+ ...viewMethods(timeline, current),
57
+ };
27
58
  }
28
59
  /**
29
60
  * Create a timeline. Schedule with dual-index assignment:
@@ -36,60 +67,86 @@ function createRangeBinder(internal, start) {
36
67
  * t.push(text('Tail'))
37
68
  * return t.toIR()
38
69
  * ```
70
+ *
71
+ * Without `width`/`height`/`fps` it takes the host canvas (the importing
72
+ * VidScript's output, or its parent's when nested), else 1080×1920 at 30 fps.
39
73
  */
40
74
  export function timeline(options = {}) {
41
- const internal = {
42
- state: createIrBuilder(options),
43
- options: { ...options },
75
+ const record = { options: { ...options }, grid: null, entries: [] };
76
+ const cursors = { visual: 0, audio: 0 };
77
+ const schedule = (start, end, value) => {
78
+ if (end < start)
79
+ throw new RangeError(`Invalid range: end (${end}) < start (${start})`);
80
+ record.entries.push({ start, end, value });
81
+ if (value.kind === 'audio')
82
+ cursors.audio = Math.max(cursors.audio, end);
83
+ else if (value.kind !== 'marker' && value.kind !== 'filter' && value.kind !== 'shader') {
84
+ cursors.visual = Math.max(cursors.visual, end);
85
+ }
44
86
  };
45
87
  const api = {
46
88
  __sdk: true,
47
89
  kind: 'timeline',
48
- options: internal.options,
90
+ options: record.options,
91
+ [TIMELINE_RECORD]: record,
49
92
  get duration() {
50
- return internal.state.ir.duration;
93
+ return lower(record).duration;
51
94
  },
52
95
  get length() {
53
- return internal.state.ir.duration;
96
+ return lower(record).duration;
54
97
  },
55
98
  grid(spec) {
56
- setGrid(internal.state, spec);
99
+ record.grid = spec;
57
100
  return proxy;
58
101
  },
59
102
  range(start, end, value) {
60
103
  assertSchedulable(value);
61
- scheduleAt(internal.state, toSeconds(start), toSeconds(end), value);
104
+ const fps = fpsOf(record);
105
+ schedule(toSeconds(start, fps), toSeconds(end, fps), value);
62
106
  return proxy;
63
107
  },
64
108
  push(value, duration) {
65
109
  assertSchedulable(value);
66
- const start = value.kind === 'audio'
67
- ? internal.state.audioCursor
68
- : internal.state.visualCursor;
69
- const span = inferAutoDuration(value, duration);
70
- scheduleAt(internal.state, start, start + span, value);
110
+ const start = value.kind === 'audio' ? cursors.audio : cursors.visual;
111
+ schedule(start, start + inferAutoDuration(value, duration, fpsOf(record)), value);
71
112
  return proxy;
72
113
  },
114
+ frames(count) {
115
+ return new Duration(count / exactFpsOf(fpsOf(record)));
116
+ },
73
117
  toIR() {
74
- // Bind transition fromId/toId now that all clips are present (incl. nested remaps).
75
- bindTransitions(internal.state.ir);
76
- // JSON clone — works in isolated-vm (no structuredClone) and strips non-JSON.
77
- return JSON.parse(JSON.stringify(internal.state.ir));
118
+ return lower(record);
78
119
  },
120
+ ...viewMethods(null, { placement: {}, effects: [] }),
79
121
  };
80
122
  const proxy = new Proxy(api, {
81
123
  get(target, prop, receiver) {
82
- if (prop === INTERNAL)
83
- return internal;
84
124
  if (prop in target || typeof prop === 'symbol') {
85
125
  return Reflect.get(target, prop, receiver);
86
126
  }
87
- const startParsed = parseTimeKey(prop);
127
+ // Times start with a digit (`3`, `3s`, `1:30`, `48f`, `00:00:01:00`) or are `-`.
128
+ // Anything else (`then` when awaited, `toJSON`) is not a time and not here.
129
+ if (!/^[\d.-]/.test(prop))
130
+ return undefined;
131
+ const startParsed = parseTimeKey(prop, fpsOf(record));
88
132
  if (startParsed === 'auto') {
89
133
  // `t['-'] = value` — auto-append
90
134
  return undefined;
91
135
  }
92
- return createRangeBinder(internal, startParsed);
136
+ return new Proxy({}, {
137
+ set(_target, endKey, value) {
138
+ assertSchedulable(value);
139
+ const endParsed = parseTimeKey(endKey, fpsOf(record));
140
+ if (endParsed === 'auto') {
141
+ throw new TypeError('End time cannot be auto-playhead "-"');
142
+ }
143
+ schedule(startParsed, endParsed, value);
144
+ return true;
145
+ },
146
+ get() {
147
+ return undefined;
148
+ },
149
+ });
93
150
  },
94
151
  set(target, prop, value, receiver) {
95
152
  if (prop in api && prop !== 'duration' && prop !== 'length') {
@@ -104,14 +161,17 @@ export function timeline(options = {}) {
104
161
  throw new TypeError('Use t[start][end] = value, t.range(start, end, value), or t["-"] = value / t.push(value)');
105
162
  },
106
163
  has(target, prop) {
107
- return prop in target || prop === INTERNAL;
164
+ return prop in target;
108
165
  },
109
166
  });
167
+ // The view methods need the proxy (not `api`) as their timeline.
168
+ Object.assign(api, viewMethods(proxy, { placement: {}, effects: [] }));
110
169
  return proxy;
111
170
  }
112
171
  export function isTimeline(value) {
113
172
  return (typeof value === 'object'
114
173
  && value !== null
115
174
  && value.__sdk === true
116
- && value.kind === 'timeline');
175
+ && value.kind === 'timeline'
176
+ && !('placement' in value));
117
177
  }
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { IRAnimation, IREffect, IRMotionTrack, IRTextStyle } from './ir.js';
1
+ import type { IRCrop, IREffect, IRMaskMode, IRMotionTrack, IRAnimation, IRTextStyle } from './ir.js';
2
2
  import type { Duration, TimeInput } from './duration.js';
3
3
  import type { GridSpec } from './grid.js';
4
- export type SdkKind = 'video' | 'text' | 'audio' | 'filter' | 'shader' | 'transition' | 'timeline' | 'animation';
4
+ export type SdkKind = 'video' | 'image' | 'text' | 'audio' | 'solid' | 'gap' | 'marker' | 'filter' | 'shader' | 'transition' | 'timeline' | 'animation';
5
5
  export interface SdkNodeBase {
6
6
  readonly __sdk: true;
7
7
  readonly kind: SdkKind;
@@ -12,39 +12,147 @@ export interface AnimationDescriptor {
12
12
  type: string;
13
13
  from: Record<string, unknown>;
14
14
  to: Record<string, unknown>;
15
+ /** Seconds; 0 spans the placement window. */
15
16
  duration: number;
16
17
  align?: 'start' | 'end';
17
18
  easing?: string;
18
19
  loop?: boolean;
19
20
  plugin?: string;
20
21
  }
21
- export interface VideoOptions {
22
- width?: number;
23
- height?: number;
22
+ /** Blend modes over the picture below (`blend:` in VidScript). Aliases like `soft-light` also work. */
23
+ export type BlendMode = 'normal' | 'multiply' | 'screen' | 'overlay' | 'difference' | 'add' | 'subtract' | 'darken' | 'lighten';
24
+ /** `motion_blur:` — `true` for the defaults (shutter 180°, 8 samples). */
25
+ export type MotionBlurOption = boolean | {
26
+ shutter?: number;
27
+ samples?: number;
28
+ };
29
+ /**
30
+ * The placement property set every picture value shares — VidScript's
31
+ * `[time] = value, x: …, opacity: …, blend: …`.
32
+ */
33
+ export interface PlacementOptions {
34
+ /** Top-left in output pixels. */
24
35
  x?: number;
25
36
  y?: number;
37
+ /** Drawn size in output pixels (default: the canvas). */
38
+ width?: number;
39
+ height?: number;
40
+ opacity?: number;
41
+ /** Constant rotation in degrees over the window. */
42
+ rotation?: number;
43
+ /** Rounded-corner radius in output pixels. */
44
+ radius?: number;
45
+ /** Four corner points in output pixels, TL → TR → BR → BL. */
46
+ corners?: [number, number][];
47
+ /** Named grid area (`t.grid(...)` or the built-in preset). Explicit x/y/width/height win. */
48
+ area?: string;
49
+ /** Blend over what is already on the timeline in this window. */
50
+ blend?: BlendMode | string;
51
+ /** Blur this item's own `animate` motion by sub-frame accumulation. */
52
+ motionBlur?: MotionBlurOption;
53
+ /** `false` skips the placement (the window still advances the playhead). */
54
+ enabled?: boolean;
55
+ animate?: AnimationDescriptor | AnimationDescriptor[];
56
+ }
57
+ /** Edits recorded by media methods (`clip.trim(1, 3).speed(2)`); placement applies them. */
58
+ export interface ClipEdits {
59
+ trimStart?: number;
60
+ trimEnd?: number;
61
+ speed?: number;
62
+ loop?: number;
26
63
  opacity?: number;
64
+ width?: number;
65
+ height?: number;
66
+ /** Per-clip grades (`clip.filter('sepia')`). */
67
+ effects?: IREffect[];
68
+ /** Source rectangle in source pixels (`clip.crop(...)`). */
69
+ crop?: IRCrop;
70
+ /** A matte over this value (`clip.mask(matte)`); placing it draws a group. */
71
+ mask?: MaskSpec;
72
+ }
73
+ export interface MaskSpec {
74
+ matte: PictureNode;
75
+ mode: IRMaskMode;
76
+ }
77
+ export interface MaskOptions {
78
+ /** `alpha` (default) multiplies by the matte's alpha, `luma` by its brightness, `inverted` by 1 − alpha. */
79
+ mode?: IRMaskMode;
80
+ }
81
+ export interface VideoOptions extends PlacementOptions {
27
82
  trimStart?: TimeInput;
28
83
  trimEnd?: TimeInput;
29
84
  speed?: number;
30
85
  loop?: number;
31
- /** Explicit duration in seconds when the asset cannot be probed yet. */
86
+ /** Media length in seconds. Known lengths place for as long as the clip plays. */
32
87
  duration?: TimeInput;
33
- animate?: AnimationDescriptor | AnimationDescriptor[];
88
+ /** Interpret the footage at this frame rate (`input a = "x.mp4", rate: 23.976`). */
89
+ rate?: number;
90
+ /** Colour space of the source / of this clip's output (`input_colorspace:` / `output_colorspace:`). */
91
+ inputColorspace?: string;
92
+ outputColorspace?: string;
93
+ /** The clip's own sound plays with it (generated clips). Audio files are placed with `audio()`. */
94
+ nativeAudio?: boolean;
95
+ /** Level of the clip's own sound (`volume:` on the placement). */
96
+ volume?: number;
34
97
  }
35
- export interface VideoClip extends SdkNodeBase {
98
+ export interface ImageSequenceOptions extends Omit<VideoOptions, 'rate' | 'duration'> {
99
+ /** Number in the first frame's file name (default 1). */
100
+ first?: number;
101
+ /** How many numbered frames exist from `first`. */
102
+ count: number;
103
+ /** Frames per second of the sequence (default: the timeline fps). */
104
+ rate?: number;
105
+ }
106
+ export type ImageOptions = PlacementOptions;
107
+ /** Methods shared by video and image values. Every method returns a copy. */
108
+ export interface MediaMethods<Self> {
109
+ /** Keep source `start`..`end`. A second trim is relative to the first. */
110
+ trim(start: TimeInput, end?: TimeInput): Self;
111
+ speed(factor: number): Self;
112
+ loop(count: number): Self;
113
+ /** Drawn size in output pixels. */
114
+ resize(width: number, height: number): Self;
115
+ opacity(value: number): Self;
116
+ /** Grade this value only (a pointwise colour filter: `sepia`, `cdl`, …). */
117
+ filter(name: string, params?: Record<string, number | string>): Self;
118
+ /** Part of the source to show, in source pixels from the top-left. A second crop is relative to the first. */
119
+ crop(x: number, y: number, width: number, height: number): Self;
120
+ /** Multiply the picture by a matte (any picture value). */
121
+ mask(matte: PictureNode, options?: MaskOptions): Self;
122
+ animate(anim: AnimationDescriptor | AnimationDescriptor[]): Self;
123
+ /** Copy with placement options merged. */
124
+ with(opts: Partial<VideoOptions>): Self;
125
+ }
126
+ export interface VideoClip extends SdkNodeBase, MediaMethods<VideoClip> {
36
127
  kind: 'video';
37
128
  source: string;
38
129
  options: VideoOptions;
39
- /** Resolved or declared duration in seconds. */
40
- duration: number;
130
+ edits: ClipEdits;
131
+ /** Set for a numbered-frame source (`imageSequence(...)`). */
132
+ sequence?: {
133
+ first: number;
134
+ count: number;
135
+ rate?: number;
136
+ };
137
+ /** Media length in seconds, when declared or probed. */
138
+ readonly mediaDuration: number | undefined;
139
+ /** How long it plays: trim range ÷ speed × loop (5 s when nothing is known). */
140
+ readonly duration: number;
141
+ animations: AnimationDescriptor[];
142
+ }
143
+ export interface ImageClip extends SdkNodeBase, MediaMethods<ImageClip> {
144
+ kind: 'image';
145
+ source: string;
146
+ options: VideoOptions;
147
+ edits: ClipEdits;
148
+ /** A still has no length; it fills its window (3 s when appended). */
149
+ readonly duration: number;
41
150
  animations: AnimationDescriptor[];
42
- animate(anim: AnimationDescriptor | AnimationDescriptor[]): VideoClip;
43
- with(opts: Partial<VideoOptions>): VideoClip;
44
151
  }
45
- export interface TextOptions {
152
+ export interface TextOptions extends Omit<PlacementOptions, 'x' | 'y' | 'radius' | 'corners' | 'motionBlur' | 'width' | 'height'> {
46
153
  font?: string;
47
154
  size?: number;
155
+ minSize?: number;
48
156
  color?: string;
49
157
  stroke?: string;
50
158
  strokeWidth?: number;
@@ -52,15 +160,13 @@ export interface TextOptions {
52
160
  italic?: boolean;
53
161
  x?: number | string;
54
162
  y?: number | string;
55
- rotation?: number;
56
- opacity?: number;
57
163
  align?: 'left' | 'center' | 'right';
58
164
  lineHeight?: number;
59
165
  letterSpacing?: number;
60
166
  position?: string;
61
- area?: string;
62
167
  fit?: IRTextStyle['fit'];
63
168
  overflow?: IRTextStyle['overflow'];
169
+ safeArea?: number | string;
64
170
  maxWidth?: number | string;
65
171
  maxHeight?: number | string;
66
172
  maxLines?: number;
@@ -69,7 +175,8 @@ export interface TextOptions {
69
175
  shadowBlur?: number;
70
176
  shadowOffsetX?: number;
71
177
  shadowOffsetY?: number;
72
- animate?: AnimationDescriptor | AnimationDescriptor[];
178
+ /** Per-token reveal for `typewriter`: `word` or `char`. */
179
+ stagger?: 'word' | 'char';
73
180
  }
74
181
  export interface TextLayer extends SdkNodeBase {
75
182
  kind: 'text';
@@ -83,17 +190,53 @@ export interface AudioOptions {
83
190
  volume?: number;
84
191
  fadeIn?: TimeInput;
85
192
  fadeOut?: TimeInput;
193
+ /** Length in seconds when the file cannot be probed. */
86
194
  duration?: TimeInput;
195
+ /** Source in-point: playback starts this far into the file (`trim_start:`). */
196
+ trimStart?: TimeInput;
197
+ /** Stereo placement in [-1, 1]. */
198
+ pan?: number;
199
+ /** Duck this track while another plays (its source path, or the track). */
200
+ duckUnder?: string | AudioTrack;
201
+ /** `ebu-r128` loudness normalization. */
202
+ loudness?: 'ebu-r128';
203
+ /** @deprecated Use `loudness: 'ebu-r128'`. */
87
204
  loudnessNormalization?: 'ebu-r128';
88
205
  targetLufs?: number;
206
+ /** Gain automation (`volumeRamp(0, 1, '2s')`). */
207
+ animate?: AnimationDescriptor | AnimationDescriptor[];
89
208
  }
90
209
  export interface AudioTrack extends SdkNodeBase {
91
210
  kind: 'audio';
92
211
  source: string;
93
212
  options: AudioOptions;
213
+ /** Seconds this track plays when declared, probed, or trimmed; undefined when unknown. */
214
+ readonly mediaDuration: number | undefined;
215
+ /** Seconds this track plays (5 s when nothing is known). */
94
216
  duration: number;
217
+ /** Keep source `start`..`end`; a second trim is relative to the first. */
218
+ trim(start: TimeInput, end?: TimeInput): AudioTrack;
95
219
  with(opts: Partial<AudioOptions>): AudioTrack;
96
220
  }
221
+ export type SolidOptions = Omit<PlacementOptions, 'rotation' | 'motionBlur'>;
222
+ /** A flat-colour rectangle (`solid("#101820")`). Places like a clip; works as a shape matte. */
223
+ export interface SolidNode extends SdkNodeBase {
224
+ kind: 'solid';
225
+ color: string;
226
+ options: SolidOptions;
227
+ animate(anim: AnimationDescriptor | AnimationDescriptor[]): SolidNode;
228
+ with(opts: Partial<SolidOptions>): SolidNode;
229
+ }
230
+ /** A transparent gap (`gap()`): occupies its window, draws nothing. */
231
+ export interface GapNode extends SdkNodeBase {
232
+ kind: 'gap';
233
+ }
234
+ /** A named instant (`marker("act 2")`). Timeline data, never rendered. */
235
+ export interface MarkerNode extends SdkNodeBase {
236
+ kind: 'marker';
237
+ name: string;
238
+ metadata?: Record<string, unknown>;
239
+ }
97
240
  export interface FilterEffect extends SdkNodeBase {
98
241
  kind: 'filter';
99
242
  name: string;
@@ -112,6 +255,10 @@ export interface TransitionOptions {
112
255
  mode?: string;
113
256
  /** Override catalog default duration (0.6s) for `push` / auto-append. */
114
257
  duration?: TimeInput;
258
+ /** Handle: source seconds the incoming clip reads before its in-point. */
259
+ inOffset?: TimeInput;
260
+ /** Handle: source seconds the outgoing clip reads past its out-point. */
261
+ outOffset?: TimeInput;
115
262
  width?: number;
116
263
  height?: number;
117
264
  x?: number | string;
@@ -129,34 +276,72 @@ export interface TransitionEffect extends SdkNodeBase {
129
276
  duration: number;
130
277
  with(opts: Partial<TransitionOptions>): TransitionEffect;
131
278
  }
132
- export type Schedulable = VideoClip | TextLayer | AudioTrack | FilterEffect | ShaderEffect | TransitionEffect | TimelineLike;
279
+ /** Placement of a timeline as a whole: its picture as one item (an `IRGroup`). */
280
+ export type TimelinePlacementOptions = Omit<PlacementOptions, 'animate'> & {
281
+ animate?: AnimationDescriptor | AnimationDescriptor[];
282
+ };
283
+ /** Methods that treat a timeline's picture as one unit. Each returns a placement view. */
284
+ export interface TimelineValueMethods {
285
+ /** Place with properties: the timeline draws as one group. */
286
+ place(opts: TimelinePlacementOptions): TimelineView;
287
+ opacity(value: number): TimelineView;
288
+ resize(width: number, height: number): TimelineView;
289
+ /** Grade this timeline's picture only. */
290
+ filter(name: string, params?: Record<string, number | string>): TimelineView;
291
+ crop(x: number, y: number, width: number, height: number): TimelineView;
292
+ mask(matte: PictureNode, options?: MaskOptions): TimelineView;
293
+ }
294
+ /** A timeline with group placement recorded (`inner.opacity(0.5)`). */
295
+ export interface TimelineView extends SdkNodeBase, TimelineValueMethods {
296
+ kind: 'timeline';
297
+ readonly timeline: TimelineLike;
298
+ readonly placement: TimelinePlacementOptions;
299
+ readonly effects: IREffect[];
300
+ readonly cropRect?: IRCrop;
301
+ readonly maskSpec?: MaskSpec;
302
+ readonly duration: number;
303
+ readonly options: TimelineOptions;
304
+ toIR(): import('./ir.js').IRTimeline;
305
+ }
306
+ /** Anything that draws a picture: usable as a placement, a matte, or a timeline item. */
307
+ export type PictureNode = VideoClip | ImageClip | TextLayer | SolidNode | TimelineLike | TimelineView;
308
+ export type Schedulable = VideoClip | ImageClip | TextLayer | AudioTrack | SolidNode | GapNode | MarkerNode | FilterEffect | ShaderEffect | TransitionEffect | TimelineLike | TimelineView;
309
+ export interface OutputOptions {
310
+ path?: string;
311
+ format?: string;
312
+ codec?: string;
313
+ bitrate?: string;
314
+ resolution?: string;
315
+ fps?: number;
316
+ /** Timecode of the first frame, `HH:MM:SS:FF` (non-drop-frame). */
317
+ startTimecode?: string;
318
+ /** Draw the running timecode onto the picture. */
319
+ burnIn?: 'timecode';
320
+ }
133
321
  export interface TimelineOptions {
322
+ /** Canvas size. Defaults to the host canvas when imported into VidScript, else 1080×1920. */
134
323
  width?: number;
135
324
  height?: number;
325
+ /** Frame rate; NTSC rates (23.976, 29.97, …) get an exact `timeBase`. */
136
326
  fps?: number;
137
327
  background?: string;
138
- output?: {
139
- path?: string;
140
- format?: string;
141
- codec?: string;
142
- bitrate?: string;
143
- resolution?: string;
144
- fps?: number;
145
- };
328
+ output?: OutputOptions;
146
329
  /** Optional name for nested timeline metadata. */
147
330
  name?: string;
148
331
  }
149
- export interface TimelineLike extends SdkNodeBase {
332
+ export interface TimelineLike extends SdkNodeBase, TimelineValueMethods {
150
333
  kind: 'timeline';
151
334
  readonly options: TimelineOptions;
152
335
  /** Visual playhead (seconds) after last scheduled visual item. */
153
336
  readonly duration: number;
154
337
  /** Alias used in plan examples (`scene1.length`). */
155
338
  readonly length: number;
156
- /** Declare CSS-grid named regions for `area:` text placement. */
339
+ /** Declare CSS-grid named regions for `area:` placement. */
157
340
  grid(spec: GridSpec): this;
158
341
  push(value: Schedulable, duration?: TimeInput): this;
159
342
  range(start: TimeInput, end: TimeInput, value: Schedulable): this;
343
+ /** `n` frames at this timeline's fps (exact for NTSC). */
344
+ frames(count: number): Duration;
160
345
  toIR(): import('./ir.js').IRTimeline;
161
346
  }
162
347
  export type TimeKey = TimeInput | '-';
@@ -173,5 +358,6 @@ export type BuiltMotion = IRMotionTrack[];
173
358
  export type BuiltAnimations = IRAnimation[];
174
359
  export declare function isSdkNode(value: unknown): value is SdkNodeBase;
175
360
  export declare function isSchedulable(value: unknown): value is Schedulable;
361
+ export declare function isPictureNode(value: unknown): value is PictureNode;
176
362
  export type { Duration };
177
363
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,MAAM,OAAO,GACf,OAAO,GACP,MAAM,GACN,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,YAAY,GACZ,UAAU,GACV,WAAW,CAAC;AAEhB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,GAAG,SAAS,CAAC;IACtE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;CAC9C;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,GAAG,SAAS,CAAC;IACtE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,qBAAqB,CAAC,EAAE,UAAU,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,UAAU,CAAC;CAC/C;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,IAAI,EAAE,YAAY,CAAC;IACnB,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,gBAAgB,CAAC;CAC1D;AAED,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,SAAS,GACT,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACrD,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAClE,IAAI,IAAI,OAAO,SAAS,EAAE,UAAU,CAAC;CACtC;AAED,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC;AAEtC,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;CAC1D;AAED,oFAAoF;AACpF,MAAM,WAAW,OAAO;IACtB,aAAa,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzD,YAAY,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;AACnC,MAAM,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;AAC1C,MAAM,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;AAE5C,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAE9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAWlE;AAED,YAAY,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,14 +1,13 @@
1
1
  export function isSdkNode(value) {
2
2
  return typeof value === 'object' && value !== null && value.__sdk === true;
3
3
  }
4
+ const SCHEDULABLE_KINDS = new Set([
5
+ 'video', 'image', 'text', 'audio', 'solid', 'gap', 'marker', 'filter', 'shader', 'transition', 'timeline',
6
+ ]);
4
7
  export function isSchedulable(value) {
5
- if (!isSdkNode(value))
6
- return false;
7
- return (value.kind === 'video'
8
- || value.kind === 'text'
9
- || value.kind === 'audio'
10
- || value.kind === 'filter'
11
- || value.kind === 'shader'
12
- || value.kind === 'transition'
13
- || value.kind === 'timeline');
8
+ return isSdkNode(value) && SCHEDULABLE_KINDS.has(value.kind);
9
+ }
10
+ const PICTURE_KINDS = new Set(['video', 'image', 'text', 'solid', 'timeline']);
11
+ export function isPictureNode(value) {
12
+ return isSdkNode(value) && PICTURE_KINDS.has(value.kind);
14
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scenerok/sdk",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "TypeScript-first SceneRok authoring SDK — build IRTimeline for complex agent-authored scenes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "prebuild": "node ../../scripts/copy-scenerok-skill.mjs .",
45
45
  "build": "tsc -p tsconfig.json",
46
46
  "dev": "tsc --watch",
47
- "test": "node --import tsx --test src/**/*.test.ts"
47
+ "test": "node --import tsx --test 'src/**/*.test.ts'"
48
48
  },
49
49
  "keywords": [
50
50
  "scenerok",
@@ -23,8 +23,11 @@ validate it, render it, and check the rendered file.
23
23
  | Use for | Promos, reels, templates, and every editing action: masks, blends, crops, speed ramps, ducking, LUTs, timecode | Timelines built by code: loops over data, computed timing across many clips |
24
24
  | Start with | [vidscript-strict.md](references/vidscript-strict.md) | [sdk-guide.md](references/sdk-guide.md) |
25
25
 
26
- The SDK has no masks, blends, crops, ducking, or delivery settings. When a
27
- scene needs both, write it in VidScript and `import` the SDK scene into it.
26
+ The SDK has the same values and placement (masks, blends, crops, groups,
27
+ ducking, timecode); LUT files, caption files, several outputs, and offline
28
+ media are VidScript only. A `.vid` can `import kit from "./kit.ts"` and place
29
+ the module's exports (`[0s .. 3s] = kit.title`), so build data-driven parts in
30
+ TypeScript and finish the edit in VidScript.
28
31
 
29
32
  ## Workflow
30
33