@scenerok/sdk 0.7.0 → 0.8.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.
@@ -0,0 +1,44 @@
1
+ # VidScript sample: a 13-second product promo
2
+
3
+ A complete script to copy and adapt: two generated shots joined by a dissolve,
4
+ titles in named areas, a voiceover, and a music bed that ducks under it.
5
+ Validate it before rendering.
6
+
7
+ ```vidscript
8
+ import xai from "@scenerok/xai"
9
+ import eleven from "@elevenlabs/music"
10
+ import motion from "@scenerok/basic-animations"
11
+ import tr from "@scenerok/transitions"
12
+
13
+ # Copy lives in variables so it is easy to change.
14
+ let product = "RokMilk"
15
+ let hook = "Chocolate milkshake, ready in seconds"
16
+ let cta = "Find it at your nearest grocery store"
17
+
18
+ # Generated media is bound with let, so its real length is known.
19
+ # Prompts never ask for text; all copy is added with `text` below.
20
+ let kitchen = xai.imagine("Chocolate milk carton on a sunlit kitchen counter, cinematic lighting, shallow depth of field, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 6)
21
+ let pour = xai.imagine("Slow pour of chocolate milkshake into a tall glass, macro, warm light, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 6)
22
+ let vo = xai.tts("Meet RokMilk. Chocolate milkshake, ready in seconds. Find it at your nearest grocery store.", voice: "eve")
23
+ let bed = eleven.music("Warm, upbeat acoustic bed for a food ad", duration: 13, instrumental: true)
24
+
25
+ # Picture: each [-] starts where the previous visual block ended.
26
+ [-] = kitchen
27
+ [- 0.6s] = tr.dissolve()
28
+ [-] = pour
29
+
30
+ # Titles go in named areas, never at guessed coordinates.
31
+ [0s .. 3s] = text product, style: title, area: "title", animate: motion.popIn(0.6s)
32
+ [3s .. 7s] = text hook, area: "lower-third", animate: motion.riseIn(0.6s)
33
+ [9s .. 12.6s] = text cta, area: "caption", animate: motion.fadeIn(0.5s)
34
+
35
+ # Sound: the voiceover runs for its measured length; the bed ducks under it.
36
+ [0s .. vo.duration] = audio vo
37
+ [0s .. 13s] = audio bed, volume: 0.6, duck_under: vo, fade_out: 1.5s
38
+
39
+ output to "rokmilk-promo.mp4", resolution: "1080x1920", fps: 30
40
+ ```
41
+
42
+ To cut your own footage instead of generating it, replace the `let … =
43
+ xai.imagine(…)` lines with `input` declarations and see `editing-actions.md`.
44
+ The `@scenerok/cli` package ships more scripts in `examples/system/`.
@@ -0,0 +1,266 @@
1
+ # VidScript v2 — Strict Agent Reference
2
+
3
+ Follow these rules exactly. For a complete working script, see `vidscript-sample.md`; for cuts, layering, masks, audio mixing, and grading, see `editing-actions.md`.
4
+
5
+ ## Rule 1: Package imports are mandatory
6
+
7
+ ```vidscript
8
+ import xai from "@scenerok/xai"
9
+ import cf from "@scenerok/cloudflare"
10
+ import eleven from "@elevenlabs/music"
11
+ import motion from "@scenerok/basic-animations"
12
+ ```
13
+
14
+ Without the owning import, calls like `xai.imagine`, `cf.video`, `xai.tts`, `eleven.music`, and `motion.fadeIn` fail validation.
15
+
16
+ **Never** call package functions without importing the package alias first.
17
+
18
+ ## Rule 2: Use URL assets selectively
19
+
20
+ A product or landing-page URL is optional source material. Capture focused, legible pieces (above-the-fold views, product shots, logos), never full-page screenshots as backgrounds, and don't invent claims. The full URL workflow is in `workflow.md`.
21
+
22
+ ## Rule 2.5: Probe real asset type and dimensions before placement
23
+
24
+ Before writing `width`, `height`, `x`, or `y` for a real image/video/screenshot/logo, identify the asset type and inspect the actual dimensions and duration:
25
+
26
+ ```bash
27
+ file asset.png
28
+ ffprobe -v error -select_streams v:0 -show_entries stream=width,height,duration -of csv=p=0 asset.mp4
29
+ sips -g pixelWidth -g pixelHeight asset.png
30
+ identify asset.webp
31
+ ```
32
+
33
+ Use real video files for motion footage and still image inputs for screenshots, logos, product photos, and brand marks. The `video` primitive accepts both videos and images; image inputs render as static clips for the block duration.
34
+
35
+ ```vidscript
36
+ import motion from "@scenerok/basic-animations"
37
+
38
+ input screenshot = "assets/screenshots/homepage.png"
39
+ [0s .. 4s] = video screenshot, width: 1080, height: 1920, x: 0, y: 0, animate: motion.fadeIn(0.35s)
40
+ ```
41
+
42
+ Use measured aspect ratio and safe-area math. Do not guess sizes or blindly resize every asset to the same box. Center visuals with explicit pixel placement when possible:
43
+
44
+ ```text
45
+ x = (outputWidth - scaledWidth) / 2
46
+ y = safeAreaTop
47
+ ```
48
+
49
+ Add entry motion to real assets, not only text. When a static visual needs a clean exit, split it:
50
+
51
+ ```vidscript
52
+ import motion from "@scenerok/basic-animations"
53
+
54
+ input product = "assets/product.png"
55
+ [0s .. 3.4s] = video product, width: 760, height: 615, x: 160, y: 300, animate: [motion.riseIn(0.6s, 70), motion.float(2.4s, 8)]
56
+ [3.4s .. 4s] = video product, width: 760, height: 615, x: 160, y: 300, animate: motion.fadeOut(0.6s)
57
+ ```
58
+
59
+ ## Rule 3: Generated media prompts must forbid text
60
+
61
+ AI-generated images and videos must not contain readable text. In every prompt for generated visual media, explicitly ask for no text, no words, no letters, no captions, no logos, no watermarks, and no readable UI copy. SceneRok has strong text primitives; all final titles, subtitles, offers, prices, feature labels, disclaimers, and CTAs must be added with VidScript `text` instructions instead of being baked into generated media.
62
+
63
+ Good prompt pattern:
64
+
65
+ ```vidscript
66
+ import xai from "@scenerok/xai"
67
+
68
+ [-] = video xai.imagine("Clean cinematic product background, premium lighting, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 5)
69
+ [0.5s .. 3s] = text "Launch offer", style: title, color: "#FFFFFF", area: "title", stroke: "#000000", stroke_width: 3
70
+ ```
71
+
72
+ Invalid: asking the generator for signs, labels, packaging text, app UI text, title cards, lower thirds, prices, CTA buttons, or any readable copy.
73
+
74
+ ## Rule 4: Use registered plugin surfaces
75
+
76
+ ```vidscript
77
+ import xai from "@scenerok/xai"
78
+ import cf from "@scenerok/cloudflare"
79
+ import eleven from "@elevenlabs/music"
80
+
81
+ [- 4s] = video xai.image("Prompt here, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", resolution: "2k")
82
+ [-] = video xai.imagine("Prompt here, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 5)
83
+ [-] = video xai.imageToVideo("https://cdn.example.com/product.png", "Slow camera move around the product, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 6)
84
+ [-] = video xai.referenceToVideo(["https://cdn.example.com/product.png", "https://cdn.example.com/person.png"], "Lifestyle scene using the referenced product and person, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 8)
85
+ [-] = video xai.extendVideo("https://cdn.example.com/clip.mp4", "Continue the camera move, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", duration: 5)
86
+ [-] = audio xai.tts("Voiceover line", voice: "eve")
87
+
88
+ [-] = video cf.video("Prompt here, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", model: "pixverse/v6", aspect_ratio: "9:16", duration: 5, generate_audio: false)
89
+ [-] = video cf.imageToVideo("https://cdn.example.com/product.png", "Animate the image, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", model: "runwayml/gen-4.5", aspect_ratio: "9:16", duration: 5)
90
+ [0s .. 15s] = audio eleven.music("Warm premium music bed", duration: 15, instrumental: true)
91
+ ```
92
+
93
+ Do not overuse one plugin function. Choose deliberately:
94
+
95
+ | Need | Use |
96
+ |------|-----|
97
+ | Still image clip | `xai.image`, `xai.generateImage`, `cf.image`, `cf.generateImage` |
98
+ | Text-to-video | `xai.imagine`, `xai.genVideo`, `cf.video`, `cf.imagine`, `cf.generateVideo` |
99
+ | Animate one image/screenshot/product photo | `xai.imageToVideo`, `cf.imageToVideo` |
100
+ | Guide with 1-7 reference images | `xai.referenceToVideo`, `cf.referenceToVideo` |
101
+ | Continue a clip | `xai.extendVideo`, `cf.extendVideo` |
102
+ | Voiceover | `xai.tts`, `xai.textToSpeech` |
103
+ | Music bed | `eleven.music`, `eleven.generateMusic`, `eleven.composeMusic` |
104
+
105
+ Use `imageToVideo` for one extracted screenshot/product/logo image and `referenceToVideo` for 1–7 reference images (xAI: prompt required, duration ≤ 10s). Cloudflare calls take an explicit `model:` and `aspect_ratio:`; models, signatures, and durations are in `ai-models.md` and the plugin table in `vidscript-guide.md`.
106
+
107
+ xAI TTS voices are only `eve`, `ara`, `rex`, `sal`, and `leo`. ElevenLabs is music only (`eleven.music`, `eleven.generateMusic`, `eleven.composeMusic`); there is no `eleven.tts`. Ads, promos, tutorials, and reels should normally have a voiceover, a music bed, or both unless the user asks for silence.
108
+
109
+ ## Rule 4.5: `[-]` uses separate audio and visual playheads
110
+
111
+ Use `[-]` freely for generated visual sequences even when audio is already scheduled. VidScript advances audio and visual auto blocks independently:
112
+
113
+ ```vidscript
114
+ import xai from "@scenerok/xai"
115
+ import eleven from "@elevenlabs/music"
116
+
117
+ input family_image = "https://cdn.example.com/family.png"
118
+ let bed = eleven.music("Warm family music", duration: 15, instrumental: true)
119
+ [0s .. 15s] = audio bed, volume: 0.35, fade_out: 2s
120
+ [-] = video xai.imageToVideo(family_image, "Warm family moment, no text, no words, no letters, no captions, no logos, no watermark, no readable UI copy", aspect_ratio: "9:16", duration: 15)
121
+ ```
122
+
123
+ The video starts at the visual playhead, usually `0s`; it is not pushed to `15s` by the audio bed. Audio blocks such as `[-] = audio xai.tts(...)` advance only the audio playhead. Visual blocks such as `[-] = video ...` and `[-] = text ...` advance only the visual playhead. A block containing both audio and visual instructions advances both.
124
+
125
+ Use explicit ranges when you need exact synchronization, overlaps, or cuts. Do not avoid `[-]` solely because the script contains music or voiceover.
126
+
127
+ ## Rule 4.6: Never guess generated-asset durations
128
+
129
+ Avoid — the real TTS length is unknown at write time, so a guessed window clips or overlaps:
130
+
131
+ ```vidscript avoid
132
+ import xai from "@scenerok/xai"
133
+
134
+ [0s .. 3s] = audio xai.tts("A sentence that may well run past three seconds", voice: "eve")
135
+ [3s .. 6s] = audio xai.tts("This one starts while the first is still playing", voice: "eve")
136
+ ```
137
+
138
+ Do this — assign with `let` and reference the measured `duration` (arithmetic allowed), or use `[-]` auto blocks:
139
+
140
+ ```vidscript
141
+ import xai from "@scenerok/xai"
142
+
143
+ let vo1 = xai.tts("First line", voice: "eve")
144
+ let vo2 = xai.tts("Second line", voice: "eve")
145
+ [0 .. vo1.duration] = audio vo1
146
+ [vo1.duration + 0.3 .. vo1.duration + 0.3 + vo2.duration] = audio vo2
147
+ ```
148
+
149
+ Exported timelines expose `.duration` the same way: `[scene1.duration .. scene1.duration + 4] = ...`.
150
+
151
+ ## Rule 4.7: Prefer `area:` over hand-picked text coordinates
152
+
153
+ Built-in named regions work with no setup and guarantee the text fits its cell (wrap + shrink + bounds):
154
+
155
+ ```vidscript
156
+ [0 .. 3] = text "BIG SALE", area: "title"
157
+ [0 .. 3] = text "50% off this week", area: "lower-third"
158
+ ```
159
+
160
+ Available by default: `title`, `stage`, `lower-third`, `caption`. Custom layouts: `grid rows: "20% 1fr 30%", areas: ["title", "stage", "caption"]` (CSS Grid semantics, `%`/`fr` tracks only). Explicit `x`/`y` still work and override the area — use them only when a region genuinely doesn't fit the design.
161
+
162
+ **TypeScript SDK:** same regions via `t.grid({ rows, cols?, areas })` and `text(..., { area: 'title' })` — see `sdk-guide.md`.
163
+
164
+ ## Rule 5: Time ranges use `..`
165
+
166
+ ```vidscript
167
+ [0s .. 5s] = text "Hello"
168
+ ```
169
+
170
+ Not `[0s - 5s]`.
171
+
172
+ ## Rule 6: Text params stay on one line
173
+
174
+ ```vidscript
175
+ [0.5s .. 3s] = text "Headline", font: "Inter", size: 64, color: "#FFFFFF", x: "50%", y: "30%", align: center
176
+ ```
177
+
178
+ ## Rule 7: Quote safety in prompts
179
+
180
+ Escape quote characters inside prompt strings, e.g. `xai.imagine("Package labeled \"RokMilk\", no text, no watermark")`.
181
+
182
+ ## Rule 8: Audio syntax
183
+
184
+ ```vidscript
185
+ import xai from "@scenerok/xai"
186
+ import cf from "@scenerok/cloudflare"
187
+ import eleven from "@elevenlabs/music"
188
+
189
+ [-] = audio xai.tts("Spoken line", voice: "eve", speed: 1.0)
190
+
191
+ # Direct music call, no trailing audio params.
192
+ [0s .. 15s] = audio eleven.music("Soft premium ad music", duration: 15, instrumental: true)
193
+
194
+ # Use a binding when you need volume or fades.
195
+ let bed = eleven.music("Soft premium ad music", duration: 15, instrumental: true)
196
+ [0s .. 15s] = audio bed, volume: 0.35, fade_out: 2s
197
+ ```
198
+
199
+ **Invalid:** `audio eleven.music("...", duration: 15), volume: 0.35` — trailing `, volume` after a direct plugin call is a parse error.
200
+
201
+ **Invalid:** `eleven.generateMusic(...)` without `import eleven from "@elevenlabs/music"`.
202
+
203
+ **Invalid:** `eleven.tts(...)` — not a registered function; use `xai.tts(...)`.
204
+
205
+ **Invalid:** `cf.video(...)` without `import cf from "@scenerok/cloudflare"`.
206
+
207
+ ## Rule 9: Filters
208
+
209
+ ```vidscript
210
+ [0s .. 15s] = filter "vignette", intensity: 0.3
211
+ [0s .. 15s] = filter "saturation", amount: 1.12
212
+ ```
213
+
214
+ Filters are optional finishing tools, not required ingredients. Use them only when they improve the visual result. Each filter has its own parameter name (`saturation` takes `amount`, `blur` takes `radius`); a wrong name is ignored without an error. The table is in `editing-actions.md` → Color and finishing.
215
+
216
+ A `filter` line grades everything in its window. To grade one clip, add `target: clip` or write `clip.Filter("sepia", intensity: 0.6)`.
217
+
218
+ ## Rule 10: Always end with output
219
+
220
+ ```vidscript
221
+ output to "video.mp4", resolution: "1080x1920", fps: 30
222
+ ```
223
+
224
+ Do **not** use legacy `config { }` blocks — they are not part of VidScript v2.
225
+
226
+ ## Rule 11: Edits are values — place the result
227
+
228
+ `Trim`, `Speed`, `Loop`, `Crop`, `Resize`, `Mask`, `Filter`, `Overlay`, and `Composite` return a new value. Place the result in one line:
229
+
230
+ ```vidscript
231
+ input hero = "hero.mp4"
232
+ input logo = "logo.png"
233
+ [0s .. 4s] = hero.Trim(2s, 6s).Crop(420, 0, 1080, 1920)
234
+ [4s .. 8s] = hero.Trim(6s, 10s).Overlay(logo.Resize(200, 200), x: 840, y: 60)
235
+ ```
236
+
237
+ - A placed value lasts its own length (trimmed range ÷ speed × loops). Make the window that long.
238
+ - Put one video over another with `Overlay`, `Composite`, or `blend:`. Two plain clips in the same window have no defined order.
239
+ - `Mask` on its own line after the clip is placed is a compile error.
240
+ - Frame counts are written `48 frame` and use the output fps (30 if `output` has none).
241
+
242
+ All editing actions (masks, speed ramps, ducking, LUTs, timecode): `editing-actions.md`.
243
+
244
+ ## Animations (after import)
245
+
246
+ ```vidscript
247
+ import motion from "@scenerok/basic-animations"
248
+
249
+ [0s .. 2s] = text "Launch", x: "50%", y: "50%", animate: motion.popIn(0.7s)
250
+ ```
251
+
252
+ Available: `fadeIn`, `fadeOut`, `slideX`, `slideY`, `popIn`, `riseIn`, `swingIn`, `glitchIn`, `float`, `typewriter`.
253
+
254
+ ## Validate before render
255
+
256
+ ```bash
257
+ scenerok validate my-video.vid
258
+ ```
259
+
260
+ Each error line includes `Line N:C — message` when the server returns location info.
261
+
262
+ ## Bundled examples
263
+
264
+ The `@scenerok/cli` npm package ships working scripts in `examples/system/`: `minimal-text-reel.vid` (text only), `product-launch.vid` (your own video + text), `ecom-product-launch.vid` (generated product visuals + CTA), `3-tips-fitness.vid` (several `[-]` blocks), `rokmilk-chocolate-promo.vid` (15 s generated promo).
265
+
266
+ Full grammar: `vidscript-guide.md`.
@@ -0,0 +1,71 @@
1
+ # SceneRok Compose Workflow
2
+
3
+ ## Pipeline
4
+
5
+ 1. **Understand the goal** — promo, testimonial, meme, code demo, etc.
6
+ 2. **Choose authoring** — VidScript (`.vid`) by default and for every editing action; TypeScript `@scenerok/sdk` (`.ts`, `sdk-guide.md`) only for loops or computed timing
7
+ 3. **Plan the structure** — time blocks, durations, inputs
8
+ 4. **Gather assets** — URLs, local paths, generated clips, selective website screenshots
9
+ 5. **Probe asset type and dimensions** — `loadVideo` / media stdlib, or `file` / `ffprobe` / `sips` / `identify`; never guess
10
+ 6. **Use images directly when useful** — VidScript `video image_input`; SDK `video(path)` / `loadVideo`
11
+ 7. **Choose plugin modality** — still / t2v / i2v / ref2v / extend / TTS / music (`ai-models.md`, `tts.md`, `music.md`)
12
+ 8. **Compose** — measured dimensions, `area:` / `t.grid` for text, symbolic durations (`vo.duration` / returned node `.duration`), entry/exit beats
13
+ 9. **Validate** — `scenerok validate script.vid` or `scenerok validate scene.ts`
14
+ 10. **Deep-validate (VidScript)** — for scripts with TTS/generated media: `scenerok validate script.vid --generate-assets --report-json` (billed; assets cache for the render). SDK plugins generate during `scenerok render` instead. Fix `offCanvas`/`wasShrunk` text, `collisions`, and unintended `audio.overlaps`, then re-validate.
15
+ 11. **Render** — `scenerok render script.vid --watch` or `scenerok render scene.ts --watch`
16
+ 12. **Check the render** — `scenerok lint-video <render-id> --cost medium --json` (billed); fix and re-render if it reports problems. `scenerok render script.vid --validate` does render and check in one step
17
+ 13. **Deliver** — share download URL when complete
18
+
19
+ ## Website URL asset workflow
20
+
21
+ When the user provides a product, company, landing page, or ecommerce URL:
22
+
23
+ 1. Visit the URL with a browser tool before composing.
24
+ 2. Capture screenshots sparingly — above-fold, product closeups, pricing cards. Avoid full-page backgrounds.
25
+ 3. Crop to the visual evidence needed.
26
+ 4. Save product images, logos, app screenshots when accessible.
27
+ 5. Probe saved asset dimensions before composing.
28
+ 6. Use stills as timeline inputs or feed into `xai.imageToVideo` / `xai.referenceToVideo` (VidScript or SDK).
29
+ 7. Combine real assets with generated clips, text, and music.
30
+ 8. Scale from measured aspect ratio; keep primary visuals in ~80–88% frame width for 9:16.
31
+ 9. Animate assets: `motion.popIn` / SDK `popIn`, `fadeIn`, `slideY`.
32
+ 10. Generative prompts must require **no text, logos, watermarks, or readable UI** in AI output — add copy with `text`.
33
+ 11. Do not invent product claims — extract from site or ask the user.
34
+
35
+ ## Best practices
36
+
37
+ - VidScript: `[-]` for channel-aware auto-append; SDK: `t.push(...)` / `t['-'] = ...`
38
+ - Never guess TTS/music durations — bind the result and use `.duration`
39
+ - Never guess text coordinates — VidScript `area: "title"`; SDK `t.grid(...)` + `text(..., { area: 'title' })`
40
+ - Named arguments (VidScript): `hero.Trim(start: 0s, end: 5s)`
41
+ - 1080×1920 vertical (TikTok/Instagram); 1920×1080 horizontal (YouTube)
42
+ - Hook in first 3 seconds; high-contrast text with stroke when needed
43
+ - Each render costs tokens (renders + AI plugins)
44
+
45
+ ## CLI commands
46
+
47
+ ```bash
48
+ scenerok auth login
49
+ scenerok validate script.vid
50
+ scenerok validate scene.ts
51
+ scenerok render script.vid --watch
52
+ scenerok render scene.ts --watch
53
+ scenerok status <render-id>
54
+ scenerok skills install <platform> # installs the skill (SKILL.md + references)
55
+ scenerok skills check [--json] # is the installed copy current?
56
+ scenerok skills update # refresh it from scenerok.com
57
+ ```
58
+
59
+ ## Error handling
60
+
61
+ If render fails: check `scenerok status <id>`, fix missing assets or syntax, re-render.
62
+
63
+ ## Sample video types
64
+
65
+ - **Product promo** — hero + headline + CTA
66
+ - **Social hook** — fast cuts, bold text
67
+ - **Testimonial** — speaker clip + quote overlay
68
+ - **Meme remix** — reaction clip + punchlines
69
+ - **Title sequence** — background + glitch + typography
70
+
71
+ For brand colors, logos, and accents see `brand-setup.md`. Ask the user only when your environment allows conversation and brand context is missing.