@scenerok/sdk 0.27.0 → 0.29.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scenerok/sdk",
3
- "version": "0.27.0",
3
+ "version": "0.29.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",
@@ -35,15 +35,16 @@ Copy this checklist into your notes and work through it:
35
35
 
36
36
  ```text
37
37
  - [ ] 1. Identify the environment (web editor, CLI, ChatGPT, MCP, chat without tools)
38
- - [ ] 2. Pick the closest recipe in recipes.md and read look-and-feel.md
39
- - [ ] 3. Gather pictures: page images, screenshots, logo, footage, or generated
40
- stills (look-and-feel.md → Sourcing imagery). Probe each one; crop with ffmpeg
41
- - [ ] 4. Decide the look: palette, two fonts, type sizes, beats. Write them as `let`s
42
- - [ ] 5. Write the script from the recipe; read other references only as needed
43
- - [ ] 6. Validate. Fix every error and aesthetic warning; validate again until clean
38
+ - [ ] 2. List the beats. For each: its job and the one thing the viewer takes away
39
+ - [ ] 3. Put the material on the table before choosing: the source's own pictures,
40
+ screenshots, logo, footage, numbers, words. Probe each file
41
+ - [ ] 4. Choose each beat's tools with choosing.md; write one line of why per beat
42
+ - [ ] 5. Decide the look (palette, fonts, sizes) as `let`s: look-and-feel.md
43
+ - [ ] 6. Write the script ([recipes.md](references/recipes.md) has the visual patterns; a plugin's README has its story). Validate: fix every error;
44
+ read every aesthetic warning as a question about your choice
44
45
  - [ ] 7. Uses TTS or generated media: deep-validate and fix the report (CLI only)
45
- - [ ] 8. Render, pull one frame per beat, look at them, run the freeze check
46
- - [ ] 9. Fix what the frames show and render again. Done = the quality gate passes
46
+ - [ ] 8. Render, pull one frame per beat, look, and answer the review questions
47
+ - [ ] 9. Fix what the frames show and render again
47
48
  ```
48
49
 
49
50
  With the CLI:
@@ -58,12 +59,12 @@ scenerok lint-video <render-id> --cost medium --json # billed
58
59
  `scenerok render script.vid --validate` renders and checks the MP4 in one step.
59
60
 
60
61
  With marketplace plugins: search, inspect, dry-run, then run a pinned ref
61
- (full workflow in [plugins.md](references/plugins.md)). A plugin's output must
62
- pass the same quality gate. When a plugin's template is text over a flat
63
- colour, draft it (`scenerok plugin draft … --out draft.vid`), add the
64
- pictures and motion from [recipes.md](references/recipes.md), then
65
- `scenerok plugin render-draft <id> --vidscript draft.vid`. Today that covers
66
- the first-party `listing-promo` and `release-video` templates.
62
+ (full workflow in [plugins.md](references/plugins.md)). Review a plugin's
63
+ output with the same questions as your own work. Today the first-party
64
+ `listing-promo` and `release-video` templates set every beat as text over a
65
+ flat colour and leave the product images unused. When the request calls for
66
+ more, draft (`scenerok plugin draft … --out draft.vid`), change the beats that
67
+ need it, then `scenerok plugin render-draft <id> --vidscript draft.vid`.
67
68
 
68
69
  ```bash
69
70
  scenerok plugin search "product promo"
@@ -101,42 +102,58 @@ ChatGPT, and MCP have their own validate and render calls but no deep
101
102
  validation or MP4 check, and can't read local files:
102
103
  [environments.md](references/environments.md).
103
104
 
104
- ## Quality gate
105
-
106
- `validate` tells you the script is valid, not that the video is good. A video
107
- is done only when all of these hold. Text over a flat colour fails, however
108
- clean the script.
109
-
110
- 1. **A picture under every beat.** Each beat shows a real asset (product
111
- photo, screenshot, logo, footage, screen recording) or a generated image or
112
- video. No beat is type on a plain colour.
113
- 2. **Nothing stands still.** Every picture and text line has `animate:` with an
114
- entrance; anything that leaves before the end also has an exit. Stills get a
115
- slow push; logos float. After rendering, this prints nothing (no hold of 3 s
116
- or longer; a `freeze_start` with no `freeze_end` runs to the end):
117
- `ffmpeg -hide_banner -i out.mp4 -vf freezedetect=n=0.003:d=3 -map 0:v -f null - 2>&1 | grep freeze_start`
118
- 3. **A deliberate look.** The script opens with `let` values for its palette
119
- (bg, ink, muted, one accent) and its two fonts. Sizes follow the type scale
120
- in [look-and-feel.md](references/look-and-feel.md): at least 44 px on a
121
- 1920 px tall canvas.
122
- 4. **One grade.** `filter "cdl"` and/or `vignette` (or a LUT from an HTTPS
123
- URL) spans the whole video.
124
- 5. **Sound.** A music bed, a voiceover, or the footage's own audio, unless the
125
- user asked for silence.
126
- 6. **Validate clean.** Fix every error and every aesthetic warning, or write
127
- down why a warning doesn't apply (each recipe names the warnings it accepts
128
- and why).
129
- 7. **Looked at.** Render, pull one frame per beat, open the frames, and fix what
130
- you see: wrapped or colliding text, black boxes where a picture should be,
131
- a fallback font, empty bands. Then render again. Validate's text sizes are
132
- estimates, so only the frames show the real result.
105
+ ## Review: look, then ask
106
+
107
+ `validate` tells you the script is valid. Only the rendered frames tell you
108
+ whether the video works. Render, pull one frame per beat, open the frames, and
109
+ ask:
110
+
111
+ 1. **Does each beat do its job at a glance?** A viewer on a phone with the sound
112
+ off gets the beat's point in under two seconds. If not, the job is unclear
113
+ or the tool fights the content.
114
+ 2. **Is every element a choice?** For each picture, motion, transition, grade
115
+ and sound, you can say what it does for its beat. If the honest answer is
116
+ "the recipe had one", cut it. A beat of plain text on a still frame is a
117
+ good choice when you can say why (see `choosing.md`).
118
+ 3. **Did you look at what the source offered?** If the user gave a page, a repo,
119
+ footage or a brand, put its pictures on the table before choosing. Not using
120
+ them can be right. Never having looked is the failure that produced
121
+ text-only videos.
122
+ 4. **Can it be read?** Text is at least 2.2 % of the frame height (44 px at
123
+ 1920), inside the safe area, contrasted against what is behind it, and on
124
+ screen long enough to read.
125
+ 5. **Does the frame match your intent?** Look for wrapped or colliding text,
126
+ black boxes where a picture should be, fallback fonts, letterbox bands, a
127
+ block smaller than you pictured.
128
+ 6. **Is it true?** Every claim, price and number comes from the source.
129
+
130
+ Questions 4 and 6 are facts, not taste: fix them. The rest call for judgement.
131
+ Answer them, change what you would defend poorly, and render again.
133
132
 
134
133
  ```bash
135
134
  for t in 1.5 5 9 13; do ffmpeg -loglevel error -y -ss $t -i out.mp4 -frames:v 1 frame-$t.png; done
136
135
  ```
137
136
 
138
- Without a shell (web editor, ChatGPT, MCP), check 1-6 against the script and
139
- ask the user to watch the preview before you call it done.
137
+ A diagnostic you can run when you intended motion: this lists every stretch
138
+ of 3 s or more where the picture doesn't change (a `freeze_start` with no
139
+ `freeze_end` runs to the end). A held quote, price or line of code can be
140
+ right, so treat the list as information, not a verdict.
141
+ `ffmpeg -hide_banner -i out.mp4 -vf freezedetect=n=0.003:d=3 -map 0:v -f null - 2>&1 | grep freeze_`
142
+
143
+ Without a shell (web editor, ChatGPT, MCP), ask questions 1-4 and 6 of the
144
+ script itself, and have the user watch the preview.
145
+
146
+ ## Who owns what
147
+
148
+ This skill owns the **language and the craft**: VidScript, the tool repertoire
149
+ and how to choose from it, the look-and-feel numbers, how to source imagery, and
150
+ how to verify a frame.
151
+
152
+ A **plugin owns its domain**: the order of beats, the copy rules, the prompt that
153
+ writes the words, and the template that times them. When a plugin covers the job,
154
+ use it and then improve the *look* of its beats — do not restate its story here.
155
+ Product promo, changelog and talking-head stories live in their packages'
156
+ READMEs; [recipes.md](references/recipes.md) is visual patterns only.
140
157
 
141
158
  ## Rules that prevent most failures
142
159
 
@@ -168,7 +185,9 @@ Read the ones the task needs. Paths are relative to this file.
168
185
 
169
186
  | Task | Read |
170
187
  | --- | --- |
171
- | Any video | [recipes.md](references/recipes.md) and [look-and-feel.md](references/look-and-feel.md) (always): complete product promo, release notes and talking-head scripts; palette, type scale, safe areas, motion, sourcing pictures |
188
+ | Any video | [choosing.md](references/choosing.md) (always): how to pick tools for a beat, with worked choices |
189
+ | What a tool looks like, is for, and fights; tools by job | [repertoire.md](references/repertoire.md) (generated; search it by job or name) |
190
+ | Visual patterns to adapt; palette, type scale, safe areas, sourcing pictures | [recipes.md](references/recipes.md), [look-and-feel.md](references/look-and-feel.md) |
172
191
  | Any VidScript | [vidscript-strict.md](references/vidscript-strict.md) (always) |
173
192
  | Editing and compositing: trims, speed, reverse, freeze, picture-in-picture, blend modes, masks, crops, split screens, audio mixing and ducking, grading and LUTs, captions, timecode | [editing-actions.md](references/editing-actions.md) |
174
193
  | Full grammar | [vidscript-guide.md](references/vidscript-guide.md) |
@@ -196,25 +215,33 @@ chat apps are there too: `consumer-chat-apps.md`,
196
215
  `chatgpt-gpt-instructions.md`, `gemini-gem-instructions.md`, `grok-skill.md`.
197
216
  Previews of every catalog item: https://scenerok.com/catalog.
198
217
 
199
- ## One beat, done properly
218
+ ## Two beats, two choices
200
219
 
201
- The smallest unit that passes the gate: a real picture with a push, copy that
202
- enters and leaves, a grade, and sound. A video is several of these; the full
203
- scripts are in [recipes.md](references/recipes.md).
220
+ Each beat gets the tools its job calls for and nothing else. Below, an
221
+ "establish" beat uses a real photo: the push gives a 4 s still a sense of time.
222
+ A "quote" beat is plain text on a flat colour with no motion, because the words
223
+ are the content and the reader needs to be left alone with them. Both are
224
+ finished. `choosing.md` walks through more choices like these.
204
225
 
205
226
  ```vidscript
206
227
  import motion from "@scenerok/basic-animations"
207
228
 
229
+ let bg = "#0A0C10"
208
230
  let ink = "#F4F6FA"
231
+ let muted = "#A3ADBD"
209
232
  let display = "Archivo Black"
233
+ let body = "Inter"
210
234
 
211
235
  input shot = "https://cdn.example.com/product-lifestyle.jpg" # 1080x1920, probed
212
- input bed = "https://cdn.example.com/music.mp3"
213
236
 
237
+ # Establish: the product in its place. A slow push, a headline that arrives.
214
238
  [0s .. 4s] = shot, width: 1080, height: 1920, x: 0, y: 0, animate: { type: "scale", from: { scale: 1 }, to: { scale: 1.08 }, easing: "linear" }
215
- [0.2s .. 4s] = text "Cleans while you're out", font: display, size: 96, color: ink, x: "50%", y: "28%", max_width: "86%", align: center, shadow_color: "#000000", shadow_blur: 24, animate: [motion.riseIn(0.5s, 60), motion.fadeOut(0.3s)]
216
- [0s .. 4s] = filter "vignette", intensity: 0.3
217
- [0s .. 4s] = audio bed, volume: 0.5, fade_out: 0.5s
239
+ [0.2s .. 4s] = text "Cleans while you're out", font: display, size: 96, color: ink, x: "50%", y: "28%", max_width: "86%", align: center, shadow_color: "#000000", shadow_blur: 24, animate: motion.riseIn(0.5s, 60)
240
+
241
+ # Quote: someone's words, held still long enough to read twice.
242
+ [4s .. 9s] = solid(bg)
243
+ [4s .. 9s] = text "\"Simplicity is the ultimate sophistication.\"", font: body, size: 64, color: ink, x: "50%", y: "45%", max_width: "80%", align: center
244
+ [4s .. 9s] = text "Leonardo da Vinci (attributed)", font: body, size: 44, color: muted, x: "50%", y: "56%", align: center
218
245
  output to "video.mp4", resolution: "1080x1920", fps: 30
219
246
  ```
220
247
 
@@ -52,7 +52,7 @@ Param resolution: **named > positional > default**.
52
52
  | Maps / liquid-glass / app-showcase | Ignore user params | Use for demo aesthetic only, or hand-author |
53
53
  | Adapter blocks | No inline audio/text siblings | Put `audio`, `text`, `filter` on separate time blocks |
54
54
  | `logo_outro` | Renders upstream demo's Figma-style mark when no logo param given | Pass `brand: "scenerok"` or `logoUrl: "<image url>"` |
55
- | `code_*` and most blocks in 9:16 | Designed at 1920x1080 and scaled to fit: 56 % size with empty bands above and below (lower thirds have native 9:16 layouts) | Use them in 16:9; in 9:16 build a code card from `text` lines (`recipes.md` → Release notes) |
55
+ | Most blocks in 9:16 | Designed at 1920x1080 and scaled to fit: 56 % size in a centred band. The `code_snippet_*` VS Code themes, `code_diff` and most lower thirds have their own 9:16 layouts | Each record in `repertoire.md` says how it behaves at 9:16 |
56
56
  | `text_counter_stat` | `suffix` defaults to `"+"`, so 12 reads "12+" | Pass `suffix: ""` unless the number really is a floor |
57
57
 
58
58
  ## Two-phase compose recipe