@scenerok/cli 1.0.4 → 1.0.6
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 +6 -3
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +17 -1
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +16 -2
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +14 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +42 -1
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +38 -9
- package/dist/index.js +3 -1
- package/dist/lib/api.d.ts +14 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +38 -4
- package/dist/lib/format-api-error.d.ts +2 -0
- package/dist/lib/format-api-error.d.ts.map +1 -0
- package/dist/lib/format-api-error.js +24 -0
- package/dist/lib/logger.d.ts +8 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +51 -0
- package/examples/system/3-tips-fitness.vid +45 -0
- package/examples/system/ecom-product-launch.vid +31 -0
- package/examples/system/glitch-title.vid +17 -0
- package/examples/system/meme-remix.vid +15 -0
- package/examples/system/minimal-text-reel.vid +11 -0
- package/examples/system/product-launch.vid +18 -0
- package/examples/system/rokmilk-chocolate-promo.vid +25 -0
- package/examples/system/testimonial-cut.vid +16 -0
- package/examples/system/ugc-testimonial-voiceover.vid +33 -0
- package/examples/system/voice-visual-promo.vid +21 -0
- package/package.json +2 -1
- package/skills/aider/SKILL.md +27 -22
- package/skills/aider/vidscript-guide.md +62 -39
- package/skills/aider/vidscript-sample.md +23 -14
- package/skills/aider/vidscript-strict.md +113 -0
- package/skills/claude/SKILL.md +27 -22
- package/skills/claude/vidscript-guide.md +59 -37
- package/skills/claude/vidscript-sample.md +23 -14
- package/skills/claude/vidscript-strict.md +113 -0
- package/skills/codex/SKILL.md +27 -22
- package/skills/codex/vidscript-guide.md +62 -39
- package/skills/codex/vidscript-sample.md +23 -14
- package/skills/codex/vidscript-strict.md +113 -0
- package/skills/cursor/SKILL.md +27 -22
- package/skills/cursor/vidscript-guide.md +62 -39
- package/skills/cursor/vidscript-sample.md +23 -14
- package/skills/cursor/vidscript-strict.md +113 -0
- package/skills/opencode/SKILL.md +27 -22
- package/skills/opencode/vidscript-guide.md +62 -39
- package/skills/opencode/vidscript-sample.md +23 -14
- package/skills/opencode/vidscript-strict.md +113 -0
- package/skills/skills/aider/SKILL.md +185 -0
- package/skills/skills/aider/vidscript-guide.md +378 -0
- package/skills/skills/aider/vidscript-sample.md +30 -0
- package/skills/skills/aider/vidscript-strict.md +113 -0
- package/skills/skills/claude/SKILL.md +185 -0
- package/skills/skills/claude/vidscript-guide.md +378 -0
- package/skills/skills/claude/vidscript-sample.md +30 -0
- package/skills/skills/claude/vidscript-strict.md +113 -0
- package/skills/skills/codex/SKILL.md +185 -0
- package/skills/skills/codex/vidscript-guide.md +378 -0
- package/skills/skills/codex/vidscript-sample.md +30 -0
- package/skills/skills/codex/vidscript-strict.md +113 -0
- package/skills/skills/cursor/SKILL.md +185 -0
- package/skills/skills/cursor/vidscript-guide.md +378 -0
- package/skills/skills/cursor/vidscript-sample.md +30 -0
- package/skills/skills/cursor/vidscript-strict.md +113 -0
- package/skills/skills/opencode/SKILL.md +185 -0
- package/skills/skills/opencode/vidscript-guide.md +378 -0
- package/skills/skills/opencode/vidscript-sample.md +30 -0
- package/skills/skills/opencode/vidscript-strict.md +113 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
# VidScript Language Reference (v2)
|
|
2
|
+
|
|
3
|
+
VidScript is a declarative DSL for composing short-form videos. Write a script, render an MP4.
|
|
4
|
+
|
|
5
|
+
## Agent quick start (read before composing)
|
|
6
|
+
|
|
7
|
+
1. **Import every package function** — use `import xai from "@scenerok/xai"`, `import eleven from "@elevenlabs/music"`, and `import motion from "@scenerok/basic-animations"` before calling `xai.*`, `eleven.*`, or `motion.*`.
|
|
8
|
+
2. **Validate early** — `scenerok validate file.vid` (errors show as `Line N:C — message`).
|
|
9
|
+
3. **Music package syntax** — `import eleven from "@elevenlabs/music"`, then call `eleven.music(...)`, `eleven.generateMusic(...)`, or `eleven.composeMusic(...)`.
|
|
10
|
+
4. **Copy working examples** — see `examples/system/` in this skill folder (e.g. `minimal-text-reel.vid`, `ecom-product-launch.vid`, `rokmilk-chocolate-promo.vid`).
|
|
11
|
+
5. **Strict rules** — see `vidscript-strict.md` for invalid patterns (bare `xai.imagine`, bare `eleven.music(...)` without import, trailing params after direct plugin calls, nested quotes in prompts).
|
|
12
|
+
|
|
13
|
+
### Common validation failures
|
|
14
|
+
|
|
15
|
+
| Symptom | Fix |
|
|
16
|
+
|---------|-----|
|
|
17
|
+
| `Unknown function 'xai.imagine'` | Add `import xai from "@scenerok/xai"` at top |
|
|
18
|
+
| `Unknown function 'fadeIn'` | Use `import motion from "@scenerok/basic-animations"` and call `motion.fadeIn(...)` |
|
|
19
|
+
| `Expected ... but "," found` | Do not put `, volume:` after a direct plugin call. Use `let bed = eleven.music(...)`, then `audio bed, volume: ...` |
|
|
20
|
+
| `Unknown function 'eleven.generateMusic'` | Add `import eleven from "@elevenlabs/music"` before calling `eleven.generateMusic(...)` |
|
|
21
|
+
| Parse error on imagine prompt | Remove nested `"` quotes inside the prompt string |
|
|
22
|
+
|
|
23
|
+
## Program Structure
|
|
24
|
+
|
|
25
|
+
A VidScript program is a sequence of statements separated by newlines.
|
|
26
|
+
|
|
27
|
+
```vidscript
|
|
28
|
+
# Single-line comment
|
|
29
|
+
/* Multi-line
|
|
30
|
+
comment */
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Statements
|
|
34
|
+
|
|
35
|
+
### Input Declaration
|
|
36
|
+
|
|
37
|
+
```vidscript
|
|
38
|
+
input hero = "https://cdn.example.com/hero.mp4"
|
|
39
|
+
input logo = "./assets/logo.png"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Supports HTTP(S) URLs, `/uploads/` paths, and local paths.
|
|
43
|
+
|
|
44
|
+
### Output Declaration
|
|
45
|
+
|
|
46
|
+
```vidscript
|
|
47
|
+
output to "video.mp4", resolution: "1080x1920", fps: 30
|
|
48
|
+
output to "reel.mp4", resolution: "720x1280", format: "mp4", codec: "h264", bitrate: "5M", background: "#0D0D0D"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Option | Type | Default | Description |
|
|
52
|
+
|--------|------|---------|-------------|
|
|
53
|
+
| `resolution` | string | `"1080x1920"` | Width×Height or single number |
|
|
54
|
+
| `fps` | number | `30` | Frames per second |
|
|
55
|
+
| `format` | string | `"mp4"` | Container format |
|
|
56
|
+
| `codec` | string | `"h264"` | Video codec |
|
|
57
|
+
| `bitrate` | string | `"5M"` | Encoding bitrate |
|
|
58
|
+
| `background` | string | `"#000000"` | Background color hex |
|
|
59
|
+
|
|
60
|
+
### Variable Assignment
|
|
61
|
+
|
|
62
|
+
```vidscript
|
|
63
|
+
let brandColor = "#6366F1"
|
|
64
|
+
let fadeTime = 0.5s
|
|
65
|
+
let titleSize = 72
|
|
66
|
+
let clipName = "hero"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Variables can hold strings, numbers, time literals, and object expressions. Variables are evaluated at compile time.
|
|
70
|
+
|
|
71
|
+
### Package Imports
|
|
72
|
+
|
|
73
|
+
Only default package imports are supported for callable packages. Call functions through the imported alias.
|
|
74
|
+
|
|
75
|
+
```vidscript
|
|
76
|
+
import xai from "@scenerok/xai"
|
|
77
|
+
import eleven from "@elevenlabs/music"
|
|
78
|
+
import motion from "@scenerok/basic-animations"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Named imports (`import { fn } ...`) and namespace imports (`import * as ...`) are not supported.
|
|
82
|
+
|
|
83
|
+
## Time Blocks
|
|
84
|
+
|
|
85
|
+
Time blocks are the core of VidScript. They define when instructions execute on the timeline.
|
|
86
|
+
|
|
87
|
+
### Dynamic Playhead (recommended)
|
|
88
|
+
|
|
89
|
+
```vidscript
|
|
90
|
+
[-] = hero # auto-append: starts after previous block
|
|
91
|
+
[- 3s] = text "Title", size: 72 # auto-start, last 3 seconds
|
|
92
|
+
[- 2.5s] = filter "glow", intensity: 0.8
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The playhead cursor (`prev`) tracks where the timeline is. Each `[-]` block advances the cursor by the block's content duration. `[- duration]` advances by an explicit duration.
|
|
96
|
+
|
|
97
|
+
### Explicit Range
|
|
98
|
+
|
|
99
|
+
```vidscript
|
|
100
|
+
[0s .. 5s] = hero # absolute range
|
|
101
|
+
[0.5s .. 3s] = text "Hello" # explicit times
|
|
102
|
+
[prev + 1s .. prev + 4s] = filter "glow" # expression-based
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use `..` (not `-`) as the range separator to avoid ambiguity with subtraction.
|
|
106
|
+
|
|
107
|
+
### Time Formats
|
|
108
|
+
|
|
109
|
+
```vidscript
|
|
110
|
+
5s # 5 seconds
|
|
111
|
+
300ms # 300 milliseconds
|
|
112
|
+
frame 90 # 90 frames at 30fps = 3 seconds
|
|
113
|
+
0:30 # 30 seconds
|
|
114
|
+
1:30:00 # 1 hour 30 minutes
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### The `prev` Keyword
|
|
118
|
+
|
|
119
|
+
`prev` refers to the current playhead position — the end time of the previous block.
|
|
120
|
+
|
|
121
|
+
```vidscript
|
|
122
|
+
[- 2s] = text "Hello" # plays from cursor to cursor+2s
|
|
123
|
+
[prev + 1s .. prev + 3s] = filter "glow" # 1s after text ends, for 2s
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Instructions (inside time blocks)
|
|
127
|
+
|
|
128
|
+
Multiple instructions in the same time block go on separate lines:
|
|
129
|
+
|
|
130
|
+
```vidscript
|
|
131
|
+
[0s .. 5s] = hero
|
|
132
|
+
hero.Trim(start: 0s, end: 5s)
|
|
133
|
+
hero.Speed(factor: 1.5)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Clip Reference
|
|
137
|
+
|
|
138
|
+
```vidscript
|
|
139
|
+
[-] = hero # just play the input clip
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Text Overlay
|
|
143
|
+
|
|
144
|
+
```vidscript
|
|
145
|
+
[- 3s] = text "Hello World", font: "Bebas Neue", x: "50%", y: "45%", align: center, color: "#FFFFFF", size: 72, stroke: "#000000", stroke_width: 3, letter_spacing: 4, shadow_color: "#FF0055", shadow_blur: 8
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Param | Type | Description |
|
|
149
|
+
|-------|------|-------------|
|
|
150
|
+
| `style` | string | `title` (64px), `subtitle` (54px), `caption` (36px), or `default` (48px) |
|
|
151
|
+
| `position` | string | `center`, `top`, `bottom`, `top-left`, `top-right`, `bottom-left`, `bottom-right` |
|
|
152
|
+
| `x` | number \| string | Horizontal position. Number = px from left. `"50%"` = percent of width. Overrides `position`. |
|
|
153
|
+
| `y` | number \| string | Vertical position. Number = px from top. `"50%"` = percent of height. Overrides `position`. |
|
|
154
|
+
| `color` | string | Hex color |
|
|
155
|
+
| `size` | number | Font size in pixels |
|
|
156
|
+
| `font` | string | Font family. System fonts or Google Fonts: `"Inter"`, `"Bebas Neue"`, `"Space Grotesk"`, `"Outfit"`, etc. |
|
|
157
|
+
| `align` | string | `left`, `center`, `right`. Default: `center` |
|
|
158
|
+
| `line_height` | number | Line height multiplier for multi-line text. Default: 1.2 |
|
|
159
|
+
| `letter_spacing` | number | Extra letter spacing in pixels. Default: 0 |
|
|
160
|
+
| `rotation` | number | Rotation in degrees. Positive = clockwise. Default: 0 |
|
|
161
|
+
| `opacity` | number | Opacity 0–1. Default: 1 |
|
|
162
|
+
| `stroke` | string | Outline color |
|
|
163
|
+
| `stroke_width` | number | Outline thickness |
|
|
164
|
+
| `shadow_color` | string | Drop shadow color |
|
|
165
|
+
| `shadow_blur` | number | Shadow blur radius |
|
|
166
|
+
| `shadow_offset_x` | number | Shadow horizontal offset |
|
|
167
|
+
| `shadow_offset_y` | number | Shadow vertical offset |
|
|
168
|
+
| `animation` | string | Parsed but not yet rendered |
|
|
169
|
+
|
|
170
|
+
Params are optional and comma-separated. Params can be on the same line as the content.
|
|
171
|
+
|
|
172
|
+
### Video Methods
|
|
173
|
+
|
|
174
|
+
```vidscript
|
|
175
|
+
hero.Trim(start: 0s, end: 5s) # trim clip (positional: hero.Trim(0s, 5s))
|
|
176
|
+
hero.Resize(width: 720, height: 1280) # resize (positional: hero.Resize(720, 1280))
|
|
177
|
+
hero.Speed(factor: 1.5) # playback rate
|
|
178
|
+
hero.Loop(count: 3) # loop count
|
|
179
|
+
hero.Opacity(value: 0.5, duration: 2s) # opacity with duration
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Arguments can be positional or named using `:`.
|
|
183
|
+
|
|
184
|
+
### Compositing
|
|
185
|
+
|
|
186
|
+
```vidscript
|
|
187
|
+
hero.Overlay(logo, x: 50, y: 100, opacity: 0.8)
|
|
188
|
+
hero.Composite(overlay, x: 0, y: 0, opacity: 0.5, mode: "screen")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
| Param | Type | Description |
|
|
192
|
+
|-------|------|-------------|
|
|
193
|
+
| `x` | number | Horizontal offset |
|
|
194
|
+
| `y` | number | Vertical offset |
|
|
195
|
+
| `opacity` | number | 0–1 transparency |
|
|
196
|
+
| `mode` | string | Blend mode for Composite |
|
|
197
|
+
|
|
198
|
+
### Filters
|
|
199
|
+
|
|
200
|
+
```vidscript
|
|
201
|
+
[- 2s] = filter "glow", intensity: 0.8
|
|
202
|
+
[0s .. 5s] = filter "vignette", intensity: 0.3
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Built-in filters: `monochrome`, `sepia`, `blur`, `chromatic`, `glitch`, `vignette`, `contrast`, `saturation`, `brightness`.
|
|
206
|
+
|
|
207
|
+
### Shaders
|
|
208
|
+
|
|
209
|
+
```vidscript
|
|
210
|
+
import shader glow from "shader-pack/glow.glsl"
|
|
211
|
+
|
|
212
|
+
[0s .. 5s] = shader glow, intensity: 0.8
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Audio
|
|
216
|
+
|
|
217
|
+
```vidscript
|
|
218
|
+
audio music, volume: 0.5, fade_in: 1s, fade_out: 2s
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Audio sources can be MP3 inputs, audio plugin results, or the embedded audio stream from an input video. Video clips are visually silent unless you explicitly add `audio clip`.
|
|
222
|
+
|
|
223
|
+
| Param | Type | Description |
|
|
224
|
+
|-------|------|-------------|
|
|
225
|
+
| `volume` | number | 0–1 |
|
|
226
|
+
| `fade_in` | number | Fade-in duration (seconds) |
|
|
227
|
+
| `fade_out` | number | Fade-out duration (seconds) |
|
|
228
|
+
|
|
229
|
+
### Plugin Calls
|
|
230
|
+
|
|
231
|
+
```vidscript
|
|
232
|
+
import xai from "@scenerok/xai"
|
|
233
|
+
import eleven from "@elevenlabs/music"
|
|
234
|
+
import motion from "@scenerok/basic-animations"
|
|
235
|
+
|
|
236
|
+
[-] = video xai.imagine("Cinematic product shot", aspect_ratio: "9:16", duration: 5)
|
|
237
|
+
[-] = audio xai.tts("Welcome to SceneRok", voice: "eve")
|
|
238
|
+
|
|
239
|
+
# ElevenLabs music package functions require an import alias.
|
|
240
|
+
[0s .. 15s] = audio eleven.music("Warm premium launch bed", duration: 15, instrumental: true)
|
|
241
|
+
|
|
242
|
+
# If you need volume or fades, store the generated audio first.
|
|
243
|
+
let bed = eleven.music("Warm premium launch bed", duration: 15, instrumental: true)
|
|
244
|
+
[0s .. 15s] = audio bed, volume: 0.35, fade_out: 2s
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`@scenerok/xai` requires an explicit default import. ElevenLabs music validates as `eleven.music(...)`, `eleven.generateMusic(...)`, or `eleven.composeMusic(...)` after `import eleven from "@elevenlabs/music"`. Plugin calls run at compile time; direct media plugin instructions cannot have trailing audio params, so use a `let` binding when you need `volume`, `fade_in`, or `fade_out`.
|
|
248
|
+
|
|
249
|
+
**Invalid (will not validate):**
|
|
250
|
+
|
|
251
|
+
```vidscript
|
|
252
|
+
[-] = video xai.imagine("...") # missing xAI import
|
|
253
|
+
[0s .. 15s] = audio eleven.generateMusic("...") # missing `import eleven from "@elevenlabs/music"`
|
|
254
|
+
[0s .. 15s] = audio eleven.music("..."), volume: 0.5 # trailing params after direct plugin call
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Animations, Effects & Plugins (v2 Extensibility)
|
|
258
|
+
|
|
259
|
+
VidScript v2 uses a **minimal-grammar, plugin-first** architecture for animations and effects.
|
|
260
|
+
|
|
261
|
+
Instead of adding dozens of animation keywords to the language, we use two powerful parameters:
|
|
262
|
+
|
|
263
|
+
- `animate:`
|
|
264
|
+
- `effects:`
|
|
265
|
+
|
|
266
|
+
These accept either plugin function calls or plain object descriptors.
|
|
267
|
+
|
|
268
|
+
### animate: parameter
|
|
269
|
+
|
|
270
|
+
Attach animations to **any** text or video surface.
|
|
271
|
+
|
|
272
|
+
```vidscript
|
|
273
|
+
import motion from "@scenerok/basic-animations"
|
|
274
|
+
|
|
275
|
+
text "Hello", animate: motion.fadeIn(0.8s)
|
|
276
|
+
|
|
277
|
+
video hero, animate: [motion.fadeIn(0.5s), motion.slideY(-40, 0, 1.2s)]
|
|
278
|
+
|
|
279
|
+
text "Title", animate: {
|
|
280
|
+
type: "fade",
|
|
281
|
+
from: { opacity: 0 },
|
|
282
|
+
to: { opacity: 1 },
|
|
283
|
+
start: 0,
|
|
284
|
+
end: 1.5
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### effects: parameter
|
|
289
|
+
|
|
290
|
+
Attach post-processing effects, with support for animated parameters.
|
|
291
|
+
|
|
292
|
+
```vidscript
|
|
293
|
+
text "Dramatic", effects: [grayscale(intensity: 0.8)]
|
|
294
|
+
|
|
295
|
+
video hero, effects: [{
|
|
296
|
+
name: "glitch",
|
|
297
|
+
strength: animate: { type: "fade", from: { strength: 0 }, to: { strength: 1 } }
|
|
298
|
+
}]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Currently Available Animation Functions (`basic-animations` plugin)
|
|
302
|
+
|
|
303
|
+
| Function | Description |
|
|
304
|
+
|---------------------------|------------------------------|
|
|
305
|
+
| `motion.fadeIn(duration?)` | Opacity 0 → 1 |
|
|
306
|
+
| `motion.fadeOut(duration?)` | Opacity 1 → 0 |
|
|
307
|
+
| `motion.slideX(from, to, dur?)` | Horizontal slide |
|
|
308
|
+
| `motion.slideY(from, to, dur?)` | Vertical slide |
|
|
309
|
+
| `motion.popIn(duration?)` | Scale + fade entrance |
|
|
310
|
+
| `motion.riseIn(duration?, dist?)` | Upward fade entrance |
|
|
311
|
+
| `motion.swingIn(duration?)` | Rotating slide/fade |
|
|
312
|
+
| `motion.glitchIn(duration?)` | Jitter + flash entrance |
|
|
313
|
+
| `motion.float(duration?, amp?)` | Gentle vertical bob |
|
|
314
|
+
| `motion.typewriter(duration?)` | Character reveal |
|
|
315
|
+
|
|
316
|
+
More plugins (advanced text animations, pixel effects, 3D, etc.) are planned.
|
|
317
|
+
|
|
318
|
+
The full architecture and IR details live in `plan-v1/29-surface-animation-effect-plugin-architecture.md`.
|
|
319
|
+
|
|
320
|
+
## Expressions
|
|
321
|
+
|
|
322
|
+
Used in time specs, `let` values, and function arguments:
|
|
323
|
+
|
|
324
|
+
```vidscript
|
|
325
|
+
let x = 5s # Time literals
|
|
326
|
+
let y = x * 2 # Arithmetic
|
|
327
|
+
let prompt = "Scene: " + title_text # String concatenation
|
|
328
|
+
let z = prev + 0.5s # Playhead reference
|
|
329
|
+
let a = { primary: "#FF5733" } # Objects
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Operators: `+`, `-`, `*`, `/` with standard precedence.
|
|
333
|
+
|
|
334
|
+
## Template Placeholders
|
|
335
|
+
|
|
336
|
+
```vidscript
|
|
337
|
+
[- 3s] = text "{{headline | Default Text}}", color: "{{color | #FFFFFF}}"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Placeholders are filled before parsing via `fillPlaceholders()`.
|
|
341
|
+
|
|
342
|
+
## CLI Commands
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Authenticate
|
|
346
|
+
scenerok auth login
|
|
347
|
+
|
|
348
|
+
# Validate a script
|
|
349
|
+
scenerok validate my-video.vid
|
|
350
|
+
|
|
351
|
+
# Render a video
|
|
352
|
+
scenerok project upload my-video.vid --assets ./assets --render --watch --download ./renders
|
|
353
|
+
scenerok project render <project-id> --watch --download ./renders
|
|
354
|
+
scenerok render my-video.vid --project-id <project-id> --watch
|
|
355
|
+
scenerok cache pull
|
|
356
|
+
|
|
357
|
+
# Check render status
|
|
358
|
+
scenerok status <render-id>
|
|
359
|
+
|
|
360
|
+
# Install agent skills
|
|
361
|
+
scenerok skills install <platform>
|
|
362
|
+
|
|
363
|
+
# Set API secrets for plugins
|
|
364
|
+
scenerok secrets set ELEVENLABS_API_KEY=your-key
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Best Practices
|
|
368
|
+
|
|
369
|
+
1. **Use dynamic timeblocks** — `[-]` auto-advances the cursor, reducing calculation errors
|
|
370
|
+
2. **Use `prev` for offsets** — `[prev + 0.5s .. prev + 2s]` for gaps after previous content
|
|
371
|
+
3. **1080×1920 for vertical** (TikTok, Reels, Shorts), **1920×1080 for horizontal** (YouTube)
|
|
372
|
+
4. **Hook viewers in the first 3 seconds** — place the most compelling content early
|
|
373
|
+
5. **High-contrast text** — use `stroke` and `stroke_width` on text overlays over video
|
|
374
|
+
6. **Test with `scenerok validate` first** — catch syntax errors before spending render credits
|
|
375
|
+
7. **Keep text content short** — text disappears when the time block ends
|
|
376
|
+
8. **One instruction per line** — each instruction inside a timeblock goes on its own line
|
|
377
|
+
9. **Text-only auto blocks** — `[-] = text ...` lasts 2 seconds by default; use `[- 3s]` for custom timing
|
|
378
|
+
10. **Named arguments are clearer** — `hero.Trim(start: 0s, end: 5s)` over `hero.Trim(0s, 5s)`
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# VidScript v2 Sample — Product promo with generated video
|
|
2
|
+
|
|
3
|
+
Copy this shape for promos that use xAI-generated clips. Run `scenerok validate` before `scenerok render`.
|
|
4
|
+
|
|
5
|
+
```vidscript
|
|
6
|
+
import xai from "@scenerok/xai"
|
|
7
|
+
import motion from "@scenerok/basic-animations"
|
|
8
|
+
|
|
9
|
+
input product_name = "{{product_name | RokMilk}}"
|
|
10
|
+
input hook_text = "{{hook_text | Chocolate Milkshake}}"
|
|
11
|
+
input cta_text = "{{cta_text | visit your nearest grocery store}}"
|
|
12
|
+
|
|
13
|
+
[0s .. 2.5s] = text product_name, font: "Bebas Neue", size: 80, color: "#FFD700", x: "50%", y: "20%", align: center, stroke: "#3E1C00", stroke_width: 4, animate: motion.fadeIn(0.6s)
|
|
14
|
+
|
|
15
|
+
[2s .. 4.5s] = text hook_text, font: "Outfit", size: 52, color: "#FFFFFF", x: "50%", y: "45%", align: center, stroke: "#3E1C00", stroke_width: 3, animate: motion.riseIn(0.8s)
|
|
16
|
+
|
|
17
|
+
[-] = video xai.imagine(
|
|
18
|
+
"Premium lifestyle product shot of " + product_name + " chocolate milk in 250ml carton, cinematic lighting, 9:16 vertical",
|
|
19
|
+
aspect_ratio: "9:16",
|
|
20
|
+
duration: 6
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
[8s .. 11s] = text cta_text, font: "Bebas Neue", size: 48, color: "#FFD700", x: "50%", y: "80%", align: center, stroke: "#3E1C00", stroke_width: 4, animate: motion.fadeIn(0.8s)
|
|
24
|
+
|
|
25
|
+
[0s .. 12s] = filter "vignette", intensity: 0.3
|
|
26
|
+
|
|
27
|
+
output to "product-promo.mp4", resolution: "1080x1920", fps: 30
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For clips you already have (no xAI), start from `examples/system/product-launch.vid` instead.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# VidScript v2 — Strict Agent Reference
|
|
2
|
+
|
|
3
|
+
Follow these rules exactly. When in doubt, copy a file from `examples/system/` (installed with `scenerok skills install`).
|
|
4
|
+
|
|
5
|
+
## Rule 1: Package imports are mandatory
|
|
6
|
+
|
|
7
|
+
```vidscript
|
|
8
|
+
import xai from "@scenerok/xai"
|
|
9
|
+
import eleven from "@elevenlabs/music"
|
|
10
|
+
import motion from "@scenerok/basic-animations"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Without the owning import, calls like `xai.imagine`, `xai.tts`, `eleven.music`, and `motion.fadeIn` fail validation.
|
|
14
|
+
|
|
15
|
+
**Never** call package functions without importing the package alias first.
|
|
16
|
+
|
|
17
|
+
## Rule 2: Use registered plugin surfaces
|
|
18
|
+
|
|
19
|
+
```vidscript
|
|
20
|
+
import xai from "@scenerok/xai"
|
|
21
|
+
import eleven from "@elevenlabs/music"
|
|
22
|
+
|
|
23
|
+
[-] = video xai.imagine("Prompt here", aspect_ratio: "9:16", duration: 5)
|
|
24
|
+
[-] = audio xai.tts("Voiceover line", voice: "eve")
|
|
25
|
+
[0s .. 15s] = audio eleven.music("Warm premium music bed", duration: 15, instrumental: true)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For ElevenLabs music, import `@elevenlabs/music` and use `eleven.music(...)`, `eleven.generateMusic(...)`, or `eleven.composeMusic(...)`.
|
|
29
|
+
|
|
30
|
+
## Rule 3: Time ranges use `..`
|
|
31
|
+
|
|
32
|
+
```vidscript
|
|
33
|
+
[0s .. 5s] = text "Hello"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Not `[0s - 5s]`.
|
|
37
|
+
|
|
38
|
+
## Rule 4: Text params stay on one line
|
|
39
|
+
|
|
40
|
+
```vidscript
|
|
41
|
+
[0.5s .. 3s] = text "Headline", font: "Inter", size: 64, color: "#FFFFFF", x: "50%", y: "30%", align: center
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Rule 5: Quote safety in prompts
|
|
45
|
+
|
|
46
|
+
Use only straight `"` inside `xai.imagine("...")`. Do not nest quotes inside the prompt string (e.g. avoid `"RokMilk"` inside the prompt — say `labeled RokMilk` without extra quotes).
|
|
47
|
+
|
|
48
|
+
## Rule 6: Audio syntax
|
|
49
|
+
|
|
50
|
+
```vidscript
|
|
51
|
+
import xai from "@scenerok/xai"
|
|
52
|
+
import eleven from "@elevenlabs/music"
|
|
53
|
+
|
|
54
|
+
[-] = audio xai.tts("Spoken line", voice: "eve", speed: 1.0)
|
|
55
|
+
|
|
56
|
+
# Direct music call, no trailing audio params.
|
|
57
|
+
[0s .. 15s] = audio eleven.music("Soft premium ad music", duration: 15, instrumental: true)
|
|
58
|
+
|
|
59
|
+
# Use a binding when you need volume or fades.
|
|
60
|
+
let bed = eleven.music("Soft premium ad music", duration: 15, instrumental: true)
|
|
61
|
+
[0s .. 15s] = audio bed, volume: 0.35, fade_out: 2s
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Invalid:** `audio eleven.music("...", duration: 15), volume: 0.35` — trailing `, volume` after a direct plugin call is a parse error.
|
|
65
|
+
|
|
66
|
+
**Invalid:** `eleven.generateMusic(...)` without `import eleven from "@elevenlabs/music"`.
|
|
67
|
+
|
|
68
|
+
## Rule 7: Filters
|
|
69
|
+
|
|
70
|
+
```vidscript
|
|
71
|
+
[0s .. 15s] = filter "vignette", intensity: 0.3
|
|
72
|
+
[0s .. 15s] = filter "saturation", value: 1.12
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`saturation` uses `value`, not `intensity`.
|
|
76
|
+
|
|
77
|
+
## Rule 8: Always end with output
|
|
78
|
+
|
|
79
|
+
```vidscript
|
|
80
|
+
output to "video.mp4", resolution: "1080x1920", fps: 30
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Do **not** use legacy `config { }` blocks — they are not part of VidScript v2.
|
|
84
|
+
|
|
85
|
+
## Animations (after import)
|
|
86
|
+
|
|
87
|
+
```vidscript
|
|
88
|
+
import motion from "@scenerok/basic-animations"
|
|
89
|
+
|
|
90
|
+
[0s .. 2s] = text "Launch", x: "50%", y: "50%", animate: motion.popIn(0.7s)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Available: `fadeIn`, `fadeOut`, `slideX`, `slideY`, `popIn`, `riseIn`, `swingIn`, `glitchIn`, `float`, `typewriter`.
|
|
94
|
+
|
|
95
|
+
## Validate before render
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
scenerok validate my-video.vid
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Each error line includes `Line N:C — message` when the server returns location info.
|
|
102
|
+
|
|
103
|
+
## Bundled examples
|
|
104
|
+
|
|
105
|
+
| File | Use case |
|
|
106
|
+
|------|----------|
|
|
107
|
+
| `minimal-text-reel.vid` | Text-only, no API keys |
|
|
108
|
+
| `product-launch.vid` | User video input + text + vignette |
|
|
109
|
+
| `ecom-product-launch.vid` | xAI product visuals + CTA |
|
|
110
|
+
| `3-tips-fitness.vid` | Multiple `[-]` blocks + xAI per segment |
|
|
111
|
+
| `rokmilk-chocolate-promo.vid` | 15s generated-video promo pattern |
|
|
112
|
+
|
|
113
|
+
Full grammar: https://scenerok.com/docs/vidscript
|