greenlight-motion 0.2.0 → 0.2.2

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.
@@ -37,6 +37,7 @@
37
37
  "frontend/src/motionEngine/sceneScriptBundle.js",
38
38
  "frontend/src/motionEngine/sceneScriptGuide.js",
39
39
  "frontend/src/motionEngine/template.js",
40
+ "frontend/src/render-shims/googleFontCatalog.js",
40
41
  "frontend/src/utils/cssGradient.js",
41
42
  "skills/greenlight-dash/references/video-design.md"
42
43
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greenlight-motion",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "GreenLight Motion Engine: AI agents make motion-design videos (3D, camera, effects, transitions, text animation, particles, motion blur) with the GreenLight Dash Video Editor's own engine, in the user's browser.",
5
5
  "keywords": [
6
6
  "video",
package/skill/SKILL.md CHANGED
@@ -18,12 +18,19 @@ You never write UI or animation code. If something is not in the format, it is n
18
18
  ## Setup (once per machine)
19
19
 
20
20
  ```
21
- npx greenlight-motion@0.2.0 doctor
21
+ npx greenlight-motion@0.2.2 doctor
22
22
  ```
23
23
 
24
24
  It checks Node 18+, Chrome or Edge, WebGPU and H.264 encoding, and prints a fix for anything missing. Do not install
25
25
  anything globally without asking the user. Always pin the version in every command you run.
26
26
 
27
+ ## First, a direction
28
+
29
+ Before any JSON, decide in a few lines what the video LOOKS like: one visual idea from the subject's own world carried
30
+ through every scene, the palette, the type, and what each scene shows besides its words. Presets make a video move;
31
+ the direction makes it look designed. `skill/references/scene-script.md` opens with how. Then build to it, and judge
32
+ every contact sheet against it.
33
+
27
34
  ## The fast way: a scene script
28
35
 
29
36
  For a new video, start with a **scene script** instead of a whole project: a short JSON file — scenes, their texts and
@@ -32,7 +39,7 @@ animation presets (the same converter the GreenLight Motion connector uses in Cl
32
39
  keyframes rarely look as good. The format, the design rules and the catalogues: `skill/references/scene-script.md`.
33
40
 
34
41
  ```
35
- npx greenlight-motion@0.2.0 script <folder> --from scenes.json # or write <folder>/script.json, then: script <folder>
42
+ npx greenlight-motion@0.2.2 script <folder> --from scenes.json # or write <folder>/script.json, then: script <folder>
36
43
  ```
37
44
 
38
45
  Then `check` and `stills` (below), fix the SCRIPT and run `script` again — it rewrites `project.json`. A scene's
@@ -40,16 +47,49 @@ Then `check` and `stills` (below), fix the SCRIPT and run `script` again — it
40
47
  `z`). For what a script can't say (3D models, particles, motion paths, masks, text animators by hand), go on from `project.json` with the
41
48
  workflow below and stop running `script` (it refuses to overwrite a project edited since, unless `--force`).
42
49
 
50
+ ## Beyond the script: the signature visual
51
+
52
+ The script gives structure; the picture that makes the video THIS product's usually needs the engine's full format.
53
+ Build it with `apply` on the project `script` wrote (the item ids are the script's element ids):
54
+
55
+ - **A material of its own**: a custom GLSL shader on a shape or the whole background (water, light through glass,
56
+ paper, heat): `shapeBackground` / `background` `{ "type": "shader", "shaderId": "custom", "shaderCode": "void
57
+ mainImage(out vec4 o, in vec2 fc) { … }" }`, Shadertoy-style, `iTime` from the timeline
58
+ (`references/video-backgrounds.md`, Custom GLSL shaders).
59
+ - **Layers that interact**: a track matte, so words dip under a surface or show only through a shape
60
+ (`"trackMatte": { "sourceId": "<item>", "mode": "alpha" | "alphaInverted" | "luma" | "lumaInverted" }` on the layer
61
+ that is cut; the source is hidden from the output; `references/video-shapes.md`). Clipping masks and Layer Mask
62
+ (`references/video-effects.md`) for reveals.
63
+ - **Your own drawing and motion**: SVG you write (`{ "type": "image", "svg": "…" }` in the script), shapes with
64
+ keyframes, motion paths (`references/video-paths.md`), particles (`references/video-particles.md`), 3D
65
+ (`references/video-3d.md`), Text Animators by hand (`references/video-text.md`).
66
+ - **Sound when nothing may be downloaded**: write it in code. A short Node script can write a 48 kHz WAV (a soft bed, a
67
+ click, a noise whoosh) into `assets/`, then use it as the script's `music` or as an audio clip. Keep the bed quiet
68
+ under the hits.
69
+
70
+ Keep the build repeatable: put your edits in a file you `apply` again after each `script` run (`script --force`, then
71
+ `apply`), so the script and the hand-made layers never drift apart.
72
+
73
+ What the engine does there, so you don't learn it from a broken frame:
74
+ - **A shader on a shape** draws in that shape's own buffer: `iResolution` is the shape's size (times `shaderScale`), not
75
+ the frame's, and `iTime` counts from the layer's own start, so layers whose shaders must stay in step need the same
76
+ start. Its settings are not keyframe tracks: change it over time inside the code, from `iTime`.
77
+ - **A track matte's source** is hidden only while a layer that uses it is on screen; outside that time it draws as an
78
+ ordinary layer. Give it the same start and end as the layer it cuts (`check` reports one that shows).
79
+ - **Fonts**: a text layer's family loads from Google Fonts while the page is online, unless a font file in `assets/`
80
+ carries that name (`assets/Manrope.ttf` is the family "Manrope"; .ttf, .otf, .woff, .woff2): that file is used,
81
+ offline. `trace` reads layers inside a script's scenes too (`--items` takes their ids).
82
+
43
83
  ## Workflow
44
84
 
45
- 1. `npx greenlight-motion@0.2.0 init <folder>` — starts from a working example (title, subtitle, accent line, four
85
+ 1. `npx greenlight-motion@0.2.2 init <folder>` — starts from a working example (title, subtitle, accent line, four
46
86
  options). `--from file.json` starts from a project you have (for example one exported from GreenLight Dash).
47
87
  2. Edit `<folder>/project.json` — for changes to an EXISTING project prefer `apply` (below): it checks every edit and
48
88
  applies all or nothing. Put pictures, video, sound and fonts in `<folder>/assets/` and refer to them as
49
89
  `"asset:<file>"` (e.g. `"url": "asset:product.png"`).
50
- 3. `npx greenlight-motion@0.2.0 check <folder>` — fix everything it lists (missing files, template mistakes, blank
90
+ 3. `npx greenlight-motion@0.2.2 check <folder>` — fix everything it lists (missing files, template mistakes, blank
51
91
  frames, page errors). `--json` for machine output.
52
- 4. `npx greenlight-motion@0.2.0 stills <folder>` — renders frames and **a labelled contact sheet**. Open and look at
92
+ 4. `npx greenlight-motion@0.2.2 stills <folder>` — renders frames and **a labelled contact sheet**. Open and look at
53
93
  it before you go on: layout, readability, timing. Fix and repeat. `--at 0.5,1.2,3` for exact times.
54
94
  5. Hand it over: tell the user to open `<folder>/index.html` (Chrome or Edge), or `pack` it into one file, or
55
95
  `render` the MP4 yourself (`--fps 60 --motion-blur` for fast motion).
@@ -114,7 +154,7 @@ editor's own normalizer), so write only what you mean.
114
154
  Full references (generated from the editor's own docs; ignore the `/api/` routes they mention):
115
155
  `skill/references/` — video-design, scene-script, video-projects, video-text, video-text-kinetic, video-text-presets, video-shapes, video-keyframes,
116
156
  video-camera, video-3d, video-effects, video-transitions, video-particles, video-paths, video-backgrounds, video-grid.
117
- Machine-readable lists: `npx greenlight-motion@0.2.0 schema effects | transitions | easings | paths | expressions`.
157
+ Machine-readable lists: `npx greenlight-motion@0.2.2 schema effects | transitions | easings | paths | expressions`.
118
158
 
119
159
  ## Template
120
160
 
@@ -161,7 +201,7 @@ an absolute moment; `align` `sync` (default) / `start` / `end`; `offset` seconds
161
201
 
162
202
  The library is 77 hand-picked sounds in categories (whooshes and swooshes, transitions, clicks, pop-ups and
163
203
  notifications, data blips, typing and writing, foley, bubbles, impacts and bass drops, camera, gears, voice clips).
164
- `npx greenlight-motion@0.2.0 schema sounds` lists every one with its `category`, `use` (what it is for), `duration`
204
+ `npx greenlight-motion@0.2.2 schema sounds` lists every one with its `category`, `use` (what it is for), `duration`
165
205
  and `sync`. Pick by `category` and `use`, then by name.
166
206
 
167
207
  - **Where the files come from:** the GreenLight sound CDN. `build` downloads each sound a cue uses into
@@ -177,7 +217,7 @@ The page has **Notes**: the user marks what should change right on the frame (a
177
217
  and writes a note for each mark. Every note carries the moment (seconds and frame), the mark in composition pixels
178
218
  and the layers under it (item ids in project.json), so you change exactly that and nothing else.
179
219
 
180
- - **They review on this computer:** run `npx greenlight-motion@0.2.0 review <folder>` and give them the URL it prints
220
+ - **They review on this computer:** run `npx greenlight-motion@0.2.2 review <folder>` and give them the URL it prints
181
221
  (it keeps running; `--open` opens their browser, only when they ask). Their notes land in `<folder>/review/`: read
182
222
  `review/NOTES.md`, look at the `at-<t>s.png` pictures (the marks are numbered), make the changes (`apply`), `build`
183
223
  again and tell them to reload the page.
@@ -206,11 +246,11 @@ that fails (`plugin`); look at `stills` for the look. A package that carries its
206
246
 
207
247
  The same project opens in GreenLight Dash (the desktop editor this engine comes from) for full editing: the page's
208
248
  edit note offers **Open in GreenLight Dash** (it imports the folder as a new project on the open board; a page with
209
- changes saves a `.glvideo`). `npx greenlight-motion@0.2.0 pack <folder> --glvideo` writes that file yourself: ONE
249
+ changes saves a `.glvideo`). `npx greenlight-motion@0.2.2 pack <folder> --glvideo` writes that file yourself: ONE
210
250
  `.glvideo` (the project + its files) that opens in GreenLight Dash on a double-click, or dropped on its board. Hand it
211
251
  over when the user wants to keep editing in the app. A
212
252
  GreenLight Dash project comes the other way through the app's **Export for agents** — a ready folder like the one
213
- `init` makes, with the options the author ticked. `npx greenlight-motion@0.2.0 init <folder> --from <its project.json>`
253
+ `init` makes, with the options the author ticked. `npx greenlight-motion@0.2.2 init <folder> --from <its project.json>`
214
254
  starts from one too. Never tell the user they must install it: the page plays, changes options and renders on its own.
215
255
 
216
256
  ## Files
@@ -13,6 +13,19 @@ works too (it has to stay reachable). SVG you write: `{ "type": "image", "svg":
13
13
 
14
14
  ## The scene script
15
15
 
16
+ **Before the script, a direction.** Presets make a video move; they don't give it an idea. Decide in a few lines first,
17
+ and keep them next to the script:
18
+ - **The idea**: ONE picture from the subject's own world (its object, place or action: a coffee shop's steam and cup rim,
19
+ a budgeting app's receipt printing line by line, a running app's track the scenes run along), carried through every scene.
20
+ - **The palette**: background, text, one accent, plus only the colours that carry meaning (good / bad, before / after).
21
+ Light or dark on purpose.
22
+ - **The type**: a big headline against a small support line; aligned left or centred on purpose, not by default.
23
+ - **Each scene**: what it SHOWS besides its words, built from shapes, lines, `svg` you write, keyframes and the camera.
24
+ The same line centred on a gradient in every scene reads as a template. Judge the stills against the direction, not
25
+ only for mistakes.
26
+ What a script can't say (a custom GLSL shader on a shape or the background, words dipping under a surface with a track
27
+ matte, masks, particles, 3D) goes on from `project.json`: SKILL.md, "Beyond the script".
28
+
16
29
  ```json
17
30
  {
18
31
  "title": "Bean There — opening day",
@@ -39,11 +52,17 @@ works too (it has to stay reachable). SVG you write: `{ "type": "image", "svg":
39
52
  ```
40
53
 
41
54
  - **format** 16:9 · 9:16 · 1:1 · 4:5 (16:9 = 1920×1080, 9:16 = 1080×1920, 1:1 = 1080×1080, 4:5 = 1080×1350). Sizes and positions are in those pixels.
55
+ - **style**: `background`, `colors` { text, accent, muted }, `font`: a Google Fonts family (the page loads it from Google Fonts while online) or any font whose file you put in assets/ named after it (`Manrope.ttf`, .otf, .woff, .woff2: used offline).
42
56
  - **at**: `center` `top` `bottom` `left` `right` `top-left` … or `[x, y]` px from the centre (+y is down). Keep text inside the middle 80 %.
43
57
  - **text**: `role` headline | subhead | body | label sets size and weight (override with `size`, `weight`); `color` text | accent | muted | #hex |
44
58
  a CSS gradient; `width` (px, wraps), `align`, `uppercase`, `letterSpacing`, `lineHeight`. A headline gets `glide-text` unless you set `textAnimation`.
59
+ The text box is CENTRED on `at`: without `width` it is as wide as its words but stays inside the frame (off-centre text wraps
60
+ sooner); for a left-aligned column give `width` and `"align": "left"` and put `at` at the column's centre.
45
61
  - **rect · pill · circle**: `w`, `h`, `color` (or a CSS gradient), `radius`, `border` {width, color}, `shadow`: true. They enter with `pop-overshoot` unless you set `enter`.
46
62
  - **line**: from `at` to `to`, `width`, drawn on (`draw`: false to skip).
63
+ - **ring**: a circle drawn as a stroke from the top, clockwise (a timer, a status or focus ring): `w` (diameter), `width` (stroke),
64
+ `color`, `sweep` (degrees, 360 = full), drawn on (`draw`: false to skip), `drain`: true empties it again by the element's
65
+ end (a countdown), `ghost` (0–100: a faint full track under it).
47
66
  - **image · video**: `src` (a file in the folder's assets/ as `asset:<name>`, or an https link) or, for an image, `svg` (SVG markup you write); `w` or `h`
48
67
  (px; the other follows the file's shape) or `fit` cover | contain
49
68
  (default: a video covers the frame, a picture sits at 70 % of contain), `rotate` (deg). A video also takes
@@ -55,8 +74,15 @@ works too (it has to stay reachable). SVG you write: `{ "type": "image", "svg":
55
74
  for directional ones), `effects`: [{ "id", "params"? }], `sound` (played at its start), `id`, `label` (its name in the page's options), `opacity` (0–1),
56
75
  `z` (px of depth, + toward the viewer, default 0: a real camera's dolly, orbit and depth of field separate layers by it), `locked`: true
57
76
  (the scene's camera doesn't move it: a logo, a caption). Keyframes also take a `z` track.
58
- - **Scene**: `duration` (s), `transition` into it (default Cross Fade, 0.6 s; `transitionDuration`), `camera` (below; default push-in),
59
- `background` (overrides style), `sounds`: [{ "sfx", "at" }]. Script-level `sound`: auto (default: a whoosh on each transition and on the first headline) | none.
77
+ - **Scene**: `duration` (s), `transition` into it (default Cross Fade, 0.6 s; `transitionDuration`), `transitionOptions` (the
78
+ transition's own settings, e.g. Circular Wipe's `point` { x, y } (% of the frame from its top-left: 50, 50 is the centre) and `feather`; every option: `npx greenlight-motion schema transitions`.
79
+ A transition's vivid colours, such as Circular Wipe's beam, take the accent unless you set them), `camera` (below; default push-in),
80
+ `background` (overrides style), `sounds`: [{ "sfx", "at" }]. Script-level `sound`: auto (default: a whoosh on each transition and
81
+ on the first headline, from the GreenLight sound library, which the CLI downloads into assets/sounds/ when it builds) | none (nothing from the library: when
82
+ nothing may be downloaded, use `music` with a file you made).
83
+ **A transition overlaps the scenes on both sides**, so the video lasts the scenes' durations added up MINUS every
84
+ transition: five 3 s scenes with the default 0.6 s transitions run 15 − 4 × 0.6 = 12.6 s. To hit a length, add the
85
+ transitions back to the scenes (`script` prints the total).
60
86
  - **camera** — a quick move of the whole scene: none | push-in | pull-out | drift-left | drift-right | drift-up. Or a REAL camera that films the scene's elements in 3D (the
61
87
  Video Editor's own camera layer; the scene's backdrop stays put, so its edge never shows). One of:
62
88
  - `{ "move": id }` — a camera move from the catalogue (or just `"camera": "cm-quiet-push"`), spread over the scene;
@@ -75,6 +101,7 @@ works too (it has to stay reachable). SVG you write: `{ "type": "image", "svg":
75
101
  - `start` / `end` (s in the scene; default the whole scene; outside them the camera rests). Keys and zooms count seconds into the camera.
76
102
  - **background**: a colour, a CSS gradient, { "shader": id, "look"? } — shaders: silk, glowblobs, waves, plasma, mesh, fire, spacetravel, glitters, blueplanet, auroraridge, emberpool, neonvignette, electricvignette, spectrumdrift, emberfacet, silkdrift, eclipseprism, glassreeds, staticfringe, ripplefold, nightaurora, pixelbeams, petalgrid, amberblinds, icehalo, windowhaze (looks: references/video-backgrounds.md) — or { "image": src } / { "video": src } (covers the frame; b-roll behind the scene).
77
103
  - **music** (script level): `"music": { "src": file, "volume": 80, "fadeIn": 0.3, "fadeOut": 1.2, "startAt": 0 }` — one track under the video.
104
+ The file must exist when you run `script` (it reads its length): write a sound you make in code before the first run.
78
105
 
79
106
  ## What makes it look made, not generated
80
107
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — 3D models, scene lighting and shadow plates
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Backgrounds and custom shaders
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Camera layers, paths, rigs and presets
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Video Editor Layer Effects and Overlay Effects
6
8
 
@@ -565,7 +567,7 @@ On a `model3d` item, these Overlay Effects have a REAL 3D version that renders i
565
567
 
566
568
  ### Installed effects (`local:<id>`)
567
569
 
568
- Effect packages an agent built or the user imported ([custom-effects skill](../../custom-effects/SKILL.md))
570
+ Effect packages an agent built or the user imported (custom-effects skill (GreenLight Dash only))
569
571
  apply exactly like the registry effects above, in the same `effects` list and both scopes:
570
572
 
571
573
  ```json
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Grid layers
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Keyframes, easing and expressions
6
8
 
@@ -32,7 +34,7 @@ Positions are always **0–100, percent of the clip's played duration** (not sec
32
34
  }
33
35
  ```
34
36
 
35
- Rules: no two keys of one track may share a `position`; a track with zero keys should be omitted. One track key lives outside the registry below and is documented with the curve it replaces: **`speed`** — the clip's playback rate, which retimes the clip rather than restyling it (see [Speed curves](video-analysis.md#speed-curves-itemspeedpoints--anchors-and-tangents)). Animatable property names (the editor's `KF_PROPS` registry in `frontend/src/components/videoEditor/keyframeProps.js`): `opacity`, `scale`, `scaleX`, `scaleY`, `rotate`, `rotateX`, `rotateY`, `translateX`, `translateY`, `xPercent`, `yPercent`, `translateZ`, `motionPathT`, `motionPathOffsetX`, `motionPathOffsetY`, `motionPathOffsetZ` (px displacement from a live motion path — see [Object Motion Paths](video-paths.md#object-motion-paths-motionpath--motionpatht)), `letterSpacing`, `clipPath`, `textPathSpread`, `textPathSpacing`, `textPathTrimStart`, `textPathTrimEnd`, `textPathOffsetY` (Transform — the `textPath*` tracks animate the [Text on Path](video-paths.md#text-on-path-textpathenabled) distribution and no-op elsewhere), `borderWidth` (Transform — the card-framing border in px, the outline on shape layers); `color`, `backgroundColor` (Color — hex or rgba strings), `textColor` (text layer's fill), `textBgColor` (text layer's caption-bar colour), `textOutlineColor` (outline/stroke colour; unset falls back to the text colour), `shapeFill` (shape layer's background paint, applied while the background type is solid or gradient), `borderColor` (the border's colour) — `textColor` and `shapeFill` keys may also hold a full CSS gradient string (`linear-gradient(90deg, #fff 0%, #8b5cf6 100%)`), and the interpolator blends gradients stop-by-stop, including solid↔gradient; `blur`, `brightness`, `contrast`, `hue-rotate`, `saturate`, `grayscale`, `sepia`, `invert` (Filters — each overrides the item's static `filter*` field while its track exists); `effectAmount`; `lutAmount`; `glowAmount`, `glowEdgeLevel`, `glowLevel`, `glowRadius`, `glowAngle`, `glowEdgeWidth`, `glowOffset`, `glowStaticRim`, `glowSoftness`, `glowSpread`, `glowHeadGlint`, `glowCenterX`, `glowCenterY`, `glowTrail`, `glowFlicker`, `glowMaskThreshold`, `glowSourceLevel`, `depthStrength`, `depthFocus`, `mskAmount` (Effects — the other Layer Effects' tracks such as `mblur*`, `trail*`, `af*`, `rep*`, `ds*`, `bn*`, `cp*`, `mf*`, `bw*`, `mw*`, `dro*`, `ck*` are listed per effect in `video-effects.md`). **Camera clips keyframe a different registry** — `camZoom`, `camX`, `camY`, `camRoll`, `camDolly`, `camTiltX`, `camTiltY`, `camPathT`, `camPathOffsetX/Y/Z`, `camFollowTarget`, plus the depth-of-field fields; see the Camera layers section. `xPercent`/`yPercent` are % of canvas size, `translateX/Y/Z` are px, `scale`/`scaleX`/`scaleY` are plain multipliers (1 = unchanged) that MULTIPLY the item's base `zoom`/`scaleX`/`scaleY` — `scale` is uniform and the other two stretch one axis on top of it, so a squash-and-stretch is `scaleX` up while `scaleY` goes down, `motionPathT`/`camPathT` are 0–100 % path progress, `brightness`/`contrast`/`saturate`/`grayscale`/`sepia`/`invert` are % (100 = neutral for the first three, 0 for the rest), `blur` is px, `opacity` 0–1. A track on an item without the matching feature is a harmless no-op. `propertyKeyframes` is baked by **`/render-onserver`** (and the desktop render); the fast `/render` ignores keyframes entirely.
37
+ Rules: no two keys of one track may share a `position`; a track with zero keys should be omitted. One track key lives outside the registry below and is documented with the curve it replaces: **`speed`** — the clip's playback rate, which retimes the clip rather than restyling it (see Speed curves (GreenLight Dash only)). Animatable property names (the editor's `KF_PROPS` registry in `frontend/src/components/videoEditor/keyframeProps.js`): `opacity`, `scale`, `scaleX`, `scaleY`, `rotate`, `rotateX`, `rotateY`, `translateX`, `translateY`, `xPercent`, `yPercent`, `translateZ`, `motionPathT`, `motionPathOffsetX`, `motionPathOffsetY`, `motionPathOffsetZ` (px displacement from a live motion path — see [Object Motion Paths](video-paths.md#object-motion-paths-motionpath--motionpatht)), `letterSpacing`, `clipPath`, `textPathSpread`, `textPathSpacing`, `textPathTrimStart`, `textPathTrimEnd`, `textPathOffsetY` (Transform — the `textPath*` tracks animate the [Text on Path](video-paths.md#text-on-path-textpathenabled) distribution and no-op elsewhere), `borderWidth` (Transform — the card-framing border in px, the outline on shape layers); `color`, `backgroundColor` (Color — hex or rgba strings), `textColor` (text layer's fill), `textBgColor` (text layer's caption-bar colour), `textOutlineColor` (outline/stroke colour; unset falls back to the text colour), `shapeFill` (shape layer's background paint, applied while the background type is solid or gradient), `borderColor` (the border's colour) — `textColor` and `shapeFill` keys may also hold a full CSS gradient string (`linear-gradient(90deg, #fff 0%, #8b5cf6 100%)`), and the interpolator blends gradients stop-by-stop, including solid↔gradient; `blur`, `brightness`, `contrast`, `hue-rotate`, `saturate`, `grayscale`, `sepia`, `invert` (Filters — each overrides the item's static `filter*` field while its track exists); `effectAmount`; `lutAmount`; `glowAmount`, `glowEdgeLevel`, `glowLevel`, `glowRadius`, `glowAngle`, `glowEdgeWidth`, `glowOffset`, `glowStaticRim`, `glowSoftness`, `glowSpread`, `glowHeadGlint`, `glowCenterX`, `glowCenterY`, `glowTrail`, `glowFlicker`, `glowMaskThreshold`, `glowSourceLevel`, `depthStrength`, `depthFocus`, `mskAmount` (Effects — the other Layer Effects' tracks such as `mblur*`, `trail*`, `af*`, `rep*`, `ds*`, `bn*`, `cp*`, `mf*`, `bw*`, `mw*`, `dro*`, `ck*` are listed per effect in `video-effects.md`). **Camera clips keyframe a different registry** — `camZoom`, `camX`, `camY`, `camRoll`, `camDolly`, `camTiltX`, `camTiltY`, `camPathT`, `camPathOffsetX/Y/Z`, `camFollowTarget`, plus the depth-of-field fields; see the Camera layers section. `xPercent`/`yPercent` are % of canvas size, `translateX/Y/Z` are px, `scale`/`scaleX`/`scaleY` are plain multipliers (1 = unchanged) that MULTIPLY the item's base `zoom`/`scaleX`/`scaleY` — `scale` is uniform and the other two stretch one axis on top of it, so a squash-and-stretch is `scaleX` up while `scaleY` goes down, `motionPathT`/`camPathT` are 0–100 % path progress, `brightness`/`contrast`/`saturate`/`grayscale`/`sepia`/`invert` are % (100 = neutral for the first three, 0 for the rest), `blur` is px, `opacity` 0–1. A track on an item without the matching feature is a harmless no-op. `propertyKeyframes` is baked by **`/render-onserver`** (and the desktop render); the fast `/render` ignores keyframes entirely.
36
38
 
37
39
  **Keys cut by a split carry `easeSlice`.** Splitting an item cuts its tracks at the split point: each half keeps its own keys, both get a key there holding the value shown at that instant, and positions are re-expressed as % of each half. Part of an easing is not itself an easing, so on each side the key that starts the cut segment keeps its `easing` and gains `easeSlice: { of, from, to, bezier? }`: the segment plays only the `from`–`to` part (fractions of the original segment) of that easing, which is what lets the two halves replay the uncut animation exactly. Copy `easeSlice` unchanged when you rewrite a track, or the halves stop matching. It applies only while `of` equals the key's `easing` (and, for `Custom`, its `bezier` equals the key's), so changing the easing switches it off; delete it to give the key the whole easing again. Do not write one yourself: it only reproduces the original curve together with the exact values the split wrote on the keys either side. A split can also add keys where an easing turns back or crosses its end value (Bounce, Elastic or Back on a shape or mask path, which clamp instead of overshooting); they belong to the same animation.
38
40
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Particle layers, fluid physics and emission
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Motion paths, text on path and motion follow
6
8
 
@@ -153,7 +155,7 @@ points, and Follow Path and Text on Path both ride the snapshot at the current f
153
155
 
154
156
  ### Motion-track follow (`motionTracks` + `motionFollow`)
155
157
 
156
- A video layer the user has motion-tracked in the editor carries the result on the item as `motionTracks: []` — each track `{ id, name, mode, refTime, region, sourceFps, sourceAspect, segments, samples }`, where `samples` rows are `[tSourceSeconds, cx, cy, scale, rotDeg, confidence]` in the clip's **source** seconds, normalised to the source frame (so a track survives trims, splits and speed changes). **The editor's own analysis has no endpoint** — it runs on decoded frames inside the app. Treat a track the USER made as read-only: preserve it verbatim when copying items, and never hand-edit its samples. An agent can, however, compute tracking data itself (OpenCV in Python) and write a NEW track into the project — the sample layout, the coordinate spaces and a worked recipe are in [tracking-data.md](tracking-data.md).
158
+ A video layer the user has motion-tracked in the editor carries the result on the item as `motionTracks: []` — each track `{ id, name, mode, refTime, region, sourceFps, sourceAspect, segments, samples }`, where `samples` rows are `[tSourceSeconds, cx, cy, scale, rotDeg, confidence]` in the clip's **source** seconds, normalised to the source frame (so a track survives trims, splits and speed changes). **The editor's own analysis has no endpoint** — it runs on decoded frames inside the app. Treat a track the USER made as read-only: preserve it verbatim when copying items, and never hand-edit its samples. An agent can, however, compute tracking data itself (OpenCV in Python) and write a NEW track into the project — the sample layout, the coordinate spaces and a worked recipe are in tracking-data.md (GreenLight Dash only).
157
159
 
158
160
  Tracks arrive from either of the editor's two analyses, and both land in the same array with the same shape: **Motion Tracking** (the user drew a box around one detail) and **Camera Tracking** (the whole frame is solved, the user picks tracking points off the result, and each null they create writes one track here). A camera-tracked null is an ordinary shape layer — a 20 px `ellipse` at `opacity: 0` — whose `motionFollow` pins it to its track, so nothing about following, rendering or copying is special-cased for it. There is nothing to distinguish the two kinds after the fact, and nothing that should be.
159
161
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Video projects and timeline basics
6
8
 
@@ -10,8 +12,8 @@
10
12
 
11
13
  | Task | Reference |
12
14
  | --- | --- |
13
- | Full export, render jobs, still frames, AI Fill | [video-rendering.md](video-rendering.md) |
14
- | AI Reframe / Beats / Sound Design, saved analysis, speed curves and smoothing | [video-analysis.md](video-analysis.md) |
15
+ | Full export, render jobs, still frames, AI Fill | video-rendering.md (GreenLight Dash only) |
16
+ | AI Reframe / Beats / Sound Design, saved analysis, speed curves and smoothing | video-analysis.md (GreenLight Dash only) |
15
17
  | Keyframe tracks, easing, custom expressions | [video-keyframes.md](video-keyframes.md) |
16
18
  | Object motion paths, point reduction, text on path, motion follow | [video-paths.md](video-paths.md) |
17
19
  | Cross transitions, layer entrances/exits, Custom lanes | [video-transitions.md](video-transitions.md) |
@@ -19,27 +21,27 @@
19
21
  | Background fills and GLSL shaders | [video-backgrounds.md](video-backgrounds.md) |
20
22
  | Shape paths, strokes and vector provenance | [video-shapes.md](video-shapes.md) |
21
23
  | Grid Builder layouts | [video-grid.md](video-grid.md) |
22
- | Using MotionFast templates and device mockup clips | [video-motion.md](video-motion.md) |
23
- | HTML pages as timeline layers (html clips) and their bakes | [video-html-clips.md](video-html-clips.md) |
24
+ | Using MotionFast templates and device mockup clips | video-motion.md (GreenLight Dash only) |
25
+ | HTML pages as timeline layers (html clips) and their bakes | video-html-clips.md (GreenLight Dash only) |
24
26
  | Overlay Effects and Layer Effects, including Running Glow and Depth | [video-effects.md](video-effects.md) |
25
27
  | 3D models, Scene Rig, lighting and shadow plates | [video-3d.md](video-3d.md) |
26
28
  | Camera layer, Camera Rig, camera paths and presets | [video-camera.md](video-camera.md) |
27
29
  | Particles, packing, proximity, fluid and smoke | [video-particles.md](video-particles.md) |
28
- | Writing motion tracks, roto masks or solved cameras | [tracking-data.md](tracking-data.md) |
29
- | You are making one version of a project for Variants (your copy, the scope, `ready`) | [video-variants.md](video-variants.md) |
30
- | AI Viral Edits (kinetic words around a layer's subject) and sequences with an Essential panel (`clip.essential`) | the `viral-edits` workflow on the `greenlight` MCP server ([SKILL.md](../SKILL.md#ai-workflows-the-greenlight-mcp-server)); `essential` below |
30
+ | Writing motion tracks, roto masks or solved cameras | tracking-data.md (GreenLight Dash only) |
31
+ | You are making one version of a project for Variants (your copy, the scope, `ready`) | video-variants.md (GreenLight Dash only) |
32
+ | AI Viral Edits (kinetic words around a layer's subject) and sequences with an Essential panel (`clip.essential`) | the `viral-edits` workflow on the `greenlight` MCP server (SKILL.md (GreenLight Dash only)); `essential` below |
31
33
 
32
34
  In this file: Editing and verification · Text animation pace · Video Projects (list, get, card, create, update, collaborative boards, refresh revision, activate, delete, build from clips) · Editor `data` shape · Sequence clips · Video presets (and project export / import bundles, GreenLight Motion pages) · Interface scenes.
33
35
 
34
- Use `GET /api/video-editor/capabilities` for the installed build's effect and transition ids, fields, ranges and render support. Read the relevant subtree instead of copying a catalog into the prompt. For custom MotionFast authoring, use [the authoring skill](../../motionfast-templates/SKILL.md).
36
+ Use `GET /api/video-editor/capabilities` for the installed build's effect and transition ids, fields, ranges and render support. Read the relevant subtree instead of copying a catalog into the prompt. For custom MotionFast authoring, use the authoring skill (GreenLight Dash only).
35
37
 
36
38
  ## Editing and verification
37
39
 
38
40
  1. GET the project and retain its top-level `version` separately from `data.version` (the editor schema version).
39
41
  2. Modify only the requested fields, preserving unrelated clips, channels, items, assets and metadata. Keep every simultaneously visible layer on its own channel.
40
42
  3. PUT the full updated `data` with `expected_version` from that GET. Resolve a 409 by fetching and reapplying the intended edit; never force a stale snapshot through.
41
- 4. GET again to verify the saved structure. For visible changes, use a composited still or a short full render from [video-rendering.md](video-rendering.md) to check the result: a successful save alone does not prove an effect or track renders.
42
- 5. Keep all media used by the project, including nested sequences and effect assets, even when it has no canvas card. Follow [media cleanup](media.md#clean-up-helper--intermediate-media-do-this-at-the-end-of-a-task).
43
+ 4. GET again to verify the saved structure. For visible changes, use a composited still or a short full render from video-rendering.md (GreenLight Dash only) to check the result: a successful save alone does not prove an effect or track renders.
44
+ 5. Keep all media used by the project, including nested sequences and effect assets, even when it has no canvas card. Follow media cleanup (GreenLight Dash only).
43
45
 
44
46
  ## Text animation pace
45
47
 
@@ -83,7 +85,7 @@ GET /api/moodboards/{board_id}/video-projects/{project_id}/card
83
85
  → { "id", "board_id", "board_name", "name", "version", "updated_at", "summary", "preview" } 404 once removed
84
86
  ```
85
87
 
86
- The project without its payload, plus its board's name: what a `video-project` canvas card shows ([elements.md](elements.md#video-editor-project-cards-a-video-project-on-any-board)). Use it to check that a board/project pair exists before making a card.
88
+ The project without its payload, plus its board's name: what a `video-project` canvas card shows (elements.md (GreenLight Dash only)). Use it to check that a board/project pair exists before making a card.
87
89
 
88
90
  ### Create video project
89
91
 
@@ -205,7 +207,7 @@ Use this to assemble the workflow's per-step videos into a project in one call w
205
207
 
206
208
  ### Editor `data` shape (for `POST/PUT video-projects`)
207
209
 
208
- Video-editor `mediaType` values include `video`, `image`, `audio`, `text`, `shape`, `adjustment`, `sequence` (compound clip — see [Sequence clips](#sequence-clips-mediatype-sequence)), `grid` (Grid Builder — a container that lays its members out by a rule; see [video-grid.md](video-grid.md)), `motion` (native MotionFast animated template — see [video-motion.md](video-motion.md)), `model3d` (a live 3D model rendered in its own pass — see [video-3d.md](video-3d.md); its clip `url` must be a `model-preset:` or `model-primitive:` sentinel or a real asset URL, **never empty**), `particles` (a seeded particle simulation in a Solver Box, filmed by the project camera — see [video-particles.md](video-particles.md); the whole system lives on the ITEM as `particleSystem`), `camera` (virtual camera over the whole stack — see [video-camera.md](video-camera.md)), and `null` (a transform with no picture, never drawn in any render: the parent other layers hang off — see [Layer parenting and null layers](video-keyframes.md#layer-parenting-and-null-layers-keyframeparenting); clip `url` is `""`; item `nullColor` (default `#ff3b30`) and `nullSize` (marker diameter in composition px, 2–2000, default 24) style only the editor's preview marker). The fast `/render` only accepts `video` and `image`; **`/render-onserver`** (full headless render) bakes in the richer timeline types — `text`, `shape`, `sequence`, `audio`, `motion`, `model3d`, `particles`, keyframes, filters — exactly like the desktop editor. A **device mockup** is not its own `mediaType` — it is a rendered `video` clip that optionally carries a `mockupConfig` for re-editing (see [video-motion.md](video-motion.md)).
210
+ Video-editor `mediaType` values include `video`, `image`, `audio`, `text`, `shape`, `adjustment`, `sequence` (compound clip — see [Sequence clips](#sequence-clips-mediatype-sequence)), `grid` (Grid Builder — a container that lays its members out by a rule; see [video-grid.md](video-grid.md)), `motion` (native MotionFast animated template — see video-motion.md (GreenLight Dash only)), `model3d` (a live 3D model rendered in its own pass — see [video-3d.md](video-3d.md); its clip `url` must be a `model-preset:` or `model-primitive:` sentinel or a real asset URL, **never empty**), `particles` (a seeded particle simulation in a Solver Box, filmed by the project camera — see [video-particles.md](video-particles.md); the whole system lives on the ITEM as `particleSystem`), `camera` (virtual camera over the whole stack — see [video-camera.md](video-camera.md)), and `null` (a transform with no picture, never drawn in any render: the parent other layers hang off — see [Layer parenting and null layers](video-keyframes.md#layer-parenting-and-null-layers-keyframeparenting); clip `url` is `""`; item `nullColor` (default `#ff3b30`) and `nullSize` (marker diameter in composition px, 2–2000, default 24) style only the editor's preview marker). The fast `/render` only accepts `video` and `image`; **`/render-onserver`** (full headless render) bakes in the richer timeline types — `text`, `shape`, `sequence`, `audio`, `motion`, `model3d`, `particles`, keyframes, filters — exactly like the desktop editor. A **device mockup** is not its own `mediaType` — it is a rendered `video` clip that optionally carries a `mockupConfig` for re-editing (see video-motion.md (GreenLight Dash only)).
209
211
 
210
212
  If you need to build the editor state by hand instead of using `/from-clips`, the canonical schema is the `sanitizeClip` / `sanitizeTimelineItem` / `buildPersistedState` functions in `frontend/src/components/videoEditor/VideoEditor.jsx`. Minimum viable shape:
211
213
 
@@ -271,7 +273,7 @@ the example until someone replaces it.
271
273
 
272
274
  **Project background.** Set `"background": { …backgroundConfig… }` at the `data` root to fill the stage behind every channel — a solid colour, gradient, GLSL shader, pattern, or image. It takes the same `backgroundConfig` object as shape backgrounds; the full schema, the gradient/shader preset ids, and the shader authoring rules live in the **Backgrounds (project & shape)** section below. Omit it (or use `"type": "transparent"`) for a transparent stage. Baked by **`/render-onserver`**; the fast `/render` ignores it. A bare colour string (`"background": "#3366cc"`) is coerced to `{"type": "solid", "solidColor": …}`; prefer the explicit object.
273
275
 
274
- **One live item per channel.** Treat every channel as one timeline track, not as a container of simultaneously composited layers. At any timeline time, a channel may have at most one active item. If two items' visible windows overlap, only one is guaranteed to render (the later-starting item commonly wins) and the save API does not reject the project. For an unsnapped item, its ordinary visible window is `[freeStart, freeStart + (trimEnd - trimStart))`; validate these windows before `PUT`. Put every simultaneously visible image, shape, text block, motion layer, or other visual on a separate channel. This rule also applies inside sequence timelines. Reuse one channel for consecutive, non-overlapping captions or shots only.
276
+ **One live item per channel.** Treat every channel as one timeline track, not as a container of simultaneously composited layers. At any timeline time, a channel may have at most one active item. If two items' visible windows overlap, only one is guaranteed to render (the later-starting item commonly wins) and the save API does not reject the project. For an unsnapped item, its ordinary visible window is `freeStart, freeStart + (trimEnd - trimStart))`; validate these windows before `PUT`. Put every simultaneously visible image, shape, text block, motion layer, or other visual on a separate channel. This rule also applies inside sequence timelines. Reuse one channel for consecutive, non-overlapping captions or shots only.
275
277
 
276
278
  **Keep unsnapped items sorted by `freeStart`.** On an `unsnapped` channel the editor treats the item BEFORE a clip in the `items` array as "the clip before it" — cross transitions, the seam button and the layout's overlap all read array neighbours, not time neighbours. The editor re-sorts on every insert, move and paste; an API write does not. After adding or moving items, sort each unsnapped channel's `items` by `freeStart` before `PUT`. An out-of-order array looks fine until the user adds a cross transition: the clip is then snapped against the wrong neighbour and jumps elsewhere on the timeline (e.g. past the end), so it appears to vanish.
277
279
 
@@ -299,7 +301,7 @@ Nothing else triggers a frame by itself: text animators, MotionFast `motion` lay
299
301
 
300
302
  The angle is how much of each frame interval the exposure covers, so wider = more blur *and* proportionally slower. The field is only written when blur is on, so projects that never enabled it round-trip unchanged. Table lives in `frontend/src/components/videoEditor/motionBlurLevels.js`. Honored by **`/render-onserver`**, **`/render-onserver-job`** and the desktop Download/Render — **ignored by the fast `/render`** and never applied in the editor preview (render-only by design). Worth enabling for projects with fast zooms/pans that would otherwise strobe. Renders get proportionally slower on accumulated frames (~16× each at the default), and a speed-ramped clip, a particle system or a live html clip makes every frame it covers an accumulated one.
301
303
 
302
- **Renderer.** Every project renders on the engine the app is set to — one app-wide setting, not a project field. Read it with `GET /api/video-editor/engine` (`engine`: `"webgl"`, the default, or `"webgpu"`). Preview and the desktop Download use it; the headless renders (`/render-onserver`, `/render-onserver-job`, `/render-still`) take it as the request's `"renderer"` field, which defaults to `"webgl"`, so pass the engine there to render what the editor shows. It matters wherever shading is written by hand rather than picked from a list: an uploaded Advanced Transition package is authored for one engine and is refused on the other, and a **custom** adjustment/layer effect (`"id": "custom"`) cannot run on WebGPU at all — its body is compiled at runtime, so the effect is skipped with a reason. Building a new template or transition: [custom-builds.md](custom-builds.md).
304
+ **Renderer.** Every project renders on the engine the app is set to — one app-wide setting, not a project field. Read it with `GET /api/video-editor/engine` (`engine`: `"webgl"`, the default, or `"webgpu"`). Preview and the desktop Download use it; the headless renders (`/render-onserver`, `/render-onserver-job`, `/render-still`) take it as the request's `"renderer"` field, which defaults to `"webgl"`, so pass the engine there to render what the editor shows. It matters wherever shading is written by hand rather than picked from a list: an uploaded Advanced Transition package is authored for one engine and is refused on the other, and a **custom** adjustment/layer effect (`"id": "custom"`) cannot run on WebGPU at all — its body is compiled at runtime, so the effect is skipped with a reason. Building a new template or transition: [custom-builds.md (GreenLight Dash only).
303
305
 
304
306
  **Sound & audio fades.** Clips with audio (`video` and `audio` media types) honor per-item `volume` (0–100 %, default 100; 0 also writes `muted: true`) and an intro/outro fade: `audioFadeIn` / `audioFadeOut` (seconds of the item's **placed** span; 0/absent = off; only stored when > 0) plus one `audioFadeCurve` for both ends (`"linear" | "smooth" | "exponential"`; only stored when it differs from the `"smooth"` default). The envelope multiplies onto `volume`; on a clip shorter than its two fades they overlap and multiply into a bump that never reaches full level. Fades span the item's placed bounds, so a partial (`rangeStart`/`rangeEnd`) render keeps the same shape. Applied identically in preview and the WebCodecs export paths (desktop Download and `/render-onserver`); the fast `/render` ignores dedicated audio clips entirely.
305
307
 
@@ -342,7 +344,7 @@ Rules:
342
344
  - To change such an edit, rebuild it with the `viral-edits` workflow (its build step rebuilds in place). Edit its inner layers by hand only for a one-word change the user asked for.
343
345
  - **A HyperFrames scene** (made by Convert to scenes): `"essential": { "kind": "hyperframes-scene", "v": 1, "recipe": { "url", "sceneId", "label", "clipValues", "compositionVariables", "sceneVariables", "sceneDefaults", "values", "sceneValues" } }`.
344
346
  - Its Essential panel sets per-scene values. A change rewrites only the `gl-vars` of the html pages inside the sequence; the layers, keys and camera stay.
345
- - To change the values, call `…/html-clips/{item_id}/hyperframes-scene-values` ([hyperframes.md](hyperframes.md#per-scene-values-after-convert-to-scenes)). Do not edit the pages' urls by hand.
347
+ - To change the values, call `…/html-clips/{item_id}/hyperframes-scene-values` (hyperframes.md (GreenLight Dash only)). Do not edit the pages' urls by hand.
346
348
  - When you write the project, keep `essential` exactly as it is. Without it, the edit can no longer be rebuilt.
347
349
  - The editor drops an `essential` sequence clip from `clips` once no item uses it.
348
350
  - **Rendering:** `/render-onserver` bakes sequences in fully; the fast `/render` rejects them with 400. Adjustment layers inside a sequence composite (grade + effects chain + layer mask alike). Known nested limits: the project's global Depth of Field doesn't composite inside a sequence (a sequence's own camera clip's depth of field does: AI Viral Edits use it), and inner audio only exports when the sequence item plays at flat 1× speed.
@@ -434,6 +436,6 @@ GET /api/moodboards/{board_id}/video-projects/{project_id}/glvideo?models=<JSON
434
436
 
435
437
  The editor's **Presets** tab also lists the **Interface scenes** library (called GL Motion before 14.0.25): 172 ready-made animated scenes (controls, cards, charts, checkout, coupons, countdowns, galleries…) in one style, all transparent (they sit over the video). Search and category chips filter them; Light / Dark and an accent recolour them. A card's **HTML clip** button inserts the scene as one standalone transparent HTML page, saved into the board's media (`ui-kit/<id>.html`) and placed as an HTML clip (`mediaType: "html"`) at the scene's own length.
436
438
 
437
- For a **whole film** — a story and its shots with the user's copy and pictures, a scenario card on the board, a voice-over, sound design and a render; with a GLEA delivery the film finished in a Video Editor project (a tutorial's interface as HTML scene clips, other films built with the editor's own layers) and rendered from it — use the `motion-film` workflow on the `greenlight` MCP server ([SKILL.md](../SKILL.md#ai-workflows-the-greenlight-mcp-server)) instead of inserting scenes one by one.
439
+ For a **whole film** — a story and its shots with the user's copy and pictures, a scenario card on the board, a voice-over, sound design and a render; with a GLEA delivery the film finished in a Video Editor project (a tutorial's interface as HTML scene clips, other films built with the editor's own layers) and rendered from it — use the `motion-film` workflow on the `greenlight` MCP server (SKILL.md (GreenLight Dash only)) instead of inserting scenes one by one.
438
440
 
439
441
  The library is the app's own, at `$GL_MOTION_KIT_DIR` in GLAI and GLEA terminals (its engine and scenes; `registry.json` beside them lists every scene with its editable texts and photo slots). To make one scene's page without the UI: `node -e "const fs=require('fs'),path=require('path'),vm=require('vm');const D=process.env.GL_MOTION_KIT_DIR,src=(f)=>fs.readFileSync(path.join(D,f),'utf8');globalThis.window=globalThis;const run=(f)=>{if(window.UIK)UIK.__loadingFile=f;vm.runInThisContext(src(f),{filename:f});};['easings.js','engine.js','catalog.js'].forEach(run);UIK.FILES.forEach(run);run('html-export.js');const el=UIK.elements.find((e)=>e.id==='odometer');console.log(UIK.toHTML(el,{theme:'light',sources:{easings:src('easings.js'),engine:src('engine.js'),files:[src(el.file)]}}));" > odometer.html`, then upload it and place it as an HTML clip.
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Shape layers
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Kinetic text: energetic in-and-out animations
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Text animation presets: typing reveals, text on shapes, highlights, loops, decoders, voice captions
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Text and animated captions
6
8
 
@@ -1,6 +1,8 @@
1
1
  > **GreenLight Motion Engine:** this is the GreenLight Dash Video Editor's project format, which the engine reads as is.
2
- > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` and run
3
- > `npx greenlight-motion build`. MotionFast templates (`mediaType: "motion"`) stay in GreenLight Dash.
2
+ > Ignore the `/api/...` routes and the app UI described here: in the engine you edit `project.json` (or `apply`) and run
3
+ > `npx greenlight-motion build`; what `GET /api/video-editor/capabilities` returns there is `npx greenlight-motion schema <topic>`
4
+ > here. `frontend/src/…` paths are files of the engine's public source repository. MotionFast templates (`mediaType: "motion"`)
5
+ > stay in GreenLight Dash.
4
6
 
5
7
  # GreenLight Dash — Cross transitions and layer entrances/exits
6
8