@vosjs/cli 0.23.0 → 0.25.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/README.md +2 -0
- package/dist/{chunk-SLCQCRNI.js → chunk-TYTUA5L5.js} +154 -15
- package/dist/chunk-TYTUA5L5.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-UU4WYO4C.js → run-OZR6NVK3.js} +2 -2
- package/package.json +5 -5
- package/schema/doc.schema.json +144 -45
- package/dist/chunk-SLCQCRNI.js.map +0 -1
- /package/dist/{run-UU4WYO4C.js.map → run-OZR6NVK3.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -495,7 +495,7 @@ async function cmdCheck(argv) {
|
|
|
495
495
|
return result.ok ? EXIT_OK : EXIT_ERROR;
|
|
496
496
|
}
|
|
497
497
|
async function delegate(argv, viaAlias = false) {
|
|
498
|
-
const { run } = await import("./run-
|
|
498
|
+
const { run } = await import("./run-OZR6NVK3.js");
|
|
499
499
|
if (viaAlias && argv[0]) {
|
|
500
500
|
process.stderr.write(
|
|
501
501
|
`note: "vos voila ${argv[0]}" is now "vos ${argv[0]}".
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vosjs/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "The vos CLI: record the real product from a scripted browser flow, auto-zoom from the cursor track, cut as data in doc.json, render deterministic video and stills, deliver a release's media per destination spec, and sync with vos.so. One binary, every verb, MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"@vosjs/core": "^0.23.6",
|
|
52
52
|
"@vosjs/editor": "^1.3.1",
|
|
53
53
|
"@vosjs/elements": "^0.8.1",
|
|
54
|
-
"@vosjs/render-core": "^0.2.
|
|
54
|
+
"@vosjs/render-core": "^0.2.5",
|
|
55
55
|
"@vosjs/shared": "^0.4.1",
|
|
56
|
-
"@vosjs/studio-core": "^0.
|
|
57
|
-
"@vosjs/
|
|
58
|
-
"@vosjs/
|
|
56
|
+
"@vosjs/studio-core": "^0.15.0",
|
|
57
|
+
"@vosjs/tween": "^0.8.2",
|
|
58
|
+
"@vosjs/timeline": "^0.4.1"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/node": "^22",
|
package/schema/doc.schema.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://vos.so/schemas/doc.schema.json",
|
|
4
|
-
"title": "vosso doc.json (the studio document
|
|
5
|
-
"description": "The editable document a vos carries beside its config: a RECORDING document (a take: `source` plus the tracks and layers) or a PROGRAM document (`program.config` plus the shared layers). Time is SECONDS everywhere. Edit this file, then re-run `vos render`
|
|
4
|
+
"title": "vosso doc.json (the studio document \u2014 a recording document or a program document)",
|
|
5
|
+
"description": "The editable document a vos carries beside its config: a RECORDING document (a take: `source` plus the tracks and layers) or a PROGRAM document (`program.config` plus the shared layers). Time is SECONDS everywhere. Edit this file, then re-run `vos render` \u2014 renders are deterministic, only your edits change the output. `vos validate <dir>` checks these contracts plus semantic lints (overlap, footage bounds).",
|
|
6
6
|
"oneOf": [
|
|
7
7
|
{
|
|
8
8
|
"title": "Recording document",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"properties": {
|
|
23
23
|
"source": {
|
|
24
24
|
"type": "object",
|
|
25
|
-
"description": "The recording this doc edits. Written by record/plan
|
|
25
|
+
"description": "The recording this doc edits. Written by record/plan \u2014 treat as read-only except videoKey/camKey/micKey when relinking assets. micKey (extension takes recorded after the audio split) is a separately-recorded mic sidecar: the voice, gained by micGain; the recording's own audio track is then system/tab audio, gained by systemGain.",
|
|
26
26
|
"additionalProperties": true
|
|
27
27
|
},
|
|
28
28
|
"segments": {
|
|
@@ -47,6 +47,10 @@
|
|
|
47
47
|
"minimum": 0,
|
|
48
48
|
"maximum": 30,
|
|
49
49
|
"description": "LEGACY spelling of a freeze at this segment's end, read into `freeze` on every path; write `freeze` instead"
|
|
50
|
+
},
|
|
51
|
+
"media": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
50
54
|
}
|
|
51
55
|
},
|
|
52
56
|
"additionalProperties": true
|
|
@@ -60,7 +64,7 @@
|
|
|
60
64
|
},
|
|
61
65
|
"zoom": {
|
|
62
66
|
"type": "array",
|
|
63
|
-
"description": "Zoom regions (SOURCE time, footage-anchored, non-overlapping). The camera ramps in around `in`, holds until `out`, ramps out
|
|
67
|
+
"description": "Zoom regions (SOURCE time, footage-anchored, non-overlapping). The camera ramps in around `in`, holds until `out`, ramps out \u2014 or pans straight to the next span when the gap is short. Planner-made spans have source:'auto' (replaced on re-plan); set source:'manual' on any span you add or edit so it survives.",
|
|
64
68
|
"items": {
|
|
65
69
|
"type": "object",
|
|
66
70
|
"required": ["id", "in", "out", "level", "cx", "cy"],
|
|
@@ -76,13 +80,13 @@
|
|
|
76
80
|
},
|
|
77
81
|
"out": {
|
|
78
82
|
"type": "number",
|
|
79
|
-
"description": "SOURCE seconds, > in (
|
|
83
|
+
"description": "SOURCE seconds, > in (\u2265 0.3s span reads well)"
|
|
80
84
|
},
|
|
81
85
|
"level": {
|
|
82
86
|
"type": "number",
|
|
83
87
|
"minimum": 1,
|
|
84
88
|
"maximum": 5,
|
|
85
|
-
"description": "zoom level; 1.4
|
|
89
|
+
"description": "zoom level; 1.4\u20132.8 reads well"
|
|
86
90
|
},
|
|
87
91
|
"cx": {
|
|
88
92
|
"type": "number",
|
|
@@ -102,7 +106,7 @@
|
|
|
102
106
|
},
|
|
103
107
|
"transition": {
|
|
104
108
|
"enum": ["instant", "fast", "smooth", "slow"],
|
|
105
|
-
"description": "transition SPEED for this span's ramps (in, out, and a chained pan arriving here). Absent = 'smooth' (the camera style's stock motion); 'instant' = hard cut; 'fast'
|
|
109
|
+
"description": "transition SPEED for this span's ramps (in, out, and a chained pan arriving here). Absent = 'smooth' (the camera style's stock motion); 'instant' = hard cut; 'fast' \u2248 half, 'slow' \u2248 1.6\u00d7."
|
|
106
110
|
},
|
|
107
111
|
"focusMode": {
|
|
108
112
|
"enum": ["manual", "auto"],
|
|
@@ -130,7 +134,11 @@
|
|
|
130
134
|
"description": "seconds from that edge to the span's `in` (negative = before it)"
|
|
131
135
|
}
|
|
132
136
|
},
|
|
133
|
-
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only
|
|
137
|
+
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only \u2014 `in`/`out` stay authoritative and lowering never reads it, so it costs nothing at render time"
|
|
138
|
+
},
|
|
139
|
+
"media": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
134
142
|
}
|
|
135
143
|
},
|
|
136
144
|
"additionalProperties": true
|
|
@@ -147,7 +155,7 @@
|
|
|
147
155
|
"cut",
|
|
148
156
|
"none"
|
|
149
157
|
],
|
|
150
|
-
"description": "Camera style preset driving planner + camera motion. Absent = 'glide'. 'none' disables auto-zoom planning (manual spans keep default motion). 'keynote' and 'drift' are tilt-forward styles: they carry a tilt personality (keynote = medium lean toward each zoom's focus with tilt ramps matched to the zoom ramps; drift = subtle lean, slower 1.6s ramps, longer chains)
|
|
158
|
+
"description": "Camera style preset driving planner + camera motion. Absent = 'glide'. 'none' disables auto-zoom planning (manual spans keep default motion). 'keynote' and 'drift' are tilt-forward styles: they carry a tilt personality (keynote = medium lean toward each zoom's focus with tilt ramps matched to the zoom ramps; drift = subtle lean, slower 1.6s ramps, longer chains) \u2014 in the studio, picking one stamps tiltStyle and plans auto tilt spans; in doc.json, set tiltStyle + tilt spans yourself (the style still shapes tilt MOTION at render)."
|
|
151
159
|
},
|
|
152
160
|
"zoomParams": {
|
|
153
161
|
"type": "object",
|
|
@@ -156,12 +164,12 @@
|
|
|
156
164
|
},
|
|
157
165
|
"speedParams": {
|
|
158
166
|
"type": "object",
|
|
159
|
-
"description": "Auto-speed planner overrides: idleMin/idleRate/typingMin/typingRate/scrollMin/scrollRate. Absent = defaults (idle
|
|
167
|
+
"description": "Auto-speed planner overrides: idleMin/idleRate/typingMin/typingRate/scrollMin/scrollRate. Absent = defaults (idle \u22655s\u21924\u00d7, typing \u22653s\u21923\u00d7, scroll \u22652.5s\u21922\u00d7).",
|
|
160
168
|
"additionalProperties": true
|
|
161
169
|
},
|
|
162
170
|
"tilt": {
|
|
163
171
|
"type": "array",
|
|
164
|
-
"description": "Card tilt regions (SOURCE time, footage-anchored, non-overlapping). While a span is active the 3D card leans to its pose; between spans it returns to FLAT (there is no static card pose: a lean is a moment on the timeline). Ramps ~0.9s in / ~0.8s out; spans
|
|
172
|
+
"description": "Card tilt regions (SOURCE time, footage-anchored, non-overlapping). While a span is active the 3D card leans to its pose; between spans it returns to FLAT (there is no static card pose: a lean is a moment on the timeline). Ramps ~0.9s in / ~0.8s out; spans \u2264 ~1.35s apart swing pose-to-pose. Direction: +rx brings the TOP edge toward the camera, +ry the LEFT edge \u2014 to lean toward a right-side focus use NEGATIVE ry. Wand-made spans have source:'auto' (replaced when Dynamic tilt re-runs); set source:'manual' on spans you add or edit.",
|
|
165
173
|
"items": {
|
|
166
174
|
"type": "object",
|
|
167
175
|
"required": ["id", "in", "out", "rx", "ry"],
|
|
@@ -177,13 +185,13 @@
|
|
|
177
185
|
},
|
|
178
186
|
"out": {
|
|
179
187
|
"type": "number",
|
|
180
|
-
"description": "SOURCE seconds, > in (
|
|
188
|
+
"description": "SOURCE seconds, > in (\u2265 0.8s so the pose can settle)"
|
|
181
189
|
},
|
|
182
190
|
"rx": {
|
|
183
191
|
"type": "number",
|
|
184
192
|
"minimum": -45,
|
|
185
193
|
"maximum": 45,
|
|
186
|
-
"description": "pose DEGREES about the horizontal axis (+ = top edge toward camera). NOT radians, NOT fractions;
|
|
194
|
+
"description": "pose DEGREES about the horizontal axis (+ = top edge toward camera). NOT radians, NOT fractions; \u00b15..18\u00b0 reads premium."
|
|
187
195
|
},
|
|
188
196
|
"ry": {
|
|
189
197
|
"type": "number",
|
|
@@ -221,7 +229,11 @@
|
|
|
221
229
|
"description": "seconds from that edge to the span's `in` (negative = before it)"
|
|
222
230
|
}
|
|
223
231
|
},
|
|
224
|
-
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only
|
|
232
|
+
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only \u2014 `in`/`out` stay authoritative and lowering never reads it, so it costs nothing at render time"
|
|
233
|
+
},
|
|
234
|
+
"media": {
|
|
235
|
+
"type": "string",
|
|
236
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
225
237
|
}
|
|
226
238
|
},
|
|
227
239
|
"additionalProperties": true
|
|
@@ -229,7 +241,7 @@
|
|
|
229
241
|
},
|
|
230
242
|
"tiltStyle": {
|
|
231
243
|
"enum": ["off", "subtle", "medium", "strong"],
|
|
232
|
-
"description": "Dynamic-tilt wand intensity: derives source:'auto' tilt spans FROM the zoom spans, leaning toward each zoom's focus (max 5/9/14
|
|
244
|
+
"description": "Dynamic-tilt wand intensity: derives source:'auto' tilt spans FROM the zoom spans, leaning toward each zoom's focus (max 5/9/14\u00b0 per axis). 'off'/absent = no auto tilt; manual spans work either way."
|
|
233
245
|
},
|
|
234
246
|
"rejected": {
|
|
235
247
|
"type": "array",
|
|
@@ -278,6 +290,10 @@
|
|
|
278
290
|
"note": {
|
|
279
291
|
"type": "string",
|
|
280
292
|
"description": "why, in the deleter's words"
|
|
293
|
+
},
|
|
294
|
+
"media": {
|
|
295
|
+
"type": "string",
|
|
296
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
281
297
|
}
|
|
282
298
|
},
|
|
283
299
|
"additionalProperties": false
|
|
@@ -296,21 +312,21 @@
|
|
|
296
312
|
"type": "number",
|
|
297
313
|
"minimum": 0,
|
|
298
314
|
"maximum": 1,
|
|
299
|
-
"description": "master gain for the recording's own system/tab audio track
|
|
315
|
+
"description": "master gain for the recording's own system/tab audio track \u2014 split takes (source.micKey) only; legacy takes have one track on micGain. Absent = 1. 0 = muted."
|
|
300
316
|
},
|
|
301
317
|
"cursor": {
|
|
302
318
|
"type": "object",
|
|
303
|
-
"description": "Cursor rendering (visible, hideWhenIdle, smoothing, size, click effects). See CursorStyle in @vosjs/studio-core. `visible: false` hides the drawn dot only
|
|
319
|
+
"description": "Cursor rendering (visible, hideWhenIdle, smoothing, size, click effects). See CursorStyle in @vosjs/studio-core. `visible: false` hides the drawn dot only \u2014 the track still drives cursor-follow zoom, and click effects keep drawing (silence those with clickFx.style: \"none\"). `hideWhenIdle` (default true) fades the dot out after ~1s parked and back in when it moves; scrolling is not movement, and it is always back at full opacity on a click.",
|
|
304
320
|
"additionalProperties": true
|
|
305
321
|
},
|
|
306
322
|
"cam": {
|
|
307
323
|
"type": "object",
|
|
308
|
-
"description": "Webcam bubble style + SOURCE-time window
|
|
324
|
+
"description": "Webcam bubble style + SOURCE-time window \u2014 the bubble's REST pose. Only applies when the take has a cam track. Placement: x/y (bubble CENTER as frame fractions, the zoom cx/cy convention) when present, else the `position` corner anchor; size = diameter as a fraction of frame height. Look: shape circle|rounded; radius (rounded corner, design px, default 18); border { width design px (default 3; 0 = none), color } (default white at 0.9); shadow none|soft|strong (default soft). Animate the pose over time with camMotion spans.",
|
|
309
325
|
"additionalProperties": true
|
|
310
326
|
},
|
|
311
327
|
"camMotion": {
|
|
312
328
|
"type": "array",
|
|
313
|
-
"description": "Animated cam layout (SOURCE time, footage-anchored, non-overlapping): while a span is active the webcam bubble holds its pose; outside spans it rests at doc.cam; spans
|
|
329
|
+
"description": "Animated cam layout (SOURCE time, footage-anchored, non-overlapping): while a span is active the webcam bubble holds its pose; outside spans it rests at doc.cam; spans \u2264 ~1.2s apart in output time morph pose-to-pose. Ramps ~0.65s, settled at span start (a cam move frames what follows). Absent pose fields inherit the rest pose, so a span may move without resizing. Only renders when the take has a cam track (source.camKey).",
|
|
314
330
|
"items": {
|
|
315
331
|
"type": "object",
|
|
316
332
|
"required": ["id", "in", "out"],
|
|
@@ -326,7 +342,7 @@
|
|
|
326
342
|
},
|
|
327
343
|
"out": {
|
|
328
344
|
"type": "number",
|
|
329
|
-
"description": "SOURCE seconds, > in (
|
|
345
|
+
"description": "SOURCE seconds, > in (\u2265 0.5s so the move can settle)"
|
|
330
346
|
},
|
|
331
347
|
"x": {
|
|
332
348
|
"type": "number",
|
|
@@ -358,6 +374,10 @@
|
|
|
358
374
|
"type": "string",
|
|
359
375
|
"enum": ["auto", "manual"],
|
|
360
376
|
"description": "reserved for a future planner; spans you add or edit are 'manual'"
|
|
377
|
+
},
|
|
378
|
+
"media": {
|
|
379
|
+
"type": "string",
|
|
380
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
361
381
|
}
|
|
362
382
|
}
|
|
363
383
|
}
|
|
@@ -369,11 +389,11 @@
|
|
|
369
389
|
"properties": {
|
|
370
390
|
"background": {
|
|
371
391
|
"type": "string",
|
|
372
|
-
"description": "CSS background (gradient/color)
|
|
392
|
+
"description": "CSS background (gradient/color) \u2014 the underlay/fallback, always painted under backgroundMedia"
|
|
373
393
|
},
|
|
374
394
|
"backgroundMedia": {
|
|
375
395
|
"type": ["object", "null"],
|
|
376
|
-
"description": "Optional media layer drawn OVER the CSS background and UNDER the card: a vos animation baked to a seamless loop, or a still image. Video time is OUTPUT-anchored modulo the loop (bgT = t % duration)
|
|
396
|
+
"description": "Optional media layer drawn OVER the CSS background and UNDER the card: a vos animation baked to a seamless loop, or a still image. Video time is OUTPUT-anchored modulo the loop (bgT = t % duration) \u2014 trims/speed never retime it. Draws outside the zoom transform. `key` may be a file inside the take dir (e.g. \"/bg.webm\"), a public https://assets.vos.so/... loop, or an /api/... URL. Fail-open: if it can't load, the CSS background still shows.",
|
|
377
397
|
"required": ["kind", "key", "dim"],
|
|
378
398
|
"properties": {
|
|
379
399
|
"kind": {
|
|
@@ -386,7 +406,7 @@
|
|
|
386
406
|
"duration": {
|
|
387
407
|
"type": "number",
|
|
388
408
|
"exclusiveMinimum": 0,
|
|
389
|
-
"description": "loop length in seconds (video only
|
|
409
|
+
"description": "loop length in seconds (video only \u2014 required for the modulo loop)"
|
|
390
410
|
},
|
|
391
411
|
"vosId": {
|
|
392
412
|
"type": "string",
|
|
@@ -409,7 +429,7 @@
|
|
|
409
429
|
"type": "number",
|
|
410
430
|
"minimum": 0,
|
|
411
431
|
"maximum": 100,
|
|
412
|
-
"description": "V2: blur radius in design px
|
|
432
|
+
"description": "V2: blur radius in design px \u2014 softens the media behind the card"
|
|
413
433
|
}
|
|
414
434
|
},
|
|
415
435
|
"additionalProperties": true
|
|
@@ -492,7 +512,7 @@
|
|
|
492
512
|
"fit": {
|
|
493
513
|
"type": "string",
|
|
494
514
|
"enum": ["contain", "cover"],
|
|
495
|
-
"description": "How footage meets an off-ratio frame. contain (default) letterboxes the card onto the background; cover makes the padded area the card and fills it with footage, cropped around `focus`
|
|
515
|
+
"description": "How footage meets an off-ratio frame. contain (default) letterboxes the card onto the background; cover makes the padded area the card and fills it with footage, cropped around `focus` \u2014 what a 440x280 store tile or a 2.5:1 marquee demands"
|
|
496
516
|
},
|
|
497
517
|
"focus": {
|
|
498
518
|
"type": "object",
|
|
@@ -580,13 +600,76 @@
|
|
|
580
600
|
"required": ["key", "aspect"],
|
|
581
601
|
"additionalProperties": false,
|
|
582
602
|
"properties": {
|
|
583
|
-
"key": {
|
|
584
|
-
|
|
603
|
+
"key": {
|
|
604
|
+
"type": "string"
|
|
605
|
+
},
|
|
606
|
+
"aspect": {
|
|
607
|
+
"type": "number",
|
|
608
|
+
"exclusiveMinimum": 0
|
|
609
|
+
}
|
|
585
610
|
},
|
|
586
611
|
"description": "the brand's mark as an image (a take-dir path or a URL the render page can load) with its width-over-height, drawn above the wordmark; a wide mark (a stylised wordmark asset) stands alone. vos deliver fetches BRAND.md's logoUrl into the take's brand/ folder and sets this"
|
|
587
612
|
}
|
|
588
613
|
},
|
|
589
614
|
"description": "the end card the clip closes on: a hold on the last frame (default 2.5 s) while the card recedes and the words rise as the house title, caption and label overlays. The clip's last frame is its poster"
|
|
615
|
+
},
|
|
616
|
+
"media": {
|
|
617
|
+
"type": "array",
|
|
618
|
+
"description": "The take's OTHER media (concat, a layer's source): each the `source` shape (a media plus the facts only a capture has) with an `id` a segment or a source-anchored span names. The primary stays `source`. Absent = one media. Each may carry `frame`, its own card.",
|
|
619
|
+
"items": {
|
|
620
|
+
"type": "object",
|
|
621
|
+
"additionalProperties": true,
|
|
622
|
+
"properties": {
|
|
623
|
+
"id": {
|
|
624
|
+
"type": "string",
|
|
625
|
+
"description": "stable identity a segment or a span names (m1, m2, \u2026)"
|
|
626
|
+
},
|
|
627
|
+
"frame": {
|
|
628
|
+
"type": "object",
|
|
629
|
+
"description": "This media's OWN card over the take's frame while it plays: its placement and size (`inset`), the browser bar, the corner, the shadow, the border, the cover fit and its focus. Frame-wide fields (aspectRatio, padding, background, backgroundMedia, anim) stay the take's. Absent fields fall to the take's frame; the bar names this media's recorded page, and a media with no page wears no bar unless `browserBar` says so.",
|
|
630
|
+
"additionalProperties": false,
|
|
631
|
+
"properties": {
|
|
632
|
+
"browserBar": {
|
|
633
|
+
"$ref": "#/oneOf/0/properties/frame/properties/browserBar"
|
|
634
|
+
},
|
|
635
|
+
"radius": {
|
|
636
|
+
"$ref": "#/oneOf/0/properties/frame/properties/radius"
|
|
637
|
+
},
|
|
638
|
+
"shadow": {
|
|
639
|
+
"$ref": "#/oneOf/0/properties/frame/properties/shadow"
|
|
640
|
+
},
|
|
641
|
+
"shadowContact": {
|
|
642
|
+
"$ref": "#/oneOf/0/properties/frame/properties/shadowContact"
|
|
643
|
+
},
|
|
644
|
+
"shadowColor": {
|
|
645
|
+
"$ref": "#/oneOf/0/properties/frame/properties/shadowColor"
|
|
646
|
+
},
|
|
647
|
+
"inset": {
|
|
648
|
+
"$ref": "#/oneOf/0/properties/frame/properties/inset"
|
|
649
|
+
},
|
|
650
|
+
"border": {
|
|
651
|
+
"$ref": "#/oneOf/0/properties/frame/properties/border"
|
|
652
|
+
},
|
|
653
|
+
"borderWidth": {
|
|
654
|
+
"$ref": "#/oneOf/0/properties/frame/properties/borderWidth"
|
|
655
|
+
},
|
|
656
|
+
"borderColor": {
|
|
657
|
+
"$ref": "#/oneOf/0/properties/frame/properties/borderColor"
|
|
658
|
+
},
|
|
659
|
+
"fit": {
|
|
660
|
+
"$ref": "#/oneOf/0/properties/frame/properties/fit"
|
|
661
|
+
},
|
|
662
|
+
"focus": {
|
|
663
|
+
"$ref": "#/oneOf/0/properties/frame/properties/focus"
|
|
664
|
+
},
|
|
665
|
+
"focusFollow": {
|
|
666
|
+
"$ref": "#/oneOf/0/properties/frame/properties/focusFollow"
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
"required": ["id"]
|
|
672
|
+
}
|
|
590
673
|
}
|
|
591
674
|
}
|
|
592
675
|
},
|
|
@@ -701,8 +784,12 @@
|
|
|
701
784
|
"type": "object",
|
|
702
785
|
"additionalProperties": false,
|
|
703
786
|
"properties": {
|
|
704
|
-
"enter": {
|
|
705
|
-
|
|
787
|
+
"enter": {
|
|
788
|
+
"$ref": "#/definitions/animStep"
|
|
789
|
+
},
|
|
790
|
+
"exit": {
|
|
791
|
+
"$ref": "#/definitions/animStep"
|
|
792
|
+
},
|
|
706
793
|
"idle": {
|
|
707
794
|
"enum": ["spin", "float", null],
|
|
708
795
|
"description": "props only: what it does while it stays"
|
|
@@ -712,7 +799,7 @@
|
|
|
712
799
|
},
|
|
713
800
|
"overlays": {
|
|
714
801
|
"type": "array",
|
|
715
|
-
"description": "Compositor v2 (V1): screen-space text clips drawn ABOVE the card, outside the zoom transform. OUTPUT-anchored (start is final-cut seconds
|
|
802
|
+
"description": "Compositor v2 (V1): screen-space text clips drawn ABOVE the card, outside the zoom transform. OUTPUT-anchored (start is final-cut seconds \u2014 trims/speed never retime a title). Optional; absent = none.",
|
|
716
803
|
"items": {
|
|
717
804
|
"type": "object",
|
|
718
805
|
"required": ["id", "kind", "start", "duration", "transform"],
|
|
@@ -753,13 +840,13 @@
|
|
|
753
840
|
},
|
|
754
841
|
"family": {
|
|
755
842
|
"type": "string",
|
|
756
|
-
"description": "font family override
|
|
843
|
+
"description": "font family override \u2014 a catalog family name (GET https://vos.so/api/fonts). Unknown names fail open to the preset stack on the render fleet"
|
|
757
844
|
},
|
|
758
845
|
"weight": {
|
|
759
846
|
"type": "number",
|
|
760
847
|
"minimum": 100,
|
|
761
848
|
"maximum": 900,
|
|
762
|
-
"description": "weight override
|
|
849
|
+
"description": "weight override \u2014 snapped to the nearest weight the catalog hosts for the family (weights are files, not synthesis)"
|
|
763
850
|
},
|
|
764
851
|
"italic": {
|
|
765
852
|
"type": "boolean",
|
|
@@ -841,13 +928,13 @@
|
|
|
841
928
|
"type": "number",
|
|
842
929
|
"minimum": -0.5,
|
|
843
930
|
"maximum": 1.5,
|
|
844
|
-
"description": "anchor CENTER as a FRACTION of the frame width [0..1] (0.5 = center at ANY aspect
|
|
931
|
+
"description": "anchor CENTER as a FRACTION of the frame width [0..1] (0.5 = center at ANY aspect \u2014 the zoom cx/cy convention; NOT pixels)"
|
|
845
932
|
},
|
|
846
933
|
"y": {
|
|
847
934
|
"type": "number",
|
|
848
935
|
"minimum": -0.5,
|
|
849
936
|
"maximum": 1.5,
|
|
850
|
-
"description": "anchor CENTER as a FRACTION of the frame height [0..1] (lower-third
|
|
937
|
+
"description": "anchor CENTER as a FRACTION of the frame height [0..1] (lower-third \u2248 0.82; NOT pixels)"
|
|
851
938
|
},
|
|
852
939
|
"scale": {
|
|
853
940
|
"type": "number",
|
|
@@ -915,7 +1002,7 @@
|
|
|
915
1002
|
},
|
|
916
1003
|
"motion": {
|
|
917
1004
|
"type": "array",
|
|
918
|
-
"description": "Pose keyframes (MO): the clip's transform animated over CLIP-LOCAL time. Values interpolate across the gap between poses (~symmetric in-out ease; a hold is two identical poses); the base transform is the value before the first pose, and absent pose fields inherit it. Pure f(t)
|
|
1005
|
+
"description": "Pose keyframes (MO): the clip's transform animated over CLIP-LOCAL time. Values interpolate across the gap between poses (~symmetric in-out ease; a hold is two identical poses); the base transform is the value before the first pose, and absent pose fields inherit it. Pure f(t) \u2014 scrub, export and chunked server renders agree.",
|
|
919
1006
|
"items": {
|
|
920
1007
|
"type": "object",
|
|
921
1008
|
"required": ["at"],
|
|
@@ -961,7 +1048,7 @@
|
|
|
961
1048
|
},
|
|
962
1049
|
"fx": {
|
|
963
1050
|
"type": "object",
|
|
964
|
-
"description": "text kind only: entrance animation evaluated per unit
|
|
1051
|
+
"description": "text kind only: entrance animation evaluated per unit \u2014 pure f(t), segmentation baked at lowering (scrub/seek/server chunks agree by construction)",
|
|
965
1052
|
"properties": {
|
|
966
1053
|
"fx": {
|
|
967
1054
|
"enum": ["fade", "rise", "pop", "blur", "typewriter"],
|
|
@@ -969,7 +1056,7 @@
|
|
|
969
1056
|
},
|
|
970
1057
|
"unit": {
|
|
971
1058
|
"enum": ["block", "line", "word", "char"],
|
|
972
|
-
"description": "what animates as one thing (default block
|
|
1059
|
+
"description": "what animates as one thing (default block \u2014 the whole text; char is grapheme-safe)"
|
|
973
1060
|
},
|
|
974
1061
|
"direction": {
|
|
975
1062
|
"enum": ["forward", "reverse", "center"],
|
|
@@ -979,7 +1066,7 @@
|
|
|
979
1066
|
"type": "number",
|
|
980
1067
|
"minimum": 0,
|
|
981
1068
|
"maximum": 2,
|
|
982
|
-
"description": "seconds between unit starts (defaults: typewriter 0.05, others 0.06 when unit
|
|
1069
|
+
"description": "seconds between unit starts (defaults: typewriter 0.05, others 0.06 when unit \u2260 block; clamped so the entrance fits the clip)"
|
|
983
1070
|
},
|
|
984
1071
|
"duration": {
|
|
985
1072
|
"type": "number",
|
|
@@ -993,13 +1080,13 @@
|
|
|
993
1080
|
},
|
|
994
1081
|
"key": {
|
|
995
1082
|
"type": "string",
|
|
996
|
-
"description": "image/video kinds: media URL or take-dir file (e.g. \"/logo.png\", \"/clip.webm\")
|
|
1083
|
+
"description": "image/video kinds: media URL or take-dir file (e.g. \"/logo.png\", \"/clip.webm\") \u2014 required for media"
|
|
997
1084
|
},
|
|
998
1085
|
"width": {
|
|
999
1086
|
"type": "number",
|
|
1000
1087
|
"exclusiveMinimum": 0,
|
|
1001
1088
|
"maximum": 1,
|
|
1002
|
-
"description": "media kinds: base width as a FRACTION of the frame width (default 0.35); height follows the media's aspect;
|
|
1089
|
+
"description": "media kinds: base width as a FRACTION of the frame width (default 0.35); height follows the media's aspect; \u00d7 transform.scale"
|
|
1003
1090
|
},
|
|
1004
1091
|
"radius": {
|
|
1005
1092
|
"type": "number",
|
|
@@ -1021,7 +1108,7 @@
|
|
|
1021
1108
|
},
|
|
1022
1109
|
"objects": {
|
|
1023
1110
|
"type": "array",
|
|
1024
|
-
"description": "Compositor v2 (V3): world-space 3D props between the card and the overlays
|
|
1111
|
+
"description": "Compositor v2 (V3): world-space 3D props between the card and the overlays \u2014 the drafted V4 engine spec. Curated primitives, GLB models by key, and extruded 3D text (TX7).",
|
|
1025
1112
|
"items": {
|
|
1026
1113
|
"type": "object",
|
|
1027
1114
|
"required": ["id", "asset", "transform3d"],
|
|
@@ -1047,7 +1134,7 @@
|
|
|
1047
1134
|
},
|
|
1048
1135
|
"key": {
|
|
1049
1136
|
"type": "string",
|
|
1050
|
-
"description": "gltf kind: GLB URL or take-dir file (e.g. \"/model.glb\")
|
|
1137
|
+
"description": "gltf kind: GLB URL or take-dir file (e.g. \"/model.glb\") \u2014 bbox-normalized so scale means the same as primitives"
|
|
1051
1138
|
},
|
|
1052
1139
|
"text": {
|
|
1053
1140
|
"type": "string",
|
|
@@ -1263,6 +1350,10 @@
|
|
|
1263
1350
|
"duck": {
|
|
1264
1351
|
"type": "boolean",
|
|
1265
1352
|
"description": "duck under the mic while speech is detected"
|
|
1353
|
+
},
|
|
1354
|
+
"media": {
|
|
1355
|
+
"type": "string",
|
|
1356
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
1266
1357
|
}
|
|
1267
1358
|
},
|
|
1268
1359
|
"additionalProperties": true
|
|
@@ -1295,7 +1386,7 @@
|
|
|
1295
1386
|
"properties": {
|
|
1296
1387
|
"id": {
|
|
1297
1388
|
"type": "string",
|
|
1298
|
-
"description": "stable identity (f0, f1,
|
|
1389
|
+
"description": "stable identity (f0, f1, \u2026)"
|
|
1299
1390
|
},
|
|
1300
1391
|
"at": {
|
|
1301
1392
|
"type": "number",
|
|
@@ -1331,6 +1422,10 @@
|
|
|
1331
1422
|
"from": {
|
|
1332
1423
|
"type": "string",
|
|
1333
1424
|
"description": "the template (a vos id, or 'endcard') that placed it, the clips' `from`: a re-apply replaces it, a loop drops it"
|
|
1425
|
+
},
|
|
1426
|
+
"media": {
|
|
1427
|
+
"type": "string",
|
|
1428
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
1334
1429
|
}
|
|
1335
1430
|
},
|
|
1336
1431
|
"additionalProperties": false
|
|
@@ -1338,7 +1433,7 @@
|
|
|
1338
1433
|
},
|
|
1339
1434
|
"speed": {
|
|
1340
1435
|
"type": "array",
|
|
1341
|
-
"description": "Speed-change spans (SOURCE time, footage-anchored, non-overlapping). Absent = all 1
|
|
1436
|
+
"description": "Speed-change spans (SOURCE time, footage-anchored, non-overlapping). Absent = all 1\u00d7. The planner proposes source:'auto' spans for typing passages, scroll runs and idle gaps (ids s0\u2026); set source:'manual' on spans you add or edit so they survive a re-plan (absent source also counts as manual).",
|
|
1342
1437
|
"items": {
|
|
1343
1438
|
"type": "object",
|
|
1344
1439
|
"required": ["id", "in", "out", "rate"],
|
|
@@ -1381,7 +1476,11 @@
|
|
|
1381
1476
|
"description": "seconds from that edge to the span's `in` (negative = before it)"
|
|
1382
1477
|
}
|
|
1383
1478
|
},
|
|
1384
|
-
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only
|
|
1479
|
+
"description": "Re-record tie: `vos plan --reuse` re-times this span onto a NEW recording of the same script by resolving the step in the new meta.steps. Metadata only \u2014 `in`/`out` stay authoritative and lowering never reads it, so it costs nothing at render time"
|
|
1480
|
+
},
|
|
1481
|
+
"media": {
|
|
1482
|
+
"type": "string",
|
|
1483
|
+
"description": "the media this belongs to: a `media[].id`; absent = the primary, `source`"
|
|
1385
1484
|
}
|
|
1386
1485
|
},
|
|
1387
1486
|
"additionalProperties": true
|