@cueframe/skills 0.1.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/.agents/plugins/marketplace.json +12 -0
- package/.claude-plugin/marketplace.json +6 -0
- package/.claude-plugin/plugin.json +15 -0
- package/.codex-plugin/plugin.json +30 -0
- package/.cursor-plugin/plugin.json +1 -0
- package/.mcp.json +1 -0
- package/AGENTS.md +20 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +111 -0
- package/assets/icon.svg +16 -0
- package/assets/logo-400.png +0 -0
- package/gemini-extension.json +1 -0
- package/glama.json +1 -0
- package/hooks/hooks.json +7 -0
- package/hooks/session-inject.md +15 -0
- package/hooks/session-start.sh +6 -0
- package/llms-install.md +47 -0
- package/mcp.json +1 -0
- package/package.json +57 -0
- package/plugin.json +46 -0
- package/rules/cueframe.mdc +19 -0
- package/skills/add-music-bed/SKILL.md +100 -0
- package/skills/add-music-bed/agents/openai.yaml +6 -0
- package/skills/add-music-bed/assets/icon.svg +16 -0
- package/skills/brand-reel/SKILL.md +100 -0
- package/skills/brand-reel/agents/openai.yaml +6 -0
- package/skills/brand-reel/assets/icon.svg +16 -0
- package/skills/clip-a-talking-head/SKILL.md +101 -0
- package/skills/clip-a-talking-head/agents/openai.yaml +6 -0
- package/skills/clip-a-talking-head/assets/icon.svg +16 -0
- package/skills/composing-video/SKILL.md +702 -0
- package/skills/composing-video/agents/openai.yaml +6 -0
- package/skills/composing-video/assets/icon.svg +16 -0
- package/skills/cueframe-brand-demo/SKILL.md +257 -0
- package/skills/cueframe-brand-demo/agents/openai.yaml +6 -0
- package/skills/cueframe-brand-demo/assets/icon.svg +16 -0
- package/skills/cueframe-cli/SKILL.md +265 -0
- package/skills/cueframe-cli/agents/openai.yaml +6 -0
- package/skills/cueframe-cli/assets/icon.svg +16 -0
- package/skills/cueframe-component-authoring/SKILL.md +179 -0
- package/skills/cueframe-component-authoring/agents/openai.yaml +6 -0
- package/skills/cueframe-component-authoring/assets/icon.svg +16 -0
- package/skills/cueframe-compose-loop/SKILL.md +114 -0
- package/skills/cueframe-compose-loop/agents/openai.yaml +6 -0
- package/skills/cueframe-compose-loop/assets/icon.svg +16 -0
- package/skills/cueframe-compose-loop/references/preview-workflow.md +37 -0
- package/skills/cueframe-connect/SKILL.md +45 -0
- package/skills/cueframe-connect/agents/openai.yaml +6 -0
- package/skills/cueframe-connect/assets/icon.svg +16 -0
- package/skills/cueframe-product-video/SKILL.md +293 -0
- package/skills/cueframe-product-video/agents/openai.yaml +6 -0
- package/skills/cueframe-product-video/assets/icon.svg +16 -0
- package/skills/cueframe-scene-shot/SKILL.md +68 -0
- package/skills/cueframe-scene-shot/agents/openai.yaml +6 -0
- package/skills/cueframe-scene-shot/assets/icon.svg +16 -0
- package/skills/cueframe-storyboard/SKILL.md +104 -0
- package/skills/cueframe-storyboard/agents/openai.yaml +6 -0
- package/skills/cueframe-storyboard/assets/icon.svg +16 -0
- package/skills/every-format-from-one-edit/SKILL.md +87 -0
- package/skills/every-format-from-one-edit/agents/openai.yaml +6 -0
- package/skills/every-format-from-one-edit/assets/icon.svg +16 -0
- package/skills/extracting-brand-kits/SKILL.md +159 -0
- package/skills/extracting-brand-kits/agents/openai.yaml +6 -0
- package/skills/extracting-brand-kits/assets/icon.svg +16 -0
- package/skills/launch-video/SKILL.md +93 -0
- package/skills/launch-video/agents/openai.yaml +6 -0
- package/skills/launch-video/assets/icon.svg +16 -0
- package/skills/make-a-social-reel/SKILL.md +105 -0
- package/skills/make-a-social-reel/agents/openai.yaml +6 -0
- package/skills/make-a-social-reel/assets/icon.svg +16 -0
- package/skills/rebrand-a-video/SKILL.md +95 -0
- package/skills/rebrand-a-video/agents/openai.yaml +6 -0
- package/skills/rebrand-a-video/assets/icon.svg +16 -0
- package/skills/video-craft-standards/SKILL.md +128 -0
- package/skills/video-craft-standards/agents/openai.yaml +6 -0
- package/skills/video-craft-standards/assets/icon.svg +16 -0
- package/skills-dir.d.ts +1 -0
- package/skills-dir.js +2 -0
- package/skills.sh.json +1 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-product-video
|
|
3
|
+
description: Use when turning a screen recording (with cursor/click events) into a polished, auto-zooming product video or demo reel via CueFrame — e.g. "make a product demo from this Browserbase capture", "auto-zoom this screen recording to where the user clicked", "turn this walkthrough into a social demo". This is a USE-CASE recipe over the CueFrame primitives in the `cueframe-cli` skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CueFrame — Product Video recipe
|
|
7
|
+
|
|
8
|
+
A **use-case recipe**, not new framework surface. CueFrame's engine only knows
|
|
9
|
+
primitives (`upload` → `composition put` → `render`, the `reframe` viewport, the
|
|
10
|
+
overlay/effect primitives). This skill is the *judgment* on top: how to turn a
|
|
11
|
+
captured walkthrough into a product video that looks good. This tells you *what*
|
|
12
|
+
to author, not how to transport it.
|
|
13
|
+
|
|
14
|
+
**Drive the primitives over MCP if you can call tools** (`new_composition` /
|
|
15
|
+
`apply_composition` / `validate_composition` / `create_render` — see the
|
|
16
|
+
`cueframe-connect` skill for the one-line setup). The `npx -y cueframe@0.5 …` commands
|
|
17
|
+
written out below are the same operations for a terminal or CI job with no MCP
|
|
18
|
+
host; see the `cueframe-cli` skill.
|
|
19
|
+
|
|
20
|
+
## The pipeline
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
capture (video + cursor/click points) → auto-zoom (points → reframe)
|
|
24
|
+
→ compose (video track + per-clip reframe) → polish (overlay primitives)
|
|
25
|
+
→ render
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 1. Capture → timed focus points
|
|
29
|
+
|
|
30
|
+
Get a screen recording **plus** the cursor/click events with viewport
|
|
31
|
+
coordinates and timestamps (e.g. from a browser-automation capture). Normalize
|
|
32
|
+
every point to `{ t: seconds, x: 0..1, y: 0..1 }` against the **real captured
|
|
33
|
+
viewport** — these are the *focus points* the zoom follows. Measure the rendered
|
|
34
|
+
video's true duration (ffprobe) and map point times onto it.
|
|
35
|
+
|
|
36
|
+
## 2. Points → reframe (auto-zoom)
|
|
37
|
+
|
|
38
|
+
The framework owns the tuning. Canonical implementation:
|
|
39
|
+
`autoZoom(points, style)` in `@cueframe/composition` (timed focus points →
|
|
40
|
+
gapless `reframe` segments; never re-derive this with an LLM — it drifts). Pick a
|
|
41
|
+
**style**, never raw numbers:
|
|
42
|
+
|
|
43
|
+
| style | zoom (`<1` punches in) | feel |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `subtle` | 0.80 | gentle, corporate |
|
|
46
|
+
| `standard` | 0.67 | default |
|
|
47
|
+
| `punchy` | 0.55 | snappy, social |
|
|
48
|
+
|
|
49
|
+
The tiling rule (what `autoZoom` does — use this until it's exposed as
|
|
50
|
+
`cueframe compose from-points`): sort points by `t`; group points within
|
|
51
|
+
`mergeGap`s; pad each group `prePad` before / `postPad` after; drop groups
|
|
52
|
+
shorter than `minZoom`; merge overlapping windows; emit `frame-center` zoom 1
|
|
53
|
+
in the gaps and a `point` punch-in (`focus:{mode:"point",x,y}`, `zoom` = the
|
|
54
|
+
style's) over each window. Result → `source.reframe.segments` on the clip.
|
|
55
|
+
|
|
56
|
+
## 3. Compose
|
|
57
|
+
|
|
58
|
+
One video track, the screen recording as a media clip carrying the reframe.
|
|
59
|
+
`npx -y cueframe@0.5 composition put <projectId> -b @composition.json` (see `cueframe-cli`).
|
|
60
|
+
Choose `-a 16:9` for landscape product video, `9:16` for social.
|
|
61
|
+
|
|
62
|
+
## 4. Polish — layer overlay primitives (this is what makes it look "produced")
|
|
63
|
+
|
|
64
|
+
A bare auto-zoom reads as a raw screen-grab. Add overlay/effect clips referencing
|
|
65
|
+
registered primitives (`registry/params-required.json` lists each one's params;
|
|
66
|
+
`$brand:` tokens bind brand colors/fonts at render). Tasteful default set for a
|
|
67
|
+
product demo:
|
|
68
|
+
|
|
69
|
+
| Goal | primitiveId | kind |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| animated cursor tracing the click path | `cursor-flow` / `simulated-cursor` | overlay |
|
|
72
|
+
| title / context | `lower-third` or `heroText` | overlay |
|
|
73
|
+
| highlight a clicked element | `marker-highlight` / `pulsing-indicator` | overlay |
|
|
74
|
+
| device/browser frame | `device-mockup-zoom` / `browser-flow` | overlay |
|
|
75
|
+
| captions (if narrated) | the top-level `captions` field | — |
|
|
76
|
+
| finish/look | `color-grade` + `vignette` | effect |
|
|
77
|
+
| several cells sharing space that should reflow (feature grid, rail + fluid content) | author a component on `FlexLayout` from `@cueframe/animate` (see `cueframe-component-authoring`) | overlay (authored) |
|
|
78
|
+
|
|
79
|
+
Static PiP / split-screen is `region` + `fit` on the clips (EX3 / EX4). Cells that must
|
|
80
|
+
**reflow together** or hold mixed content are one authored component built on `FlexLayout`;
|
|
81
|
+
the catalog `flex-layout` primitive is that same layout, but a bare composition overlay has
|
|
82
|
+
no children, so on its own it draws only the rig outlines.
|
|
83
|
+
|
|
84
|
+
A primitive is the `source` of a clip; the clip wraps it with `id`/`startTime`/`duration`:
|
|
85
|
+
- Overlay clip (on a `kind:"overlay"` track): `{ "id":"t1", "startTime":1, "duration":3, "source":{ "kind":"overlay", "primitiveId":"lower-third", "params":{…}, "zPlane":"front" } }`.
|
|
86
|
+
- Effect clip (on a `kind:"effect"` track): `{ "id":"e1", "startTime":0, "duration":9, "source":{ "kind":"effect", "primitiveId":"color-grade", "params":{…} } }`.
|
|
87
|
+
Simultaneous overlays go on **separate tracks** — clips on one track can't overlap in time.
|
|
88
|
+
**Don't over-decorate** — 2–4 primitives. Cursor + title + grade is usually enough.
|
|
89
|
+
|
|
90
|
+
## 5. Render
|
|
91
|
+
|
|
92
|
+
First use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md):
|
|
93
|
+
check framing with `preview_frame` and click/zoom timing with an affected-window `preview_clip`.
|
|
94
|
+
For a small revision, verify that change and relevant regressions without exporting the whole film.
|
|
95
|
+
When delivering the finished video:
|
|
96
|
+
|
|
97
|
+
`npx -y cueframe@0.5 render <projectId> -o out.mp4 --json`. Verify the output (ffprobe +
|
|
98
|
+
sample frames) before declaring done.
|
|
99
|
+
|
|
100
|
+
## Worked examples — composition JSON
|
|
101
|
+
|
|
102
|
+
These are **orientation, not the contract.** The live wire schema is
|
|
103
|
+
`npx -y cueframe@0.5 schema composition`, and the way to know a draft is correct is
|
|
104
|
+
`npx -y cueframe@0.5 composition validate -b @composition.json` — it runs the same
|
|
105
|
+
validator the server enforces, with no save and no render. Discover + validate
|
|
106
|
+
before you render; never spend a render to find a schema mistake.
|
|
107
|
+
|
|
108
|
+
Each block below is a complete `@composition.json` (the bare object `composition put`
|
|
109
|
+
accepts: top-level `v`, `format`, `tracks`, optional `captions`). All five validate
|
|
110
|
+
against the real wire schema + save invariants (swap the `<…MediaId>` placeholders for
|
|
111
|
+
real `npx -y cueframe@0.5 upload` ids). Conventions that keep them valid:
|
|
112
|
+
|
|
113
|
+
- Tracks hold **`contents`** (not `clips`); each clip wraps a `source`.
|
|
114
|
+
- A clip's `source.kind` must match the track `kind`: `media` → `video`/`image`/`audio`
|
|
115
|
+
tracks, `overlay` → `overlay` tracks, `effect` → `effect` tracks.
|
|
116
|
+
- Clip/segment times are **seconds** (`startTime`, `duration`, `startSec`, `endSec`,
|
|
117
|
+
`trim`); caption word times are **milliseconds** (`startMs`/`endMs`).
|
|
118
|
+
- `region`/`fit` are **clip-level** (siblings of `source`); `reframe` lives on the media `source`.
|
|
119
|
+
- Clips on one track can't overlap — put simultaneous layers on **separate tracks**.
|
|
120
|
+
- `zoom < 1` punches in (range `[0.1, 1]`, default `1`). Durations are illustrative — match your source.
|
|
121
|
+
|
|
122
|
+
### EX1 · Auto-zoom screen demo (16:9)
|
|
123
|
+
One screen recording with `reframe` punch-ins (the `autoZoom` output: `frame-center` in the gaps, `point` over each click) + a cinematic grade.
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"v": 1,
|
|
128
|
+
"format": { "aspectRatio": "16:9", "fps": 30 },
|
|
129
|
+
"tracks": [
|
|
130
|
+
{
|
|
131
|
+
"id": "v-screen", "kind": "video", "contents": [
|
|
132
|
+
{
|
|
133
|
+
"id": "rec", "startTime": 0, "duration": 12,
|
|
134
|
+
"source": {
|
|
135
|
+
"kind": "media", "mediaId": "<mediaId>",
|
|
136
|
+
"reframe": { "segments": [
|
|
137
|
+
{ "startSec": 0, "endSec": 2, "focus": { "mode": "frame-center" }, "zoom": 1 },
|
|
138
|
+
{ "startSec": 2, "endSec": 5, "focus": { "mode": "point", "x": 0.28, "y": 0.42 }, "zoom": 0.6, "ease": { "in": 0.4, "out": 0.4 } },
|
|
139
|
+
{ "startSec": 5, "endSec": 7, "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } },
|
|
140
|
+
{ "startSec": 7, "endSec": 10, "focus": { "mode": "point", "x": 0.72, "y": 0.66 }, "zoom": 0.55, "ease": { "in": 0.4, "out": 0.4 } },
|
|
141
|
+
{ "startSec": 10, "endSec": 12, "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } }
|
|
142
|
+
] }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "fx", "kind": "effect", "contents": [
|
|
149
|
+
{ "id": "grade", "startTime": 0, "duration": 12, "source": { "kind": "effect", "primitiveId": "color-grade", "params": { "preset": "cinematic" } } }
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### EX2 · Social vertical with captions (9:16)
|
|
157
|
+
Reframe + a `lower-third` title, then a `cursor-flow` overlay (non-overlapping on one overlay track), transcript `captions` (ms timing), warm grade. `$brand:` refs bind brand colors/fonts at render.
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"v": 1,
|
|
162
|
+
"format": { "aspectRatio": "9:16", "fps": 30, "platform": "tiktok" },
|
|
163
|
+
"tracks": [
|
|
164
|
+
{
|
|
165
|
+
"id": "v", "kind": "video", "contents": [
|
|
166
|
+
{
|
|
167
|
+
"id": "rec", "startTime": 0, "duration": 10,
|
|
168
|
+
"source": {
|
|
169
|
+
"kind": "media", "mediaId": "<mediaId>",
|
|
170
|
+
"reframe": { "segments": [
|
|
171
|
+
{ "startSec": 0, "endSec": 4, "focus": { "mode": "point", "x": 0.3, "y": 0.4 }, "zoom": 0.7, "ease": { "in": 0.4, "out": 0.4 } },
|
|
172
|
+
{ "startSec": 4, "endSec": 10, "focus": { "mode": "point", "x": 0.62, "y": 0.55 }, "zoom": 0.62, "ease": { "in": 0.4, "out": 0.4 } }
|
|
173
|
+
] }
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "ov", "kind": "overlay", "contents": [
|
|
180
|
+
{
|
|
181
|
+
"id": "title", "startTime": 0, "duration": 3.5,
|
|
182
|
+
"source": {
|
|
183
|
+
"kind": "overlay", "primitiveId": "lower-third",
|
|
184
|
+
"params": {
|
|
185
|
+
"text": "AI video, one command", "subtitle": "cueframe", "variant": "modern",
|
|
186
|
+
"tokens": { "textColor": "$brand:colors.textOnMedia", "accentColor": "$brand:colors.accent", "fontFamily": "$brand:fonts.heading.family" }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"id": "cursor", "startTime": 3.5, "duration": 6,
|
|
192
|
+
"source": {
|
|
193
|
+
"kind": "overlay", "primitiveId": "cursor-flow",
|
|
194
|
+
"params": {
|
|
195
|
+
"waypoints": [ { "x": 200, "y": 180 }, { "x": 540, "y": 240, "click": true, "label": "Generate" }, { "x": 1040, "y": 520, "click": true, "label": "Publish" } ],
|
|
196
|
+
"cursorColor": "$brand:colors.text", "showTargets": true
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"id": "fx", "kind": "effect", "contents": [
|
|
204
|
+
{ "id": "grade", "startTime": 0, "duration": 10, "source": { "kind": "effect", "primitiveId": "color-grade", "params": { "preset": "warm" } } }
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
],
|
|
208
|
+
"captions": {
|
|
209
|
+
"segments": [
|
|
210
|
+
{ "words": [
|
|
211
|
+
{ "text": "Watch", "startMs": 0, "endMs": 320 },
|
|
212
|
+
{ "text": "this", "startMs": 320, "endMs": 560, "emphasis": true },
|
|
213
|
+
{ "text": "render", "startMs": 560, "endMs": 980 },
|
|
214
|
+
{ "text": "in", "startMs": 980, "endMs": 1120 },
|
|
215
|
+
{ "text": "one", "startMs": 1120, "endMs": 1360, "emphasis": true },
|
|
216
|
+
{ "text": "command", "startMs": 1360, "endMs": 1900 }
|
|
217
|
+
] }
|
|
218
|
+
],
|
|
219
|
+
"style": { "fontFamily": "Inter", "fontSize": 6.5, "fontWeight": 900, "color": "#ffffff", "highlightColor": "#10B981", "position": "bottom", "textTransform": "uppercase" }
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### EX3 · Picture-in-picture (16:9)
|
|
225
|
+
Full-frame screen recording + a webcam **inset** placed with `region`/`fit` on a second video track (composites on top by track order). Two uploads → two `mediaId`s.
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"v": 1,
|
|
230
|
+
"format": { "aspectRatio": "16:9", "fps": 30 },
|
|
231
|
+
"tracks": [
|
|
232
|
+
{ "id": "v-screen", "kind": "video", "contents": [
|
|
233
|
+
{ "id": "screen", "startTime": 0, "duration": 10, "source": { "kind": "media", "mediaId": "<screenMediaId>" } }
|
|
234
|
+
] },
|
|
235
|
+
{ "id": "v-cam", "kind": "video", "contents": [
|
|
236
|
+
{ "id": "cam", "startTime": 0, "duration": 10, "source": { "kind": "media", "mediaId": "<webcamMediaId>" }, "region": { "x": 0.68, "y": 0.04, "w": 0.3, "h": 0.3 }, "fit": "cover" }
|
|
237
|
+
] }
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### EX4 · Split-screen (16:9)
|
|
243
|
+
Two sources side-by-side, each with a half-frame `region` on its own video track.
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"v": 1,
|
|
248
|
+
"format": { "aspectRatio": "16:9", "fps": 30 },
|
|
249
|
+
"tracks": [
|
|
250
|
+
{ "id": "v-left", "kind": "video", "contents": [
|
|
251
|
+
{ "id": "left", "startTime": 0, "duration": 8, "source": { "kind": "media", "mediaId": "<leftMediaId>" }, "region": { "x": 0, "y": 0, "w": 0.5, "h": 1 }, "fit": "cover" }
|
|
252
|
+
] },
|
|
253
|
+
{ "id": "v-right", "kind": "video", "contents": [
|
|
254
|
+
{ "id": "right", "startTime": 0, "duration": 8, "source": { "kind": "media", "mediaId": "<rightMediaId>" }, "region": { "x": 0.5, "y": 0, "w": 0.5, "h": 1 }, "fit": "cover" }
|
|
255
|
+
] }
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### EX5 · Presenter intro — title behind the speaker (9:16)
|
|
261
|
+
Talking-head with an `active-speaker` reframe and a `heroText` title at `zPlane:"behind-subject"`. The speaker **detection** and the person **matte** are both resolved automatically at render (see the `cueframe-cli` skill's "Render resolves expensive intents" section) — author the intent, render, done.
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"v": 1,
|
|
266
|
+
"format": { "aspectRatio": "9:16", "fps": 30 },
|
|
267
|
+
"tracks": [
|
|
268
|
+
{ "id": "v", "kind": "video", "contents": [
|
|
269
|
+
{ "id": "cam", "startTime": 0, "duration": 6, "source": { "kind": "media", "mediaId": "<mediaId>", "reframe": { "segments": [ { "startSec": 0, "endSec": 6, "focus": { "mode": "active-speaker" }, "zoom": 0.8 } ] } } }
|
|
270
|
+
] },
|
|
271
|
+
{ "id": "ov", "kind": "overlay", "contents": [
|
|
272
|
+
{ "id": "hero", "startTime": 0.5, "duration": 5, "source": {
|
|
273
|
+
"kind": "overlay", "primitiveId": "heroText",
|
|
274
|
+
"params": { "text": "SHIP IN MINUTES", "fontSizePct": 14, "textColor": "$brand:colors.textOnMedia", "fontFamily": "$brand:fonts.heading.family" },
|
|
275
|
+
"zPlane": "behind-subject", "anchor": { "space": "scene", "x": 0.5, "y": 0.42 }
|
|
276
|
+
} }
|
|
277
|
+
] }
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Notes / honesty
|
|
283
|
+
|
|
284
|
+
- **Picture-in-picture / inset cards render** — per-clip output-space placement
|
|
285
|
+
(`region:{x,y,w,h}` in `[0,1]` + `fit`) is wired for PiP / inset / split-screen,
|
|
286
|
+
for video, image, and overlay clips. Set `region`/`fit` on the **clip** (siblings
|
|
287
|
+
of `source`, not inside it — as an agent, patch them with an `apply_composition`
|
|
288
|
+
`clip.update` op: `{ type: 'clip.update', clipId, patch: { region, fit } }`); two
|
|
289
|
+
clips with different placement composite by track order instead of occluding the
|
|
290
|
+
background. See EX3 / EX4 below.
|
|
291
|
+
- This recipe lives in a skill on purpose: the engine stays use-case-free; the
|
|
292
|
+
product opinions (style, which primitives, layout) live here and ship via
|
|
293
|
+
`npx -y cueframe@0.5 install`. Add sibling recipes (`cueframe-podcast-clip`, …) the same way.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "CueFrame — Product Video recipe"
|
|
3
|
+
short_description: "Use when turning a screen recording (with cursor/click events) into a…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $cueframe-product-video when turning a screen recording (with cursor/click events) into a polished, auto-zooming product video or demo reel via CueFrame — e.g. \"make a product demo from this Browserbase capture\", \"auto-zoom this screen recording to where the user clicked\", \"turn this walkthrough into a social demo\"."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-scene-shot
|
|
3
|
+
description: Author a CueFrame 3D world-object shot as canonical SceneShotSpecV2 JSON. Use for slabs, pages, phones, laptops, captured component or video surfaces, world text, camera motion, studio lighting, focus, and product-shot recipes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CueFrame scene shots
|
|
7
|
+
|
|
8
|
+
Use `scene.add` and `scene.update` through `apply_composition`. Author the scene JSON; CueFrame owns the generated wrapper, preparation, resource admission, previews, and export.
|
|
9
|
+
|
|
10
|
+
Before authoring, read `cueframe://scene-shot`. It serves the canonical generated `SceneShotSpecV2` schema, exact operation contracts, supported brand tokens, refusal rules, and a copyable nested slab-and-page recipe. Do not infer fields from an older example.
|
|
11
|
+
|
|
12
|
+
On the CueFrame desktop app that resource is unreachable — its MCP surface is tools-only and no `cueframe://` URI resolves there. Call the `get_scene_contract` tool instead: same document, served in sections (`essentials` by default, then `rules` and `schema`).
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
17
|
+
for the available hosted/local lane. Inspect affected camera/focus/entrance windows in motion,
|
|
18
|
+
not only keyframes. A scene tweak can finish with preview evidence; export for final delivery.
|
|
19
|
+
|
|
20
|
+
1. Create or open a composition at the target aspect and FPS.
|
|
21
|
+
2. Register every image or video source. Capture-backed component surfaces use an exact component id, source version id, capture frame, layout, and optional bake scale.
|
|
22
|
+
3. Read `cueframe://scene-shot` (desktop: `get_scene_contract`), copy its `world-objects` recipe, and replace placeholder ids and copy.
|
|
23
|
+
4. Send `apply_composition` with `dry_run: true`. Fix the exact reported field path.
|
|
24
|
+
5. Apply the same batch for real. Preview the first frame, object entrances, focus transitions, and the last frame.
|
|
25
|
+
6. Revise with `scene.update`; do not hand-edit a generated wrapper.
|
|
26
|
+
7. Render only after surfaces report ready and the previews show the intended pixels.
|
|
27
|
+
|
|
28
|
+
## Ownership boundaries
|
|
29
|
+
|
|
30
|
+
The composition owns clip start, duration, ordering, cuts, and transitions. The scene owns objects, camera, environment, backdrop, post effects, constraints, and normalized animation. Scene clips occupy a dedicated full-frame front overlay track. Outer region, position, scale, rotation, fit, clip effects, and internal fades are refused because they would create two transform or timing owners.
|
|
31
|
+
|
|
32
|
+
`referenceSize` must have the same aspect ratio as the composition. Coordinates are reference pixels with origin at frame center, +X right, +Y down, and +Z toward the viewer. Equal-aspect outputs scale uniformly.
|
|
33
|
+
|
|
34
|
+
Animation keyframe `at` is normalized over clip duration. Easing belongs to the keyframe it arrives at. The first keyframe has no easing; each later keyframe supplies `linear`, `hold`, or cubic `bezier` easing. Topology, bindings, text content, fonts, material roles, and object kind remain static within a shot.
|
|
35
|
+
|
|
36
|
+
## Objects and surfaces
|
|
37
|
+
|
|
38
|
+
V2 supports nested `group` layers and canonical `slab`, `page`, `phone`, `laptop`, and `text` layers. Use each object's declared surface slot:
|
|
39
|
+
|
|
40
|
+
- `source: "image"` binds an admitted PNG, JPEG, or WebP through the outer `assets` map.
|
|
41
|
+
- `source: "component"` captures an immutable component source at the declared frame and layout. Omitted `bakeScale` lets preparation select 2× or 3×; an explicit insufficient scale refuses.
|
|
42
|
+
- `source: "video"` binds an admitted media id with frame-addressed start/end facts. Video decoding and committed-frame readiness are sealed before drawing.
|
|
43
|
+
- `source: "color"` supplies an unlit solid surface.
|
|
44
|
+
|
|
45
|
+
Never insert a URL, raw HTML, shader source, or placeholder art into a surface. Every required slot must resolve before capture. UI surfaces and world text are unlit and color-managed; bodies use declared physical material roles. Invisible objects do not write depth.
|
|
46
|
+
|
|
47
|
+
World text participates in camera, depth, occlusion, and focus. Screen text stays fixed above the world result. Both are line-authored with no automatic reflow. Every exact font family, weight, and style used by base or emphasized runs must be admitted.
|
|
48
|
+
|
|
49
|
+
## Lighting and post
|
|
50
|
+
|
|
51
|
+
Choose the generated studio environment for named studio profiles or `{kind:"photographic-studio-v1"}` for the fixed photographic recipe. Arbitrary HDR fields are refused. Backdrops may be transparent, solid, linear, or radial. Focus is per-pixel world depth; sample the actual object face rather than its layer origin when choosing distance and range.
|
|
52
|
+
|
|
53
|
+
Brand tokens are allowed only in schema-declared color and font-family fields. Read the token enums from the resource. A font token resolves the family only; authored weight and style still require exact admitted bytes.
|
|
54
|
+
|
|
55
|
+
## Limits and refusals
|
|
56
|
+
|
|
57
|
+
The contract admits at most 32 layers, 4 devices, 16 distinct image slots, 256 keyframes per channel, and 2048 keyframes per shot. Raw HTML, custom shader properties, imported GLB models, arbitrary external HDR environments, skeletal animation, and physics are unsupported. Unknown keys, duplicate ids, missing bindings, non-finite values, aspect mismatch, budget overflow, and unsupported capabilities fail with a named code and exact path.
|
|
58
|
+
|
|
59
|
+
Composition-level global wrap effects do not reach front-overlay scene clips. Author grain, vignette, focus, backdrop, and environment inside the scene.
|
|
60
|
+
|
|
61
|
+
## Delivery checks
|
|
62
|
+
|
|
63
|
+
- The rendered subject is a real object with a real admitted surface.
|
|
64
|
+
- Every key entrance, reflection sweep, screen update, and focus transition was previewed.
|
|
65
|
+
- Device and slab bodies receive the intended light while UI colors remain unchanged.
|
|
66
|
+
- Text uses the intended admitted face and remains legible.
|
|
67
|
+
- The output aspect matches the authored reference aspect.
|
|
68
|
+
- The final response identifies the composition, render, source provenance, and any intentional unsupported boundary.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "CueFrame scene shots"
|
|
3
|
+
short_description: "Author a CueFrame 3D world-object shot as canonical SceneShotSpecV2 JSON. Use…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $cueframe-scene-shot to author a CueFrame 3D world-object shot as canonical SceneShotSpecV2 JSON."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-storyboard
|
|
3
|
+
description: >-
|
|
4
|
+
Use BEFORE composing when starting a NEW video from scratch and you need to plan its structure — turning a rough ask ("make a launch video", "30s promo", "an explainer for our API") into a concrete beat flow. Owns the intake + storyboard step: interview the user for the brief, resolve the format from the platform, and lay out the hook→body→cta beats that drive the compose workflow. Triggers on "plan a video", "storyboard", "structure this video", "outline the video", "where do I start", or any new-video ask that has no structure yet. Hand off to composing-video for per-beat craft.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CueFrame Storyboard: brief → flow
|
|
8
|
+
|
|
9
|
+
This is a new-video planning workflow. For revisions to an approved plan, preserve its structure
|
|
10
|
+
and use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
11
|
+
to verify the requested change; do not restart intake, Director authoring, or final export by default.
|
|
12
|
+
|
|
13
|
+
> **The bar:** the `video-craft-standards` skill (GET /v1/skills/video-craft-standards) defines DONE for every artifact class — per-class MUST checklists and kill criteria. Read it before composing and score against it before rendering. When this skill and that document disagree, the standards win.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## The one idea
|
|
17
|
+
|
|
18
|
+
**You are the planner.** You have the user, the whole conversation, the brand, and the judgment — you are
|
|
19
|
+
the smartest thing in this loop. CueFrame is the hands. This skill is the **intake + structure** step:
|
|
20
|
+
turn intent into a concrete **beat flow** *before* you seed a composition, so the curated workflow (media →
|
|
21
|
+
components → seed) executes a plan instead of a guess. Craft — grounded-vs-slop, the verify loop — belongs
|
|
22
|
+
to the sibling **composing-video** skill; this skill gets you a flow, then hands off to it.
|
|
23
|
+
|
|
24
|
+
Do not offload the *thinking* to CueFrame. There is no server that plans the video for you, and you would
|
|
25
|
+
not want one — it would be a blind model with none of your context. Plan here, in the open, with the user.
|
|
26
|
+
|
|
27
|
+
## 1. Interview for the brief — ask only what you can't infer
|
|
28
|
+
|
|
29
|
+
Fill the brief from the conversation first; ask the user **only for the 1–2 things you genuinely cannot
|
|
30
|
+
infer**, and STATE what you assume for the rest. Never wall them with a form.
|
|
31
|
+
|
|
32
|
+
- **Goal / intent** *(required)* — what is this video FOR? launch, promo, explainer, demo, teaser, recap.
|
|
33
|
+
- **Platform** *(sets the format)* — reels / tiktok / shorts → **9:16, ~20s** · youtube → **16:9, ~45s** ·
|
|
34
|
+
linkedin / x → **1:1, ~20s** · web → **16:9, ~30s**. (Or an explicit aspect ratio + duration.)
|
|
35
|
+
- **Audience**, **tone** (punchy / premium-calm / playful / authoritative), **CTA**, **must-includes**
|
|
36
|
+
(a number, a name, a screen), **references** (a style to echo), **brand kit**.
|
|
37
|
+
|
|
38
|
+
If the ask is "make a launch video for our API," you already have goal + a hint of audience — ask "Reels,
|
|
39
|
+
YouTube, or your site?" and infer the rest: *"I'll assume a developer audience and a punchy tone — say if
|
|
40
|
+
you'd rather it feel calm/premium."* One or two questions, not seven.
|
|
41
|
+
|
|
42
|
+
## 2. Structure the flow — the storyboard
|
|
43
|
+
|
|
44
|
+
Lay the duration into **beats** using the fixed editorial vocabulary
|
|
45
|
+
**hook → context → body → proof → cta → outro** (use what the piece needs — most short-form is
|
|
46
|
+
hook → body → cta). For each beat decide:
|
|
47
|
+
|
|
48
|
+
- a one-line **intent** (what this beat does for the viewer),
|
|
49
|
+
- a **duration** (they sum to the target; the hook earns attention in ~3s),
|
|
50
|
+
- a **media need** — real footage is the strongest grounding and CueFrame's home turf, so reach for it
|
|
51
|
+
first; otherwise `generate` a *purposeful* clip (a diagram of the real mechanism, the real UI) or `find`
|
|
52
|
+
stock. Animated text over a gradient is not grounding — it's the slop default,
|
|
53
|
+
- an optional **graphic** (a lower-third, title, CTA card),
|
|
54
|
+
- a **caption** and/or a **VO/script** line.
|
|
55
|
+
|
|
56
|
+
**Ground it, don't invent it.** Pick every graphic/scene from `list_catalog` (filter by `useCase`/`tier`)
|
|
57
|
+
— never hardcode hex or positions or name a component that doesn't exist. Theme from the brand kit. If
|
|
58
|
+
you're planning over real footage, read `get_media_context` (detected faces + transcript) so beat timing,
|
|
59
|
+
crops, and captions land on what's actually there.
|
|
60
|
+
|
|
61
|
+
## 3. Show the flow, then persist it as a Brief
|
|
62
|
+
|
|
63
|
+
Show the user the beat list **first** — a five-line outline. It is cheap to change here and expensive to
|
|
64
|
+
change after a render, so this is where you converge on structure. On their go, **persist the plan with
|
|
65
|
+
`create_brief`** — the beats/goal/format/gates you just elicited map 1:1 onto its fields, and the plan stops
|
|
66
|
+
being chat-ephemeral (it survives the session, carries a cost quote, and is honored field-by-field):
|
|
67
|
+
|
|
68
|
+
1. `import_media` / `generate_media` for each beat's media need,
|
|
69
|
+
2. `create_brief` — goal, audience, platform/format, durationSec, tone, cta, locale, and the beats
|
|
70
|
+
(each with its editorial intent and, when you're cutting real footage, MOMENT PINNING
|
|
71
|
+
`source: {mediaId, startSec, endSec}` from the transcript — honored to-the-frame or refused).
|
|
72
|
+
Relay the response's **quote** (compose + estimated render) BEFORE composing.
|
|
73
|
+
3. `compose { briefId }` — the Director authors FROM your brief; every field is honored or the
|
|
74
|
+
compose is refused loudly naming the field. Gates: put `holdAt: ["layout"]` in the brief's `gates` when
|
|
75
|
+
the user wants to approve the storyboard mid-flight; `autoApprove: true` for hands-off.
|
|
76
|
+
4. `score_composition` / `consult` to fix the weakest beat,
|
|
77
|
+
5. `create_render` for the MP4.
|
|
78
|
+
|
|
79
|
+
**Two graphic media — pick per beat, and review accordingly:** a `card` (verbatim HTML in
|
|
80
|
+
`seededGraphics`) is a STATIC graphic — cheap, approve it from a still; a **component**
|
|
81
|
+
(`create_component`, `useCurrentFrame`) is MOTION — a still is one frame, so preview it before trusting it.
|
|
82
|
+
Seeded graphics you author into the brief are carried VERBATIM as locked clips — the Director never
|
|
83
|
+
re-authors them; `exclusions` bans graphic kinds you never want it to author.
|
|
84
|
+
|
|
85
|
+
Then load **composing-video** and apply its craft to make each beat good.
|
|
86
|
+
|
|
87
|
+
## Related skills & positioning
|
|
88
|
+
|
|
89
|
+
This skill owns **structure/intake**; its siblings own execution and craft — defer to them:
|
|
90
|
+
|
|
91
|
+
- **composing-video** — the craft/quality layer (grounded specificity vs. slop, the vision → rubric →
|
|
92
|
+
verify loop). Load it *after* you have a flow; it makes each beat good.
|
|
93
|
+
- **cueframe-compose-loop** — the author → render → verify → fix convergence loop + the ship bar.
|
|
94
|
+
- **cueframe-product-video** — click-points → auto-zoom tiling + PiP for screen demos.
|
|
95
|
+
- **cueframe-brand-demo** — brand-token vocabulary + auto intro/outro/logo for branded launches.
|
|
96
|
+
- **cueframe-component-authoring** — fork → preview → push for a custom graphic a beat needs.
|
|
97
|
+
- **cueframe-cli** — the `cueframe` binary + wire mechanics.
|
|
98
|
+
|
|
99
|
+
## The boundary
|
|
100
|
+
|
|
101
|
+
You own the **vision** (the one idea and the flow for *this* video) and **data correctness** (a wrong
|
|
102
|
+
number you supply is rendered faithfully — the mistake is yours). CueFrame owns being faithful, legible,
|
|
103
|
+
and giving you real footage + real components to plan against. Reason from this; skip the whole flow only
|
|
104
|
+
for a re-render of an approved composition or a single trivial one-off.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "CueFrame Storyboard: brief → flow"
|
|
3
|
+
short_description: "Use BEFORE composing when starting a NEW video from scratch and you need to…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $cueframe-storyboard before composing when starting a NEW video from scratch and you need to plan its structure — turning a rough ask (\"make a launch video\", \"30s promo\", \"an explainer for our API\") into a concrete beat flow."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: every-format-from-one-edit
|
|
3
|
+
description: Derives content-aware 9:16, 1:1, and 4:5 siblings from one finished composition — same edit, every platform, no re-editing. Triggers on "make this vertical too", "I need this for TikTok and LinkedIn", "every aspect ratio", "square version of this", "resize for Reels", "one video, all platforms", "port this edit to Shorts".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Every format from one edit
|
|
7
|
+
|
|
8
|
+
You finish ONE edit; you get back its siblings for every platform — 9:16 for
|
|
9
|
+
Reels/TikTok/Shorts, 1:1 and 4:5 for feeds — derived content-aware from the master,
|
|
10
|
+
subject-tracked rather than letterboxed, each judged and rendered on its own. The edit decisions
|
|
11
|
+
are made once; the formats are a job, not a re-edit.
|
|
12
|
+
|
|
13
|
+
## Before you start
|
|
14
|
+
|
|
15
|
+
Confirm which master and which target platforms before setup. When the first tool call
|
|
16
|
+
approaches and CueFrame isn't connected, load **`cueframe-connect`** and follow it once.
|
|
17
|
+
|
|
18
|
+
Then straight to deriving — this whole job is minutes when the master is good.
|
|
19
|
+
|
|
20
|
+
## Inputs
|
|
21
|
+
|
|
22
|
+
- **The master composition** (required): a finished, approved edit — find it via
|
|
23
|
+
`list_compositions` if the user doesn't have the id. If the master isn't done, finish it first
|
|
24
|
+
(this skill multiplies quality AND flaws).
|
|
25
|
+
- **Target aspects**: default all three siblings — 9:16, 1:1, 4:5. The documented derive lane
|
|
26
|
+
starts from a 16:9 master.
|
|
27
|
+
- **Per-platform tweaks**: default none — determinism is the point. Take an explicit ask (e.g.
|
|
28
|
+
"shorter for TikTok") as a separate edit on the derived sibling.
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
33
|
+
for each affected sibling. Check motion as well as layout where the new crop changes visibility.
|
|
34
|
+
A correction to one sibling does not require rendering the master or the other unchanged siblings.
|
|
35
|
+
|
|
36
|
+
1. **Verify the master is actually done.** It passed its class checklist, its audio was
|
|
37
|
+
decided, its render was approved. Deriving from a draft ships the draft's flaws four times.
|
|
38
|
+
2. **Derive each sibling.** `derive_composition` per target aspect — the reframe is
|
|
39
|
+
content-aware: it tracks the subject into the new frame instead of letterboxing. Each
|
|
40
|
+
sibling is a real composition you can edit independently afterward; the master is never
|
|
41
|
+
touched.
|
|
42
|
+
3. **Audit every sibling on real pixels — required, not optional.** `preview_frame` each
|
|
43
|
+
sibling at t=0, hook-end, and each card's midpoint; describe each still. What to look for
|
|
44
|
+
per aspect: the subject's head fully in the vertical frame; cards and captions inside the
|
|
45
|
+
safe area (no critical copy in the outer ~8%); no beat where the tighter crop lost the thing
|
|
46
|
+
the beat exists to show.
|
|
47
|
+
4. **Fix per-sibling, surgically.** Where a crop or card misbehaves, `apply_composition` on
|
|
48
|
+
THAT sibling — nudge a `setCropIntents` segment, resize a card for the narrower frame
|
|
49
|
+
(re-shell with `applyMotionPreset` in a following call if you replace the card). Don't
|
|
50
|
+
re-edit the story; the story is the master's.
|
|
51
|
+
5. **Confirm the audio carried.** The master's decided audio — bed, ducking, beat-aligned cuts
|
|
52
|
+
(`materializeGrid` markers), or its intentional silence — rides into each sibling. Verify
|
|
53
|
+
the bed is present and the silence decision, if any, still holds; the sibling's delivery
|
|
54
|
+
note repeats it. If a sibling needs a different bed, `search_resources` honoring the brand
|
|
55
|
+
kit's `musicMood` and swap it on that sibling only.
|
|
56
|
+
6. **Judge each sibling as its own artifact.** `score_composition` per sibling with the
|
|
57
|
+
master's vision as `editorialIntent`. A 9:16 sibling is a social reel and answers to that
|
|
58
|
+
class's checklist — hook inside 2 seconds still applies in the new crop. Fix worst-first to
|
|
59
|
+
≥ 7.5.
|
|
60
|
+
7. **Render each approved sibling.** `create_render` → `wait_job (kind:"render")` per
|
|
61
|
+
composition. One final render per approval; iterate with previews.
|
|
62
|
+
|
|
63
|
+
## What good looks like
|
|
64
|
+
|
|
65
|
+
Quoted from `video-craft-standards` (cross-cutting rules — every artifact):
|
|
66
|
+
|
|
67
|
+
> **MUST** Safe-area respected: no critical copy in the outer ~8% of frame.
|
|
68
|
+
|
|
69
|
+
> **MUST** One final render per approval; iterate with previews, not renders.
|
|
70
|
+
|
|
71
|
+
> **MUST** Delivery never ends with "done": the last message carries the output link and where
|
|
72
|
+
> to find it, plus the intentional-silence note if any.
|
|
73
|
+
|
|
74
|
+
And the class rule that governs each sibling: a derived 9:16 answers to §1 (Social reel) —
|
|
75
|
+
*"**MUST (K)** The hook lands inside 2 seconds"* — a derived 16:9 to its own class. Derivation
|
|
76
|
+
changes the frame, never the bar.
|
|
77
|
+
|
|
78
|
+
## Delivering
|
|
79
|
+
|
|
80
|
+
The last message is a manifest, never "done":
|
|
81
|
+
|
|
82
|
+
- Every sibling's render link, labeled by aspect and platform, and where each lives (project +
|
|
83
|
+
composition id — the master's id too, since it stays the source of truth).
|
|
84
|
+
- The master's attribution list (it covers all siblings — same assets).
|
|
85
|
+
- The intentional-silence note, restated once, if the master chose silence.
|
|
86
|
+
- Any sibling-specific edits you made (which crop nudged, which card resized) so future master
|
|
87
|
+
edits know what to re-check after re-deriving.
|