mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-27 11:37:02 -06:00
M13.15: qa project lifecycle; Collect Files makes its folder; agents cookbook
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
77ab92fb7d
commit
12235b5dc5
+35
-1
@@ -55,9 +55,10 @@ The server speaks JSON-RPC 2.0 over stdio, one message per line, and supports MC
|
||||
| `get_property {layer, path, comp?, time?}` | Value at a time, keyframes and expression. |
|
||||
| `set_property {layer, path, value?, time?, expression?, comp?}` | Sets a static value. With `time` it sets a keyframe; with `expression` it sets an expression. |
|
||||
| `add_keyframe {layer, path, time+value \| keys:[...], interpolation?}` | Adds keys, then optionally applies linear/bezier/hold/easyEase. |
|
||||
| `render_frame {comp?, time?, max_side?, path?, inline?}` | Returns a PNG image of a frame. |
|
||||
| `render_frame {comp?, time?, max_side?, path?, inline?, transparent?}` | Returns a PNG image of a frame; `transparent: true` keeps the alpha (as an RGB + Alpha render writes it) instead of compositing over the comp background. |
|
||||
| `open_project {path \| demo \| new}` / `save_project {path?}` | Open and save files. |
|
||||
| `undo {steps?}` / `redo {steps?}` | History. |
|
||||
| `batch {steps: [{command, params}], label?, atomic?}` | Several commands in one call and one undo step (`engine.batch`); `"$N.key"` in a param is step N's result (`"$1.layer"`). A failing step rolls the batch back and names the step. |
|
||||
| *(bridge)* `screenshot {panel?, id?}`, `ui_inspect`, `ui_elements {prefix?}`, `ui_click`, `ui_drag`, `ui_key`, `ui_type`, `ui_set`, `control {method, params}` | Look at and operate the live window. |
|
||||
|
||||
Layers are referenced by id (from `get_comp`), `"#n"` (1-based index from the top) or name. Comps are
|
||||
@@ -78,6 +79,39 @@ instead of being ignored.
|
||||
4. `execute_command {"command":"effect.apply","params":{"layer":2,"effect":"Gaussian Blur"}}`, then `set_property {"layer":2,"path":"effects/#1/blurriness","value":8}`
|
||||
5. `render_frame {"time":1.0}` lets you look at the result, and `save_project {"path":"intro.ecproj"}` saves it.
|
||||
|
||||
### Cookbook (from end-to-end QA)
|
||||
|
||||
The scenarios in `crates/automation/tests/qa/` and `apps/effectcraft-cli/tests/qa_template.rs`
|
||||
build real projects through these interfaces; they are worked examples of everything below.
|
||||
|
||||
* **Name things when you create them**: `layer.newText`, `layer.newShape`, `layer.newSolid`,
|
||||
`layer.newNull`, `layer.newCamera` and `layer.newLight` take `name`, so later calls can say
|
||||
`"layer": "Title"`. A reference that matches no layer is an error, never a silent no-op.
|
||||
* **Use the paths replies give you**: `effect.apply` returns `{effects: [uid], paths:
|
||||
["effects/#2"]}`; `layer.addShapeItem {kind, group?: uid|path}` returns `{uid, path}` (e.g.
|
||||
`contents/group/contents/gfill`), ready for `set_property`. `@uid` works as a whole path.
|
||||
* **One call, one undo step**: `batch {"steps":[{"command":"layer.newShape","params":{"kind":"ellipse","name":"Ring"}},{"command":"layer.addShapeItem","params":{"layer":"$1.layer","kind":"trim"}},{"command":"prop.addKey","params":{"layer":"$1.layer","path":"transform/opacity","time":0,"value":0}}]}`
|
||||
(a string param that is exactly `"$N"` or `"$N.key"` is replaced; `$2.path` is the trim's path).
|
||||
* **Expressions**: `set_property`/`get_property` replies carry `evaluated` (what renders) next to
|
||||
`value` (the keyframed value) and `expressionError` when the expression fails.
|
||||
* **Easing with Keyframe Velocity**: select keys by path, `keys.select {"keys":[{"layer":"Ring","path":"contents/trim/end","time":0}]}`,
|
||||
then `keys.velocity {"outSpeed":0,"outInfluence":33.33}`.
|
||||
* **Gradients**: `set_property {"path":"contents/gfill/colors","value":["#0080ff","#ffff00"]}` or
|
||||
`{"colors":[[0,"#0080ff"],[1,[1,1,0]]],"opacities":[[0,1],[1,0.5]]}`.
|
||||
* **Image sequences** import at 30 fps (Settings ▸ Import); `file.interpretFootage {"items":[id],
|
||||
"frameRate":12}` conforms them (the item and layers that ran to its end get the new length).
|
||||
* **Masks**: `layer.addMask {layer, shape: rect|ellipse, rect}` first, then `layer.mask.set
|
||||
{field: feather|expansion|opacity, value}`.
|
||||
* **Renders**: `renderQueue.add {comp, format: h264|prores|webm|png…, channels: rgba,
|
||||
proresProfile: 4444, output}` then `renderQueue.render {"wait": true}`. Check a render by
|
||||
importing it (`file.import`, `file.newCompFromSelection`) and `render_frame {transparent: true}`
|
||||
for its alpha. (WebM VP9 alpha is written, but read back opaque for now.)
|
||||
* **Essential Graphics**: controls can be addressed by name (`essential.set {"layer":"#1",
|
||||
"control":"Title","value":"John Smith"}`); a command that targets an explicit `comp` runs even
|
||||
when the active comp would disable it (`essential.exportTemplate {"comp":"Lower Third", …}`).
|
||||
* **History**: Levels of Undo defaults to 32 (`prefs.set {"key":"general.undoLevels","value":99}`);
|
||||
`history` lists branches and `history {"goto": id}` jumps between them.
|
||||
|
||||
### Motion tracking
|
||||
|
||||
Trackers live on the tracked layer (`Motion Trackers ▸ Tracker n ▸ Track Point n`) and are driven
|
||||
|
||||
Reference in New Issue
Block a user