@scenerok/sdk 0.6.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.
- package/README.md +10 -0
- package/package.json +3 -1
- package/skills/scenerok/SKILL.md +147 -0
- package/skills/scenerok/references/ai-models.md +64 -0
- package/skills/scenerok/references/animations-catalog.md +226 -0
- package/skills/scenerok/references/animations-picker.md +88 -0
- package/skills/scenerok/references/brand-setup.md +71 -0
- package/skills/scenerok/references/catalog-index.json +1954 -0
- package/skills/scenerok/references/editing-actions.md +518 -0
- package/skills/scenerok/references/environments.md +72 -0
- package/skills/scenerok/references/intent-router.md +71 -0
- package/skills/scenerok/references/media-stdlib.md +65 -0
- package/skills/scenerok/references/music.md +50 -0
- package/skills/scenerok/references/sdk-guide.md +201 -0
- package/skills/scenerok/references/shaders-filters.md +100 -0
- package/skills/scenerok/references/text-styles.md +88 -0
- package/skills/scenerok/references/transitions-catalog.md +57 -0
- package/skills/scenerok/references/tts.md +64 -0
- package/skills/scenerok/references/vidscript-guide.md +721 -0
- package/skills/scenerok/references/vidscript-sample.md +44 -0
- package/skills/scenerok/references/vidscript-strict.md +266 -0
- package/skills/scenerok/references/workflow.md +71 -0
package/README.md
CHANGED
|
@@ -8,6 +8,16 @@ TypeScript-first authoring SDK for SceneRok. Agents use this for **complex, data
|
|
|
8
8
|
npm install @scenerok/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Agent skill
|
|
12
|
+
|
|
13
|
+
The package includes the scenerok agent skill at `skills/scenerok/` (`SKILL.md` plus `references/`): how to write, validate, and render SceneRok scenes in TypeScript or VidScript. Copy that directory into your agent's skills folder, for example:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cp -r node_modules/@scenerok/sdk/skills/scenerok ~/.claude/skills/
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
or install it with the CLI: `npx @scenerok/cli skills install claude`.
|
|
20
|
+
|
|
11
21
|
## Quick start
|
|
12
22
|
|
|
13
23
|
```ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scenerok/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.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",
|
|
@@ -37,9 +37,11 @@
|
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"dist",
|
|
40
|
+
"skills",
|
|
40
41
|
"README.md"
|
|
41
42
|
],
|
|
42
43
|
"scripts": {
|
|
44
|
+
"prebuild": "node ../../scripts/copy-scenerok-skill.mjs .",
|
|
43
45
|
"build": "tsc -p tsconfig.json",
|
|
44
46
|
"dev": "tsc --watch",
|
|
45
47
|
"test": "node --import tsx --test src/**/*.test.ts"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scenerok
|
|
3
|
+
description: >-
|
|
4
|
+
Writes, validates, and renders SceneRok videos from VidScript (.vid) or the
|
|
5
|
+
TypeScript @scenerok/sdk: promos, reels, explainers, social cards, motion
|
|
6
|
+
graphics, and edits of existing footage (trims, speed changes, picture-in-picture,
|
|
7
|
+
blend modes, masks, crops, color grades, LUTs, audio mixing and ducking, captions,
|
|
8
|
+
timecode). Use when the user wants to make or edit a video with SceneRok, or
|
|
9
|
+
mentions VidScript, a .vid file, @scenerok/sdk, the scenerok CLI, or the SceneRok
|
|
10
|
+
MCP tools.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# SceneRok
|
|
14
|
+
|
|
15
|
+
SceneRok turns a script into an MP4. Write the script in VidScript or in
|
|
16
|
+
TypeScript with `@scenerok/sdk`; both compile to the same timeline. Then
|
|
17
|
+
validate it, render it, and check the rendered file.
|
|
18
|
+
|
|
19
|
+
## Choose the language
|
|
20
|
+
|
|
21
|
+
| | VidScript (`.vid`) | TypeScript (`@scenerok/sdk`, `.ts`) |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| Use for | Promos, reels, templates, and every editing action: masks, blends, crops, speed ramps, ducking, LUTs, timecode | Timelines built by code: loops over data, computed timing across many clips |
|
|
24
|
+
| Start with | [vidscript-strict.md](references/vidscript-strict.md) | [sdk-guide.md](references/sdk-guide.md) |
|
|
25
|
+
|
|
26
|
+
The SDK has no masks, blends, crops, ducking, or delivery settings. When a
|
|
27
|
+
scene needs both, write it in VidScript and `import` the SDK scene into it.
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
Copy this checklist into your notes and work through it:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
- [ ] 1. Identify the environment (web editor, CLI, ChatGPT, MCP, chat without tools)
|
|
35
|
+
- [ ] 2. Classify the request; read only the references it needs (table below)
|
|
36
|
+
- [ ] 3. Branded promo with unknown colors or logo: ask once
|
|
37
|
+
- [ ] 4. Probe real assets: type, width, height, duration
|
|
38
|
+
- [ ] 5. Write the script
|
|
39
|
+
- [ ] 6. Validate. Fix every error and validate again until clean
|
|
40
|
+
- [ ] 7. Uses TTS or generated media: deep-validate and fix the report (CLI only)
|
|
41
|
+
- [ ] 8. Render
|
|
42
|
+
- [ ] 9. Check the rendered MP4; fix and repeat from step 6 if it reports problems (CLI only)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
With the CLI:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
scenerok validate script.vid # or scene.ts
|
|
49
|
+
scenerok validate script.vid --generate-assets --report-json # billed; VidScript only
|
|
50
|
+
scenerok render script.vid --watch
|
|
51
|
+
scenerok lint-video <render-id> --cost medium --json # billed
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`scenerok render script.vid --validate` renders and checks the MP4 in one step.
|
|
55
|
+
|
|
56
|
+
The deep validation generates the real speech and media (cached for the
|
|
57
|
+
render) and reports text that runs off-canvas or was shrunk (`offCanvas`,
|
|
58
|
+
`wasShrunk`), overlapping elements (`collisions`), and voice-over-voice
|
|
59
|
+
overlaps (`audio.overlaps`; music under voice is fine). The web editor,
|
|
60
|
+
ChatGPT, and MCP have their own validate and render calls but no deep
|
|
61
|
+
validation or MP4 check, and can't read local files:
|
|
62
|
+
[environments.md](references/environments.md).
|
|
63
|
+
|
|
64
|
+
## Rules that prevent most failures
|
|
65
|
+
|
|
66
|
+
1. **Import before calling.** `import xai from "@scenerok/xai"`, then
|
|
67
|
+
`xai.tts(…)`. The same for `@scenerok/cloudflare`, `@elevenlabs/music`,
|
|
68
|
+
`@scenerok/basic-animations`, `@scenerok/animations`,
|
|
69
|
+
`@scenerok/transitions`, and `@scenerok/media`.
|
|
70
|
+
2. **Never guess a duration.** Bind generated media and use its length:
|
|
71
|
+
`let vo = xai.tts(…)` then `[0 .. vo.duration] = audio vo`.
|
|
72
|
+
3. **Never guess text coordinates.** Use `area: "title"` (also `stage`,
|
|
73
|
+
`lower-third`, `caption`, or your own `grid`).
|
|
74
|
+
4. **No text in generated images or video.** Every prompt asks for no text,
|
|
75
|
+
letters, logos, or watermarks; put all copy in `text` lines.
|
|
76
|
+
5. **Edits return values; place the result.**
|
|
77
|
+
`[0s .. 4s] = clip.Trim(2s, 6s).Crop(420, 0, 1080, 1920)`. Put one video
|
|
78
|
+
over another with `Overlay`, `Composite`, or `blend:`.
|
|
79
|
+
6. **Use only documented syntax.** Don't invent functions or parameters. A
|
|
80
|
+
validation error names the problem; fix that line rather than rewriting the
|
|
81
|
+
script.
|
|
82
|
+
|
|
83
|
+
## References
|
|
84
|
+
|
|
85
|
+
Read the ones the task needs. Paths are relative to this file.
|
|
86
|
+
|
|
87
|
+
| Task | Read |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| Any VidScript | [vidscript-strict.md](references/vidscript-strict.md) (always) |
|
|
90
|
+
| 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) |
|
|
91
|
+
| Full grammar | [vidscript-guide.md](references/vidscript-guide.md) |
|
|
92
|
+
| A complete commented promo script | [vidscript-sample.md](references/vidscript-sample.md) |
|
|
93
|
+
| TypeScript SDK | [sdk-guide.md](references/sdk-guide.md) |
|
|
94
|
+
| Probing media, grabbing frames, beats | [media-stdlib.md](references/media-stdlib.md) |
|
|
95
|
+
| Generated images and video | [ai-models.md](references/ai-models.md) |
|
|
96
|
+
| Voiceover | [tts.md](references/tts.md) |
|
|
97
|
+
| Music beds | [music.md](references/music.md) |
|
|
98
|
+
| Animated blocks: lower thirds, code, social cards, text animations, custom HTML | [animations-picker.md](references/animations-picker.md), then [animations-catalog.md](references/animations-catalog.md) for every parameter |
|
|
99
|
+
| Titles animated with motion primitives | [text-styles.md](references/text-styles.md) |
|
|
100
|
+
| Scene transitions | [transitions-catalog.md](references/transitions-catalog.md) |
|
|
101
|
+
| Filters, VFX, custom shaders | [shaders-filters.md](references/shaders-filters.md) |
|
|
102
|
+
| A promo from a product URL | [workflow.md](references/workflow.md), [brand-setup.md](references/brand-setup.md) |
|
|
103
|
+
| Which workflow fits the request | [intent-router.md](references/intent-router.md) |
|
|
104
|
+
| Where you are running and what you can call | [environments.md](references/environments.md) |
|
|
105
|
+
| Every catalog item as data | [catalog-index.json](references/catalog-index.json) |
|
|
106
|
+
|
|
107
|
+
Without local files (for example, only this text was pasted into a chat),
|
|
108
|
+
fetch any reference from
|
|
109
|
+
`https://scenerok.com/.well-known/agent-skills/<filename>`. Setup guides for
|
|
110
|
+
chat apps are there too: `consumer-chat-apps.md`,
|
|
111
|
+
`chatgpt-gpt-instructions.md`, `gemini-gem-instructions.md`, `grok-skill.md`.
|
|
112
|
+
Previews of every catalog item: https://scenerok.com/catalog.
|
|
113
|
+
|
|
114
|
+
## Minimal VidScript
|
|
115
|
+
|
|
116
|
+
```vidscript
|
|
117
|
+
import motion from "@scenerok/basic-animations"
|
|
118
|
+
|
|
119
|
+
input hero = "https://cdn.example.com/clip.mp4"
|
|
120
|
+
[0s .. 4s] = hero.Trim(1s, 5s)
|
|
121
|
+
[0s .. 3s] = text "Hello", style: title, color: "#FFFFFF", area: "title", animate: motion.fadeIn(0.8s)
|
|
122
|
+
output to "video.mp4", resolution: "1080x1920", fps: 30
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Minimal SDK scene
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { timeline, text, s, fadeIn } from '@scenerok/sdk'
|
|
129
|
+
|
|
130
|
+
export default function main() {
|
|
131
|
+
const t = timeline({ width: 1080, height: 1920, fps: 30 })
|
|
132
|
+
t.grid({
|
|
133
|
+
rows: '16% 1fr 18% 10%',
|
|
134
|
+
areas: ['title', 'stage', 'lower-third', 'caption'],
|
|
135
|
+
})
|
|
136
|
+
t[0][s(3)] = text('SceneRok', { size: 72, area: 'title' }).animate(fadeIn(s(0.4)))
|
|
137
|
+
t[3][5] = text('Text to video', { size: 40, area: 'lower-third' })
|
|
138
|
+
return t.toIR()
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Validate and render it like a `.vid`: `scenerok validate scene.ts`.
|
|
143
|
+
|
|
144
|
+
## Keeping the skill current
|
|
145
|
+
|
|
146
|
+
`scenerok skills check` compares the installed copy with scenerok.com;
|
|
147
|
+
`scenerok skills update` downloads what changed.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# AI Models — Video and Image Generation
|
|
2
|
+
|
|
3
|
+
## Modality picker
|
|
4
|
+
|
|
5
|
+
| Intent | API | When |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| Clean still / key visual | `xai.image(...)` · `cf.image(...)` | Product shot, poster frame |
|
|
8
|
+
| Text-to-video | `xai.imagine(...)` · `xai.genVideo(...)` · `cf.video(...)` | B-roll, lifestyle, cinematic |
|
|
9
|
+
| Animate one image | `xai.imageToVideo(img, prompt, ...)` · `cf.imageToVideo(...)` | Product photo → motion |
|
|
10
|
+
| Multi-reference scene | `xai.referenceToVideo([imgs], prompt, ...)` | Brand elements guide scene |
|
|
11
|
+
| Extend existing clip | `xai.extendVideo(...)` · `cf.extendVideo(...)` | Continue generated clip |
|
|
12
|
+
|
|
13
|
+
**Always import:** `import xai from "@scenerok/xai"` and/or `import cf from "@scenerok/cloudflare"`.
|
|
14
|
+
|
|
15
|
+
Generative prompts must require: no text, no words, no letters, no captions, no logos, no watermarks, no readable UI copy.
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
### Grok genVideo()
|
|
20
|
+
|
|
21
|
+
Explicit duration, resolution, and aspect ratio for text-to-video.
|
|
22
|
+
|
|
23
|
+
**Landscape 8 s**
|
|
24
|
+
|
|
25
|
+
```vidscript
|
|
26
|
+
import xai from "@scenerok/xai"
|
|
27
|
+
|
|
28
|
+
[- 3s] = video xai.genVideo("Timelapse of clouds over desert mesas, wide cinematic, anamorphic flare", duration: 3, aspect_ratio: "16:9", resolution: "720p")
|
|
29
|
+
|
|
30
|
+
[prev .. prev + 0.8s] = text "genVideo()", font: "Inter Bold", size: 44, color: "#FFFFFF", shadow_blur: 10, align: "center", y: "88%"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Vertical 6 s reel**
|
|
34
|
+
|
|
35
|
+
```vidscript
|
|
36
|
+
import xai from "@scenerok/xai"
|
|
37
|
+
|
|
38
|
+
[- 3s] = video xai.genVideo("Drone shot over a futuristic city at sunset, lens flare, cinematic", duration: 3, aspect_ratio: "9:16", resolution: "720p")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Grok imagine()
|
|
42
|
+
|
|
43
|
+
One-call text-to-video. Default 5 s, 720p, 9:16.
|
|
44
|
+
|
|
45
|
+
**Ocean drone**
|
|
46
|
+
|
|
47
|
+
```vidscript
|
|
48
|
+
import xai from "@scenerok/xai"
|
|
49
|
+
|
|
50
|
+
[- 3s] = video xai.imagine("Slow aerial drone over turquoise ocean waves, golden hour, cinematic", aspect_ratio: "16:9", resolution: "720p")
|
|
51
|
+
|
|
52
|
+
[prev .. prev + 0.8s] = text "imagine()", font: "Inter Bold", size: 48, color: "#FFFFFF", align: "center", y: "85%"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Street market**
|
|
56
|
+
|
|
57
|
+
```vidscript
|
|
58
|
+
import xai from "@scenerok/xai"
|
|
59
|
+
|
|
60
|
+
[- 3s] = video xai.imagine("A neon-lit street market at night, cinematic, volumetric light", aspect_ratio: "9:16", resolution: "720p")
|
|
61
|
+
|
|
62
|
+
[prev .. prev + 0.8s] = text "Grok imagine()", font: "Inter Bold", size: 56, color: "#FFFFFF", shadow_color: "#000000", shadow_blur: 12, position: "bottom", align: "center"
|
|
63
|
+
```
|
|
64
|
+
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Animations Catalog
|
|
2
|
+
|
|
3
|
+
All `animations.<fn>(...)` blocks from `@scenerok/animations`. Total: **77** entries.
|
|
4
|
+
|
|
5
|
+
```vidscript
|
|
6
|
+
import animations from "@scenerok/animations"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
| fn | family | verified | defaultDuration | params |
|
|
10
|
+
| --- | --- | --- | --- | --- |
|
|
11
|
+
| `app_showcase` | other | yes | 6s | positional: `imageUrl` · named: `imageUrl, userName, userRole, tagline, accentColor` |
|
|
12
|
+
| `apple_money_count` | other | yes | 5s | positional: `amount` · named: `amount, currency, accentColor` |
|
|
13
|
+
| `blend_caption` | lower-third | yes | 5s | positional: `text` · named: `text, color` |
|
|
14
|
+
| `blue_sweater_intro_video` | other | yes | 12s | positional: `creatorName` · named: `headline, creatorName, creatorHandle, creatorBio, avatarUrl` |
|
|
15
|
+
| `code_3d_extrude` | code-anim | yes | 8s | positional: `code` · named: `code, lang, theme, filename` |
|
|
16
|
+
| `code_diff` | code-anim | yes | 6s | positional: `from, to` · named: `from, to, lang, theme` |
|
|
17
|
+
| `code_highlight` | code-anim | yes | 5s | positional: `code` · named: `code, lang, theme, filename` |
|
|
18
|
+
| `code_morph` | code-anim | yes | 7s | positional: `from, to` · named: `from, to, lang, theme` |
|
|
19
|
+
| `code_particle_assemble` | code-anim | yes | 8s | positional: `code` · named: `code, lang, theme, filename` |
|
|
20
|
+
| `code_scroll` | code-anim | yes | 6s | positional: `code` · named: `code, lang, theme, filename` |
|
|
21
|
+
| `code_shader_dissolve` | code-anim | yes | 7s | positional: `code` · named: `code, lang, theme, filename` |
|
|
22
|
+
| `code_snippet_apple_terminal_basic` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
23
|
+
| `code_snippet_apple_terminal_clear_dark` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
24
|
+
| `code_snippet_apple_terminal_clear_light` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
25
|
+
| `code_snippet_apple_terminal_grass` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
26
|
+
| `code_snippet_apple_terminal_homebrew` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
27
|
+
| `code_snippet_apple_terminal_man_page` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
28
|
+
| `code_snippet_apple_terminal_novel` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
29
|
+
| `code_snippet_apple_terminal_ocean` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
30
|
+
| `code_snippet_apple_terminal_pro` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
31
|
+
| `code_snippet_apple_terminal_red_sands` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
32
|
+
| `code_snippet_apple_terminal_silver_aerogel` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
33
|
+
| `code_snippet_apple_terminal_solid_colors` | code-snippet | yes | 12s | positional: `command` · named: `command, output, prompt, title` |
|
|
34
|
+
| `code_snippet_dark_2026` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
35
|
+
| `code_snippet_dark_modern` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
36
|
+
| `code_snippet_dark_plus` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
37
|
+
| `code_snippet_flight` | code-snippet | yes | 6s | positional: `code` · named: `code, lang, theme, filename` |
|
|
38
|
+
| `code_snippet_high_contrast` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
39
|
+
| `code_snippet_high_contrast_light` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
40
|
+
| `code_snippet_light_2026` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
41
|
+
| `code_snippet_light_modern` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
42
|
+
| `code_snippet_light_plus` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
43
|
+
| `code_snippet_monokai` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
44
|
+
| `code_snippet_solarized_light` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
45
|
+
| `code_snippet_visual_studio_dark` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
46
|
+
| `code_snippet_visual_studio_light` | code-snippet | yes | 11s | positional: `code` · named: `code, filename, lang` |
|
|
47
|
+
| `code_typing` | code-anim | yes | 5s | positional: `code` · named: `code, lang, theme, filename` |
|
|
48
|
+
| `instagram_follow` | social-card | yes | 5s | positional: `displayName, handle` · named: `displayName, handle, followers, avatarUrl, url` |
|
|
49
|
+
| `ios26_liquid_glass` | other | yes | 15s | positional: `(none)` · named: `(none)` |
|
|
50
|
+
| `liquid_glass_context_menu` | other | yes | 8s | positional: `fileName` · named: `fileName, fileMeta` |
|
|
51
|
+
| `liquid_glass_media_controls` | other | yes | 8s | positional: `trackTitle` · named: `trackTitle, artist` |
|
|
52
|
+
| `liquid_glass_notification` | other | yes | 8s | positional: `title` · named: `title, body, messageText` |
|
|
53
|
+
| `liquid_glass_widgets` | other | yes | 8s | positional: `showcaseTitle` · named: `showcaseTitle, showcaseDescription` |
|
|
54
|
+
| `logo_outro` | brand | yes | 6s | positional: `tagline` · named: `tagline, url, logoUrl, brand, accent` |
|
|
55
|
+
| `lower_third` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle` |
|
|
56
|
+
| `lower_third_bild` | lower-third | yes | 8s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
57
|
+
| `lt_accent_underline` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
58
|
+
| `lt_bold_block` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
59
|
+
| `lt_clean_bar` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
60
|
+
| `lt_color_block` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
61
|
+
| `lt_dark_card` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
62
|
+
| `lt_kicker_name` | lower-third | yes | 5s | positional: `kicker, title` · named: `kicker, title, accent` |
|
|
63
|
+
| `lt_mask_reveal` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
64
|
+
| `lt_side_rule` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
65
|
+
| `lt_soft_pill` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
66
|
+
| `lt_stack_bars` | lower-third | yes | 5s | positional: `title, subtitle` · named: `title, subtitle, accent, bg` |
|
|
67
|
+
| `macos_notification` | social-card | yes | 5s | positional: `appName, title` · named: `appName, timeLabel, title, body` |
|
|
68
|
+
| `macos_tahoe_liquid_glass` | other | yes | 15s | positional: `windowTitle` · named: `wallpaperUrl, windowTitle, toastBody, weatherLocation` |
|
|
69
|
+
| `news_ticker` | social-card | yes | 7s | positional: `headline` · named: `desk, time, label, headline, headlineAccent, ticker` |
|
|
70
|
+
| `reddit_post` | social-card | yes | 5s | positional: `subreddit, title` · named: `subreddit, author, title, body, votes` |
|
|
71
|
+
| `spotify_card` | social-card | yes | 5s | positional: `track, artist` · named: `track, artist` |
|
|
72
|
+
| `text_counter_stat` | text-anim | yes | 5s | positional: `value, label` · named: `value, label, prefix, suffix, color, accent` |
|
|
73
|
+
| `text_glitch_title` | text-anim | yes | 5s | positional: `text` · named: `text, color` |
|
|
74
|
+
| `text_gradient_sweep` | text-anim | yes | 5s | positional: `text` · named: `text, from, to` |
|
|
75
|
+
| `text_kinetic_words` | text-anim | yes | 5s | positional: `text` · named: `text, color, accent` |
|
|
76
|
+
| `text_line_stack` | text-anim | yes | 5s | positional: `line1, line2` · named: `line1, line2, line3, color, accent` |
|
|
77
|
+
| `text_neon_flicker` | text-anim | yes | 5s | positional: `text` · named: `text, color` |
|
|
78
|
+
| `text_scramble_decode` | text-anim | yes | 5s | positional: `text` · named: `text, color, accent` |
|
|
79
|
+
| `text_typewriter_quote` | text-anim | yes | 5s | positional: `text, author` · named: `text, author, color, accent` |
|
|
80
|
+
| `text_word_cascade` | text-anim | yes | 5s | positional: `text` · named: `text, color, accent` |
|
|
81
|
+
| `tiktok_follow` | social-card | yes | 5s | positional: `displayName, handle` · named: `displayName, handle, followers, avatarUrl, url` |
|
|
82
|
+
| `ui_3d_reveal` | other | yes | 13s | positional: `heroTitle` · named: `heroTitle, outroUrl` |
|
|
83
|
+
| `vfx_iphone_device` | other | yes | 15s | positional: `imageUrl` · named: `imageUrl` |
|
|
84
|
+
| `vpn_youtube_spot` | other | yes | 7s | positional: `headlineLine1` · named: `headlineLine1, headlineLine2, subtext, appTitle, appSubtitle` |
|
|
85
|
+
| `x_post` | social-card | yes | 5s | positional: `displayName, handle` · named: `displayName, handle, body, hashtag, timestamp` |
|
|
86
|
+
| `yt_lower_third` | lower-third | yes | 5s | positional: `channel, subscribers` · named: `channel, subscribers, avatarUrl` |
|
|
87
|
+
|
|
88
|
+
## Unverified blocks
|
|
89
|
+
|
|
90
|
+
Blocks with `verified: no` vendor upstream demo content and may ignore user params. `scenerok validate` warns but does not error.
|
|
91
|
+
|
|
92
|
+
## Text animation blocks (`text-anim` family)
|
|
93
|
+
|
|
94
|
+
Hand-authored, fully parameterized text/typography animations — staggered word reveals,
|
|
95
|
+
scramble decode, kinetic word-per-beat typography, gradient sweeps, typed quotes, masked
|
|
96
|
+
line stacks, count-up stats, RGB-split glitch, and neon flicker. All are transparent
|
|
97
|
+
overlays (composite over video/scenes), honor every param, and scale to any output size.
|
|
98
|
+
Prefer these over hand-authoring when a headline/caption/stat treatment fits; see the
|
|
99
|
+
`text-anim` rows in `animations-picker.md` for intent mapping.
|
|
100
|
+
|
|
101
|
+
## Custom HTML (bring your own animation)
|
|
102
|
+
|
|
103
|
+
`animations.custom_html(...)` renders **your own HTML/CSS/JS** through the same HyperFrames
|
|
104
|
+
pipeline as the catalog blocks. Use it when no catalog block fits and you want to hand-author
|
|
105
|
+
an animation (or an agent generates one) using standard web tech.
|
|
106
|
+
|
|
107
|
+
```vidscript
|
|
108
|
+
import animations from "@scenerok/animations"
|
|
109
|
+
|
|
110
|
+
# Each call takes exactly ONE source:
|
|
111
|
+
[0s .. 5s] = animations.custom_html(html: "<!doctype html>...") # inline HTML
|
|
112
|
+
[5s .. 10s] = animations.custom_html(src: "https://cdn.example.com/intro.html") # remote URL
|
|
113
|
+
[10s .. 15s] = animations.custom_html(src: "./anim/hero.html") # local file
|
|
114
|
+
[15s .. 20s] = animations.custom_html(src: "scenerok://asset/123") # uploaded asset
|
|
115
|
+
|
|
116
|
+
# Sizing, timing, and author params. designWidth/designHeight: native authoring size
|
|
117
|
+
# (default = output size). timelineId: default "custom-html". Any other named arg
|
|
118
|
+
# (title, accent) is forwarded to window.__BLOCK.
|
|
119
|
+
[20s .. 24s] = animations.custom_html(src: "scenerok://asset/123", designWidth: 1920, designHeight: 1080, timelineId: "my-anim", title: "Q3 Launch", accent: "#3b82f6")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Reserved named args (consumed by custom_html, NOT forwarded to `__BLOCK`): `src, html, mode,
|
|
123
|
+
designWidth, designHeight, width, height, fit, duration, timelineId, zBand, x, y, opacity,
|
|
124
|
+
responsive`. Every other named arg is forwarded to `window.__BLOCK[name]` (values become strings).
|
|
125
|
+
|
|
126
|
+
### Author contract (required)
|
|
127
|
+
|
|
128
|
+
Custom HTML is mounted in a **sandboxed cross-origin iframe** and driven one frame at a time.
|
|
129
|
+
Your HTML MUST:
|
|
130
|
+
|
|
131
|
+
1. Render on a **transparent** background, sized to its declared design dimensions
|
|
132
|
+
(e.g. `html,body { width:1920px; height:1080px; background:transparent; }`).
|
|
133
|
+
2. Register a **paused** GSAP timeline at `window.__timelines['<timelineId>']` (default
|
|
134
|
+
`custom-html`). The host calls `tl.seek(t, false)` per frame.
|
|
135
|
+
3. Treat `window.__HF_DURATION` (seconds) as "stay PAUSED — I am in the seek-driven host".
|
|
136
|
+
Auto-play only when it is `undefined`: `if (typeof window.__HF_DURATION === "undefined") tl.play();`.
|
|
137
|
+
4. Read author params from `window.__BLOCK` (e.g. `window.__BLOCK.title`).
|
|
138
|
+
5. Load libraries from the pinned allowlist below (or inline their source). GSAP + Three.js
|
|
139
|
+
are allowlisted; anything else must be pasted inline in a `<script>` tag.
|
|
140
|
+
|
|
141
|
+
### Allowlisted libraries (loadable via `<script src>` / `<link>`)
|
|
142
|
+
|
|
143
|
+
| Library | Pinned URL |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| GSAP | `https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js` |
|
|
146
|
+
| Three.js (jsdelivr) | `https://cdn.jsdelivr.net/npm/three@0.147.0/build/three.min.js` (+ `examples/js/…`) |
|
|
147
|
+
| Three.js (cdnjs) | `https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js` |
|
|
148
|
+
| Google Fonts | `https://fonts.googleapis.com/css2?family=…` (files from `fonts.gstatic.com`) |
|
|
149
|
+
|
|
150
|
+
Any **seekable** library works if you register it at `window.__timelines[id]` with a
|
|
151
|
+
`.seek(seconds, false)` method. anime.js needs a unit adapter: `window.__timelines={x:{seek:t=>anim.seek(t*1000)}}`.
|
|
152
|
+
Purely rAF-loop libraries with no time-scrubbing will NOT render frame-by-frame.
|
|
153
|
+
|
|
154
|
+
### Minimal working template (GSAP)
|
|
155
|
+
|
|
156
|
+
Copy-paste starting point that satisfies the whole contract — agents authoring custom
|
|
157
|
+
animations should start from this skeleton and only change the markup, styles, and tweens:
|
|
158
|
+
|
|
159
|
+
```html
|
|
160
|
+
<!doctype html>
|
|
161
|
+
<html lang="en">
|
|
162
|
+
<head>
|
|
163
|
+
<meta charset="UTF-8" />
|
|
164
|
+
<meta name="viewport" content="width=1920, height=1080" />
|
|
165
|
+
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
|
166
|
+
<style>
|
|
167
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
168
|
+
html, body { width: 1920px; height: 1080px; overflow: hidden; background: transparent; }
|
|
169
|
+
#hero { position: absolute; inset: 0; display: flex; align-items: center;
|
|
170
|
+
justify-content: center; font: 900 160px system-ui; color: #fff; }
|
|
171
|
+
</style>
|
|
172
|
+
</head>
|
|
173
|
+
<body>
|
|
174
|
+
<div id="hero"></div>
|
|
175
|
+
<script>
|
|
176
|
+
(function () {
|
|
177
|
+
// 1. Params arrive via window.__BLOCK (every extra named arg, stringified).
|
|
178
|
+
var B = window.__BLOCK || {};
|
|
179
|
+
document.getElementById('hero').textContent = B.title || 'Hello';
|
|
180
|
+
|
|
181
|
+
// 2. Build a PAUSED timeline; the host drives it with tl.seek(t, false) per frame.
|
|
182
|
+
window.__timelines = window.__timelines || {};
|
|
183
|
+
var tl = gsap.timeline({ paused: true });
|
|
184
|
+
tl.from('#hero', { opacity: 0, y: 80, duration: 0.8, ease: 'power3.out' }, 0);
|
|
185
|
+
tl.to('#hero', { letterSpacing: '12px', duration: 4, ease: 'none' }, 0.4);
|
|
186
|
+
|
|
187
|
+
// Optional: window.__HF_DURATION (seconds) = the mounted [start .. end] window,
|
|
188
|
+
// injected before this script runs — use it to pace beats across the full window.
|
|
189
|
+
|
|
190
|
+
window.__timelines['custom-html'] = tl; // key must match timelineId (default 'custom-html')
|
|
191
|
+
|
|
192
|
+
// 3. Standalone preview only — inside the host __HF_DURATION exists, stay paused.
|
|
193
|
+
if (typeof window.__HF_DURATION === 'undefined') tl.play();
|
|
194
|
+
})();
|
|
195
|
+
</script>
|
|
196
|
+
</body>
|
|
197
|
+
</html>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Gotchas: CSS `animation`/`transition` run on the wall clock and are NOT seek-driven — frames
|
|
201
|
+
render wrong or frozen; drive every visual change through the registered timeline (use finite
|
|
202
|
+
`repeat:` counts for loops, never `repeat: -1` — an infinite timeline breaks seeking). Avoid
|
|
203
|
+
`Math.random()` per frame unless keyed off seek time — the same `t` must always draw the same
|
|
204
|
+
frame (renders can revisit frames out of order).
|
|
205
|
+
|
|
206
|
+
### Security constraints
|
|
207
|
+
|
|
208
|
+
- Cross-origin sandboxed: author JS cannot reach the parent page, other surfaces, or the canvas.
|
|
209
|
+
- Strict CSP: `connect-src 'none'` — no `fetch`/`XHR`/`WebSocket` at runtime. Pass data via
|
|
210
|
+
`__BLOCK` params. Images from `data:`/`https:`. External `<script src>` blocked except the
|
|
211
|
+
allowlist above (inline other libraries). DRACO-compressed glTF unsupported (decoder fetch blocked).
|
|
212
|
+
- `mode: "inline"` is not supported (cannot be sandboxed) — it is a compile error. Blend/backdrop
|
|
213
|
+
overlays stay catalog-only.
|
|
214
|
+
- Max HTML size 512 KB.
|
|
215
|
+
|
|
216
|
+
## Usage
|
|
217
|
+
|
|
218
|
+
```vidscript
|
|
219
|
+
import animations from "@scenerok/animations"
|
|
220
|
+
|
|
221
|
+
[0s .. 6s] = animations.code_typing("const x = 1;")
|
|
222
|
+
[0s .. 5s] = animations.text_word_cascade("Make videos from plain text", accent: "#60a5fa")
|
|
223
|
+
[5s .. 9s] = animations.text_counter_stat("12500", "Downloads", suffix: "+")
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
See `animations-picker.md` for intent-based selection. Preview samples: https://scenerok.com/catalog#animations
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Animation Block Picker
|
|
2
|
+
|
|
3
|
+
`import animations from "@scenerok/animations"` surfaces the vendored HyperFrames block catalog as positionable, time-windowed VidScript surfaces. Each `animations.<fn>(...)` call resolves to a `hyperframes` IR surface; no LLM runs at render time.
|
|
4
|
+
|
|
5
|
+
**Reuse-first:** prefer `animations.<fn>(...)` over hand-authoring composition HTML. Full per-fn param shapes: `animations-catalog.md`.
|
|
6
|
+
|
|
7
|
+
## Intent → `animations.<fn>(...)`
|
|
8
|
+
|
|
9
|
+
| Intent | Family | `animations.<fn>(…)` | Positional args (in order) |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| typing / live code walk | code-anim | `code_typing` | `code`, `lang`, `theme`, `filename` |
|
|
12
|
+
| scroll through a file | code-anim | `code_scroll` | `code`, `lang`, `theme` |
|
|
13
|
+
| spotlight a line | code-anim | `code_highlight` | `code`, `lang`, `theme` |
|
|
14
|
+
| 3D extrude / shader dissolve / particle title | code-anim | `code_3d_extrude` · `code_shader_dissolve` · `code_particle_assemble` | `code`, `theme` |
|
|
15
|
+
| assemble snippets in flight | code-anim | `code_snippet_flight` | `code`, `theme` |
|
|
16
|
+
| before/after code change | code-anim | `code_morph` · `code_diff` | `from`, `to`, `lang`, `theme` |
|
|
17
|
+
| themed VS Code window | code-snippet | 24 `code_snippet_*` themes | `code`, `filename` |
|
|
18
|
+
| Apple Terminal command + output | code-snippet | 12 `code_snippet_apple_terminal_*` | `command`, `output`, `prompt`, `title` |
|
|
19
|
+
| broadcast name / title bar | lower-third | `lt_clean_bar` · `lt_accent_underline` · `lt_kicker_name` · `lt_mask_reveal` · `lt_stack_bars` | `title`, `subtitle`, `accent?` |
|
|
20
|
+
| lower-third with kicker | lower-third | `lt_kicker_name` · `lt_side_rule` | `kicker`, `title`, `accent?` |
|
|
21
|
+
| YouTube channel card | lower-third | `yt_lower_third` | `channel`, `subscribers`, `avatarUrl?` |
|
|
22
|
+
| Bild-style brand accent | lower-third | `lower_third_bild` | `title`, `subtitle`, `accent?` |
|
|
23
|
+
| inline text over footage | text-overlay | `lower_third` · `blend_caption` | inline `{{title}}` / `{{subtitle}}` tokens |
|
|
24
|
+
| X / Twitter post | social-card | `x_post` | `displayName`, `handle`, `body?`, `hashtag?`, `timestamp?` |
|
|
25
|
+
| Reddit thread | social-card | `reddit_post` | `subreddit`, `title`, `body?`, `author?`, `votes?` |
|
|
26
|
+
| TikTok / Instagram follow | social-card | `tiktok_follow` · `instagram_follow` | `displayName`, `handle`, `avatarUrl?`, `url?` |
|
|
27
|
+
| Spotify now-playing | social-card | `spotify_card` | `track`, `artist` |
|
|
28
|
+
| macOS notification | social-card | `macos_notification` | `appName`, `title`, `body?`, `timeLabel?` |
|
|
29
|
+
| news ticker / headline crawl | social-card | `news_ticker` | `headline`, `headlineAccent?`, `ticker?`, `desk?`, `time?` |
|
|
30
|
+
| logo outro / brand sting | brand | `logo_outro` | `tagline`, `url?`, `brand?` (`"scenerok"` preset) or `logoUrl?`, `accent?` |
|
|
31
|
+
| staggered word-reveal headline | text-anim | `text_word_cascade` | `text`, `color?`, `accent?` (accent tints last word) |
|
|
32
|
+
| matrix-style decode / decrypt title | text-anim | `text_scramble_decode` | `text`, `color?`, `accent?` |
|
|
33
|
+
| word-per-beat kinetic typography | text-anim | `text_kinetic_words` | `text` (space-separated words), `color?`, `accent?` |
|
|
34
|
+
| animated gradient headline | text-anim | `text_gradient_sweep` | `text`, `from?`, `to?` (gradient colors) |
|
|
35
|
+
| typed quote with attribution | text-anim | `text_typewriter_quote` | `text`, `author`, `color?`, `accent?` |
|
|
36
|
+
| 2–3 line masked title stack | text-anim | `text_line_stack` | `line1`, `line2`, `line3?`, `accent?` |
|
|
37
|
+
| count-up stat / metric | text-anim | `text_counter_stat` | `value`, `label`, `prefix?`, `suffix?`, `accent?` |
|
|
38
|
+
| RGB-split glitch title | text-anim | `text_glitch_title` | `text`, `color?` |
|
|
39
|
+
| neon sign flicker-on | text-anim | `text_neon_flicker` | `text`, `color?` (glow color) |
|
|
40
|
+
| punchy kinetic title (no block) | kinetic-type | (use `text` + `motion.*` — see `text-styles.md`) | — |
|
|
41
|
+
| no catalog block fits / author your own animation (HTML+CSS with GSAP, Three.js, or any seekable JS lib) | custom | `custom_html` | `src` or `html` — author contract, allowlisted libraries, and a minimal GSAP template in `animations-catalog.md` → "Custom HTML" |
|
|
42
|
+
|
|
43
|
+
Param resolution: **named > positional > default**.
|
|
44
|
+
|
|
45
|
+
## Gotchas
|
|
46
|
+
|
|
47
|
+
| Block / family | Issue | Fix |
|
|
48
|
+
| --- | --- | --- |
|
|
49
|
+
| `code_diff` | Line indices may be 0-based in adapter | Match sample in `animations-catalog.md` |
|
|
50
|
+
| Unverified blocks | `scenerok validate` warns `verified:false` | Accept demo render or switch to verified family |
|
|
51
|
+
| Maps / liquid-glass / app-showcase | Ignore user params | Use for demo aesthetic only, or hand-author |
|
|
52
|
+
| Adapter blocks | No inline audio/text siblings | Put `audio`, `text`, `filter` on separate time blocks |
|
|
53
|
+
| `logo_outro` | Renders upstream demo's Figma-style mark when no logo param given | Pass `brand: "scenerok"` or `logoUrl: "<image url>"` |
|
|
54
|
+
|
|
55
|
+
## Two-phase compose recipe
|
|
56
|
+
|
|
57
|
+
**Part 1 — classify (before probing assets):**
|
|
58
|
+
|
|
59
|
+
1. Decide intent family from the table above.
|
|
60
|
+
2. Pick `animations.<fn>` (or `text` + `motion.*` for kinetic-type).
|
|
61
|
+
3. Note param values from the user request.
|
|
62
|
+
4. Draft time blocks: `[<start>s .. <end>s] = animations.<fn>(...)`.
|
|
63
|
+
|
|
64
|
+
**Part 2 — compose (after probing assets):**
|
|
65
|
+
|
|
66
|
+
1. Probe assets (logo, avatar, code) — never guess dimensions.
|
|
67
|
+
2. Resolve params: named override positional; defaults fill the rest.
|
|
68
|
+
3. Emit VidScript call.
|
|
69
|
+
4. Adjacent `audio`, `text`, `filter` on **separate** time blocks.
|
|
70
|
+
5. Run `scenerok validate script.vid`.
|
|
71
|
+
|
|
72
|
+
## Demo script
|
|
73
|
+
|
|
74
|
+
```vidscript
|
|
75
|
+
import animations from "@scenerok/animations"
|
|
76
|
+
import tr from "@scenerok/transitions"
|
|
77
|
+
output to "demo.mp4", resolution: "1920x1080", fps: 30
|
|
78
|
+
|
|
79
|
+
[0s .. 6s] = animations.code_typing("let abc = 23; abc += 10; console.log(abc);")
|
|
80
|
+
[6s .. 6.6s] = tr.dissolve()
|
|
81
|
+
[6.6s .. 13s] = animations.code_morph("const a = 1", "const a = 2")
|
|
82
|
+
[13s .. 19s] = animations.code_typing(code: "const z = 5;", duration: 6, filename: "app.ts", theme: "monokai")
|
|
83
|
+
[19s .. 24s] = animations.lt_clean_bar("Ada Lovelace", "Engineer", accent: "#00ff00")
|
|
84
|
+
[24s .. 29s] = animations.x_post("SceneRok", "@scenerok", body: "Shipped adapters.", hashtag: "#v1")
|
|
85
|
+
[29s .. 34s] = animations.news_ticker("Tech Desk", time: "15:30 UTC",
|
|
86
|
+
headline: "SceneRok ships", headlineAccent: "53 verified blocks",
|
|
87
|
+
ticker: "Verified count: 53/78\nBeta opens July")
|
|
88
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Brand Setup for Agents
|
|
2
|
+
|
|
3
|
+
Collect brand context **only when it improves the video** and **only when your runtime allows asking the user or discovering assets**. Never block composition on a long questionnaire.
|
|
4
|
+
|
|
5
|
+
## When to ask (vs infer)
|
|
6
|
+
|
|
7
|
+
| Situation | Action |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| User gave product/company URL + you can browse | Extract colors, logo, hero imagery from the site first |
|
|
10
|
+
| User mentioned a brand by name with no assets | Ask for logo URL and primary color (one message, ≤3 fields) |
|
|
11
|
+
| Template has `color` placeholders | Use template defaults; offer to customize |
|
|
12
|
+
| Motion graphic / code demo with no brand | Skip brand questions |
|
|
13
|
+
| User already specified hex colors / logo | Use as-is; do not re-ask |
|
|
14
|
+
|
|
15
|
+
**Ask at most one short brand message** with combined fields, not a multi-step wizard.
|
|
16
|
+
|
|
17
|
+
## What to collect (priority order)
|
|
18
|
+
|
|
19
|
+
1. **Primary brand color** — hex, e.g. `#6366F1` (for text `color:`, lower-third `accent:`, animation `accentColor:`)
|
|
20
|
+
2. **Logo** — HTTPS URL or uploaded asset (editor library / ChatGPT import / local path on CLI)
|
|
21
|
+
3. **Secondary / text color** — default white `#FFFFFF` on dark or dark `#0F172A` on light
|
|
22
|
+
4. **Font preference** — only if user cares; default `Inter` / system stacks in examples
|
|
23
|
+
5. **Tagline or CTA** — for promos and `logo_outro`
|
|
24
|
+
|
|
25
|
+
## Where brand lands in VidScript
|
|
26
|
+
|
|
27
|
+
```vidscript
|
|
28
|
+
import motion from "@scenerok/basic-animations"
|
|
29
|
+
import animations from "@scenerok/animations"
|
|
30
|
+
|
|
31
|
+
input logo = "https://cdn.example.com/brand-logo.png"
|
|
32
|
+
|
|
33
|
+
let brandColor = "#6366F1"
|
|
34
|
+
|
|
35
|
+
[0s .. 3s] = text "Launch Week", color: brandColor, style: title, animate: motion.popIn(0.6s)
|
|
36
|
+
[3s .. 8s] = animations.lt_clean_bar("Product Name", "Tagline here", accent: brandColor)
|
|
37
|
+
[8s .. 14s] = animations.logo_outro("Thanks for watching", url: "scenerok.com", logoUrl: logo)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Use `accent`, `accentColor`, and `color` params consistently across text and animation blocks.
|
|
41
|
+
|
|
42
|
+
**`logo_outro` branding:** without `logoUrl` or `brand`, the outro renders the upstream demo's colorful Figma-style mark — never ship that on a branded video. Pass `logoUrl:` (user's logo image) or `brand: "scenerok"` (built-in SceneRok preset, also tints the glow), plus `accent:` to override the glow color.
|
|
43
|
+
|
|
44
|
+
## Per-environment collection
|
|
45
|
+
|
|
46
|
+
| Environment | How to get brand assets |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| **Web editor** | Ask in chat; user can upload to asset library and paste URLs into script |
|
|
49
|
+
| **CLI / desktop agent** | Ask in terminal; accept local paths; user may run `scenerok auth login` for cloud assets |
|
|
50
|
+
| **ChatGPT** | Ask in conversation; user uploads logo/screenshot → `importOpenAIConversationFiles` → use returned `asset.url` |
|
|
51
|
+
| **URL-only (no uploads)** | Screenshot logo from site; probe dimensions before placement |
|
|
52
|
+
|
|
53
|
+
## Website-derived brand (preferred when URL given)
|
|
54
|
+
|
|
55
|
+
1. Visit the URL (browser tool or user-provided screenshots).
|
|
56
|
+
2. Note dominant accent from buttons, links, or hero — sample one hex.
|
|
57
|
+
3. Save logo and product stills; **probe width/height** before composing.
|
|
58
|
+
4. Do not invent claims, pricing, or testimonials — extract or ask.
|
|
59
|
+
|
|
60
|
+
See `workflow.md` for the full URL asset pipeline.
|
|
61
|
+
|
|
62
|
+
## Defaults when user declines
|
|
63
|
+
|
|
64
|
+
- Accent: `#6366F1` (SceneRok indigo) or high-contrast pair white on `#0B1020`
|
|
65
|
+
- No logo: kinetic `text` + `motion.popIn` instead of `logo_outro`
|
|
66
|
+
- Music: neutral instrumental bed from `music.md`
|
|
67
|
+
|
|
68
|
+
## Privacy
|
|
69
|
+
|
|
70
|
+
- Do not paste API tokens or OAuth secrets into VidScript or chat logs.
|
|
71
|
+
- Use only assets the user provided or that are public on their stated URL.
|