@kolbo/mcp 1.93.2 → 1.93.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skill/GENERATED.md +1 -1
- package/skill/SKILL.md +18 -4
- package/skill/references/models/seedance.md +2 -2
- package/skill/references/models/seedance25.md +1 -1
- package/skill/references/workflows/adobe.md +23 -52
- package/skill/references/workflows/production-planning.md +6 -3
- package/src/tools/generate.js +2 -2
- package/skill/references/workflows/after-effects-motion.md +0 -193
- package/skill/references/workflows/davinci-resolve.md +0 -163
package/package.json
CHANGED
package/skill/GENERATED.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AUTO-GENERATED — do not edit
|
|
2
2
|
|
|
3
|
-
This tree is mirrored from kolbo-code@
|
|
3
|
+
This tree is mirrored from kolbo-code@54e9713, the single source of truth.
|
|
4
4
|
Canonical source: packages/opencode/skills/kolbo/
|
|
5
5
|
Distribution: .github/workflows/sync-skill-to-plugin.yml
|
|
6
6
|
|
package/skill/SKILL.md
CHANGED
|
@@ -221,11 +221,25 @@ A URL from `generate_*`, `list_media`, `get_media`, or a prior `upload_media` is
|
|
|
221
221
|
- `upload_media` is only for a **local disk path** or an **external** (non-Kolbo) URL — `files`/`source_images`/`image_url` reject unknown hosts with `400`; a Kolbo URL passes through as-is.
|
|
222
222
|
- Same rule after compaction: pull the URL from `.kolbo/production.md` and reuse it. Never download-then-reupload.
|
|
223
223
|
|
|
224
|
-
## ⚠️
|
|
224
|
+
## ⚠️ Route video per use case (decide — do not cargo-cult)
|
|
225
225
|
|
|
226
|
-
|
|
226
|
+
Pick the cheapest route that actually controls what the brief needs. Do not invent a pipeline.
|
|
227
227
|
|
|
228
|
-
|
|
228
|
+
**1. Recurring identity (cast / product / location must match across shots)**
|
|
229
|
+
Map → Visual DNA sheets → Confirm → `generate_elements` (or DNA-locked Multishot). Asset sheets earn their cost here.
|
|
230
|
+
|
|
231
|
+
**2. Composition must be locked before motion** (deliberate framing, Pixar-like kids beats, specific staging, hero product plate, user-approved look)
|
|
232
|
+
Generate the needed keyframe still(s) first, then animate with `generate_video_from_image` / first-last / Elements **using those images as real inputs**. Stills without attaching them to the video call are waste.
|
|
233
|
+
|
|
234
|
+
**3. Pure text-to-video / Multishot Locked Intro — only when keyframes are 100% unnecessary**
|
|
235
|
+
Use for generic b-roll, ambient motion, simple stock-like scenes, or any brief where the video model inventing composition is fine and stills would not improve control. If you are not sure keyframes add nothing, prefer route 2.
|
|
236
|
+
|
|
237
|
+
**Anti-patterns (HARD)**
|
|
238
|
+
- Do not generate N stills and then run a Multishot T2V that never attaches them.
|
|
239
|
+
- Do not default every "make a video" to keyframes (generic b-roll does not need them).
|
|
240
|
+
- Do not default every narration-only brief to T2V when the user asked for tightly designed cute/controlled shots — those often need keyframes.
|
|
241
|
+
|
|
242
|
+
Scene dialogue is **never** `generate_speech` or `generate_lipsync` on a Seedance shoot. Seedance 2 / 2.5 perform quoted lines written into the shot beat — English or Latin transliteration of Hebrew (`"shalom"`), never Hebrew script. For native Hebrew speech, prefer Gemini Omni Flash 1.1 or Gemini Omni 1. Full flow: `references/workflows/production-planning.md`.
|
|
229
243
|
|
|
230
244
|
## ⚠️ Load the matching skill BEFORE generating (HARD RULE)
|
|
231
245
|
|
|
@@ -452,7 +466,7 @@ If at this point you still don't know which `references/` file to load, default
|
|
|
452
466
|
## Media selection preferences
|
|
453
467
|
Honor explicit models, presets, budget and inputs. Choose only eligible catalog candidates with all required capabilities. Use requested presets; otherwise use fitting presets when useful. For video generation, editing and lip-sync, when the user has not explicitly selected an output resolution, use the cheapest supported output resolution from the live catalog and pass it explicitly; do not inherit an expensive provider default. Preserve explicit user-selected resolution/settings. Finish fully, cinematic, professional, final, production and available credits are NOT permission to increase resolution. Never infer output resolution from reference media or export settings. A budget is a ceiling, not a spending target. Do not upscale or regenerate at a higher tier without explicit user authorization. If pricing or supported resolutions cannot be verified, inspect the catalog before dispatch; never invent a tier. Models with fixed output resolution use their native output. Never treat a policy refusal as a technical failure or route around safeguards.
|
|
454
468
|
Default images and edits: GPT Image 2.5 Flare/Sunburst; medium for value, high for ordinary maximum quality. Reserve xhigh/max for exceptional dense or difficult multilingual text after medium/high prove insufficient; do not automatically spend on retries. Nano Banana 2 is secondary. Seedream 5.0 Pro favors cinematic aesthetics over complex instruction fidelity; Wan 2.7 Pro is another creative alternative. Z Image/P Image for cheap tests. Midjourney for artistic concepts only, never editing. Soul V2 for realistic people/UGC concepts; derive character sheets before registering finished Visual DNA. Mirage Film 2 for environments and cinematic inspiration.
|
|
455
|
-
Default video: Seedance 2.5. Kling specializes in controlled single-image and first/last-frame shots. Wan 3.0 specializes in motion graphics and Hebrew
|
|
469
|
+
Default video: Seedance 2.5 for general cinematic work (not Hebrew speech). Kling specializes in controlled single-image and first/last-frame shots. Wan 3.0 specializes in motion graphics and animated typography — native Hebrew speech is poor; attached-audio lip-sync works well. MiniMax H3 offers higher resolution and strong attached-audio lip-sync; H3 Max favors speed at lower resolution with the same audio lip-sync strength. **Native Hebrew dialogue:** Gemini Omni Flash 1.1 or Gemini Omni 1 (best). Seedance 2 / 2.5 do not speak Hebrew — use Latin transliteration in quotes on Seedance, or switch to Gemini Omni. Grok Imagine 1.5 and Seedance 2.0 are non-Hebrew alternatives. P Video/Draft for cheap fast tests. Use base, edit or extend variants only with their required inputs.
|
|
456
470
|
Existing-video lip-sync: Sync 3 for active-speaker handling; PixVerse for cartoons/2D and economical faster work. Portrait lip-sync: Veed Fabric or HeyGen Avatar; P Avatar for budget work. LTX Audio to Video for camera/environment motion with audio-driven performance.
|
|
457
471
|
Default music: Suno v6. ElevenLabs Music is an alternative, especially for duration-directed scoring. Both accept custom duration requests; validate the selected tool schema and inspect actual output duration.
|
|
458
472
|
|
|
@@ -13,7 +13,7 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
|
|
|
13
13
|
|
|
14
14
|
## Creative direction takes precedence
|
|
15
15
|
|
|
16
|
-
The current user brief overrides template defaults and illustrative examples. Keep the two-layer organization, but include only relevant locks. State concrete camera trajectory and visible action prominently; optics numbers, equipment names, repetition and word counts are not guarantees of fidelity. Preserve a continuous-shot exception even when other scenes are multishot. For one shot use `Single continuous shot`, `Total: Xs / 1 shot / AR`, one SHOT heading and `multi_shots: false`; for multiple shots use `Multishot ON` and matching counts. AR comes from the brief, never a copied example.
|
|
16
|
+
The current user brief overrides template defaults and illustrative examples. Keep the two-layer organization, but include only relevant locks. State concrete camera trajectory and visible action prominently; optics numbers, equipment names, repetition and word counts are not guarantees of fidelity. Preserve a continuous-shot exception even when other scenes are multishot. For one shot use `Single continuous shot`, `Total: Xs / 1 shot / AR`, one SHOT heading and `multi_shots: false`; for multiple shots use `Multishot ON` and matching counts. AR comes from the brief, never a copied example. Seedance does not speak Hebrew — use Latin transliteration in quotes or route native Hebrew to Gemini Omni. Narration reserved for post does not belong in the generation prompt.
|
|
17
17
|
|
|
18
18
|
## Universal Rules (apply to EVERY Seedance / Elements prompt)
|
|
19
19
|
|
|
@@ -142,7 +142,7 @@ Appearance locks WHO. Persona locks HOW THEY BEHAVE — without it Seedance rend
|
|
|
142
142
|
## Dialogue & expression
|
|
143
143
|
|
|
144
144
|
- **Dialogue is PERFORMED by the model, never by a TTS tool.** Quoted lines in the prompt come back as synced speech with lip movement and room tone, together with the SFX you name in AUDIO. Scene dialogue therefore never routes through `generate_speech` or `generate_lipsync` — write the line in quotes inside its shot beat and let Seedance act it.
|
|
145
|
-
- **
|
|
145
|
+
- **Hebrew (HARD):** Seedance 2 / 2.5 do **not** speak Hebrew. Never put Hebrew-script dialogue in the prompt. Use Latin transliteration in quotes (`שלום` → `"shalom"`), or recommend Gemini Omni Flash 1.1 / Gemini Omni 1 for native Hebrew. Do not promise Seedance Hebrew success. Attached-audio lip-sync on 2.5 is unreliable unless audio length matches the clip and the prompt has no Hebrew script. Keep narration reserved for post out of the prompt.
|
|
146
146
|
- `list_models` reports `sound_generation_type: "none"` for Seedance 2 / 2.5 because there is no in-app sound toggle (`sound_baked_in: true`). That field does NOT mean the model is silent. Do not read it as a reason to add TTS.
|
|
147
147
|
- For silent tension, deliver it as expression, not speech: `He does not speak. His expression clearly says: "…"`.
|
|
148
148
|
|
|
@@ -11,7 +11,7 @@ Load this file when the user wants a **Seedance 2.5** video (they said "2.5" / "
|
|
|
11
11
|
|
|
12
12
|
**Audio:** Seedance 2.5 emits real synced audio. `list_models` shows `sound_generation_type: none` only because there is no in-app toggle (`sound_baked_in: true`) — it does NOT mean the model is silent, and it is never a reason to reach for TTS. Quoted dialogue is PERFORMED (synced voices, lip movement, room tone) alongside the SFX named in AUDIO, so scene dialogue never goes through `generate_speech` or `generate_lipsync`; write the lines in quotes inside their shot beats.
|
|
13
13
|
|
|
14
|
-
**
|
|
14
|
+
**Hebrew (HARD):** Seedance 2.5 does **not** speak Hebrew. Never put Hebrew-script dialogue in the prompt. Use Latin transliteration in quotes per speaker (`שלום` → `"shalom"`), or route native Hebrew speech to Gemini Omni Flash 1.1 / Gemini Omni 1. Attached-audio lip-sync sometimes works when audio length matches the clip exactly and the prompt has no Hebrew script; Kolbo accepts native audio uploads (no black-video workaround). Asset tags always retain their exact stored spelling, including `@אביב` / `#ישראל` literally. Keep post-production VO out of the generation prompt.
|
|
15
15
|
|
|
16
16
|
**Use the cheapest supported tier unless the user selected an output resolution.** Resolution is a credit MULTIPLIER, not a flat rate. Relative to 720p: 480p ×0.44, 1080p ×2.25. A 30s pass costs ~540cr at 480p against ~1230cr at 720p and ~2770cr at 1080p. When no output resolution was selected and 480p is the cheapest supported tier, block the film at 480p, get the user's sign-off on staging, performance and timing, then re-run only the approved cut at a higher delivery resolution if the user explicitly authorizes that resolution increase. Approval of the creative cut alone does not authorize a more expensive resolution. If no output resolution was selected, use the cheapest supported tier from the live catalog even for final work; pass it explicitly.
|
|
17
17
|
|
|
@@ -1,70 +1,41 @@
|
|
|
1
1
|
# Premiere Pro & After Effects Workflow
|
|
2
2
|
|
|
3
|
-
Use these rules whenever the user wants an agent to inspect
|
|
4
|
-
|
|
5
|
-
For motion graphics in After Effects (shape layers, animated text, effects, expressions), also read `references/workflows/after-effects-motion.md` before writing any script.
|
|
3
|
+
Use these rules whenever the user wants an agent to inspect or edit an open Premiere Pro or After Effects project through Kolbo. The Kolbo panel inside the Adobe app is a separate desktop authority boundary: a Kolbo account is necessary, but the editor's approval inside the panel is the final gate for every edit.
|
|
6
4
|
|
|
7
5
|
## Connect and target safely
|
|
8
6
|
|
|
9
7
|
1. Call `adobe_list_sessions` before the first Adobe action.
|
|
10
|
-
2. If no session is listed, ask the user to open **Window → Extensions → Kolbo Studio** in Premiere Pro or After Effects
|
|
11
|
-
3. If one session is active, `session_id` may be omitted. If several are active, show each session's `name` (Premiere Pro / After Effects), `adobe_version
|
|
8
|
+
2. If no session is listed, ask the user to open **Window → Extensions → Kolbo Studio** in Premiere Pro or After Effects, sign in, and click the **AI agents** (robot) button in the panel header until its dot turns green. Do not substitute any other Kolbo tool for the panel relay.
|
|
9
|
+
3. If one session is active, `session_id` may be omitted. If several are active, show each session's `name` (Premiere Pro / After Effects), `adobe_version`, platform and id, and ask which to target. Never guess.
|
|
12
10
|
4. Keep the chosen `session_id` on every later Adobe call in the task. Re-list after a disconnect or app restart; ids are process-scoped.
|
|
13
11
|
|
|
14
|
-
There is no MCP logout tool. The editor
|
|
15
|
-
|
|
16
|
-
## Command lifecycle and approval
|
|
17
|
-
|
|
18
|
-
Every Adobe tool except `adobe_list_sessions` and `adobe_get_command_status` returns a **command record**, not the result. Poll `adobe_get_command_status` with its `command_id` until the status is terminal: `succeeded`, `failed`, `denied` or `canceled`.
|
|
19
|
-
|
|
20
|
-
- Reads (`adobe_get_project`, `adobe_get_timeline`) run without approval. Everything else waits for **Allow once / Allow for this session / Deny** in the panel.
|
|
21
|
-
- `awaiting_approval` is not a polling state. Tell the user to approve or deny in the Kolbo panel, then check once more after they answer.
|
|
22
|
-
- `denied` is final. Do not retry the same change with cosmetic edits; ask the user what they want instead.
|
|
23
|
-
- "Allow for this session" lives only in the panel's memory and ends on disconnect. Never tell the user it persists and never ask them to enable it for you.
|
|
24
|
-
- Pass a stable `idempotency_key` when a timeout may make you retry the same command. A new intent needs a new key.
|
|
25
|
-
|
|
26
|
-
## Choosing the right tool
|
|
27
|
-
|
|
28
|
-
| Goal | Tool |
|
|
29
|
-
|---|---|
|
|
30
|
-
| See the project / active sequence or comp (tracks, clips with start/end, playhead; or comp layers) | `adobe_get_project`, `adobe_get_timeline` |
|
|
31
|
-
| Put a Kolbo clip in the bin, or at the Premiere playhead | `adobe_import_media`, `adobe_place_on_timeline` |
|
|
32
|
-
| New Premiere sequence (no dialog, copies the open sequence's settings) | `adobe_create_sequence` |
|
|
33
|
-
| Captions onto the active Premiere sequence | `transcribe_audio` → `adobe_import_captions` with the `.srt` URL |
|
|
34
|
-
| After Effects edit: comps, timed/trimmed clips, titles, solids, fades, keyframes, music | `adobe_edit_composition` |
|
|
35
|
-
| After Effects motion graphics beyond those operations | `adobe_run_script` (read `after-effects-motion.md`) |
|
|
36
|
-
| Check what it actually looks like | `adobe_capture_frame` → look at the returned `url` |
|
|
12
|
+
There is no MCP logout tool. The editor disconnects from the panel header button.
|
|
37
13
|
|
|
38
|
-
|
|
14
|
+
## Inspect before changing
|
|
39
15
|
|
|
40
|
-
|
|
16
|
+
- Start with `adobe_get_project`, then `adobe_get_timeline` for the active Premiere sequence or After Effects composition. Both are read-only and run without approval.
|
|
17
|
+
- Timeline responses are bounded; pass `max_clips` when you only need the first clips.
|
|
41
18
|
|
|
42
|
-
|
|
43
|
-
- Start a new piece with `comp.create` (defaults 1920×1080, 30 fps). Later operations in the same batch target it.
|
|
44
|
-
- Times are **seconds on the composition timeline**. For media: `start_seconds` = where it begins, `trim_start_seconds` = seconds skipped at the head of the source, `duration_seconds` = visible length.
|
|
45
|
-
- Crossfade = overlap two shots by 0.3–1 s and animate the upper shot's opacity 0 → 100 across the overlap. New layers stack on top, so add the later shot after the earlier one.
|
|
46
|
-
- **Name every layer you will address later** and use that exact name in `layer.update` / `layer.animate`. Indexes shift as layers are added (1 = top).
|
|
47
|
-
- `fit: "cover"` fills the frame (default), `"contain"` letterboxes, `"none"` keeps source size. Keyframed `scale` values are absolute percentages, so animate scale on titles and solids, not on fitted media, unless you first read the fitted scale from `adobe_get_timeline`.
|
|
48
|
-
- Titles default to Arial Bold, white, centred. Add `stroke_width` 3–6 (black stroke) whenever text sits over bright or busy footage - white text on a light shot is invisible.
|
|
49
|
-
- Music: add audio with `layer.add_media`, then animate `audio_levels` from 0 dB to about −40 dB over the last 1.5–2 s for a clean fade-out.
|
|
50
|
-
- Solids are sent to the bottom automatically (backgrounds).
|
|
19
|
+
## Command lifecycle and approval
|
|
51
20
|
|
|
52
|
-
|
|
21
|
+
Every Adobe tool except `adobe_list_sessions` and `adobe_get_command_status` returns a **command record**, not the result. Poll `adobe_get_command_status` with its `command_id` until the status is terminal: `succeeded`, `failed`, `denied` or `canceled`.
|
|
53
22
|
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
23
|
+
- `awaiting_approval` is not a polling state. Stop and tell the user to approve or deny the request in the Kolbo panel, then check once more after they answer.
|
|
24
|
+
- `denied` is final. Do not retry the same edit with cosmetic changes; ask the user what they want instead.
|
|
25
|
+
- "Allow for this session" lives only in the panel's memory and ends when the editor disconnects. Never tell the user it persists, and never ask them to enable it for you.
|
|
26
|
+
- Pass a stable `idempotency_key` when a timeout may cause you to retry the same command. A new intent needs a new key.
|
|
58
27
|
|
|
59
|
-
##
|
|
28
|
+
## Media, sequences and captions
|
|
60
29
|
|
|
61
|
-
- `
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
30
|
+
- `adobe_import_media` and `adobe_place_on_timeline` accept exactly one Kolbo `media_id` (preferred) or a Kolbo-owned HTTPS `url`. Third-party hosts, HTTP, private network and guessed URLs are rejected; import third-party files into Kolbo first.
|
|
31
|
+
- To generate then edit: run the Kolbo generation tool, wait for its successful result, then pass the real media id. Never place a still-running generation.
|
|
32
|
+
- `adobe_place_on_timeline` drops the clip into a free track at the playhead of the Premiere work sequence, or into the active After Effects composition. There is no time, track, trim or transition control in v1; do not promise one. Ask the user to position the playhead first when placement matters.
|
|
33
|
+
- `adobe_create_sequence` and `adobe_import_captions` are Premiere Pro only. In After Effects they fail with `UNSUPPORTED_HOST`.
|
|
34
|
+
- For captions, create the SRT with `transcribe_audio`, then pass its Kolbo-hosted `.srt` URL to `adobe_import_captions`.
|
|
35
|
+
- There is no raw ExtendScript tool. If the user asks for an edit outside these commands, say it is not available through agents yet and suggest doing it in the panel or the app.
|
|
65
36
|
|
|
66
37
|
## Completion proof
|
|
67
38
|
|
|
68
|
-
1. Re-read with `adobe_get_timeline` after an edit.
|
|
69
|
-
2.
|
|
70
|
-
3.
|
|
39
|
+
1. Re-read with `adobe_get_timeline` or `adobe_get_project` after an edit.
|
|
40
|
+
2. Report what changed, which session was targeted, and that the editor approved it.
|
|
41
|
+
3. A command is complete only when `adobe_get_command_status` shows `succeeded`. An accepted enqueue is not proof the edit happened.
|
|
@@ -9,10 +9,13 @@ starts here, **before** a single video credit is spent. Most users do not know
|
|
|
9
9
|
this flow exists; they ask for a film and expect a film. Walk them through it
|
|
10
10
|
rather than jumping to a prompt.
|
|
11
11
|
|
|
12
|
-
Skip
|
|
13
|
-
|
|
12
|
+
**Skip asset mapping** only when keyframes and DNA are **100% unnecessary**: generic b-roll,
|
|
13
|
+
ambient motion, simple stock-like scenes where the video model inventing composition is fine.
|
|
14
|
+
For tightly designed kids/educational beats, Pixar-like staging, or any brief where composition
|
|
15
|
+
must be locked, generate keyframes (or DNA) first and attach them to the video call — do not
|
|
16
|
+
invent stills and then run a Multishot T2V that ignores them.
|
|
14
17
|
|
|
15
|
-
## The order is not negotiable
|
|
18
|
+
## The order is not negotiable (when cast/product identity must lock)
|
|
16
19
|
|
|
17
20
|
1. **Map** every element the script needs — including the **session plan** (names).
|
|
18
21
|
2. **Create** each one as an asset (Visual DNA), grouped into the planned sessions.
|
package/src/tools/generate.js
CHANGED
|
@@ -617,7 +617,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
617
617
|
// retired textToVideoGeneration path and was stale.
|
|
618
618
|
server.tool(
|
|
619
619
|
'generate_video',
|
|
620
|
-
'Generate a video from a text prompt using Kolbo AI. For SEVERAL different videos, pass all their prompts in `prompts` in ONE call (one combined widget) — never a series of separate calls. For animating an existing still image into motion, use generate_video_from_image instead. For a coordinated multi-scene video campaign, use generate_creative_director with workflow_type="video". Supports reference images (for style/composition guidance) and Visual DNA for character consistency. Seedance 2/2.5 PERFORM quoted dialogue natively (synced voice, lip movement, room tone) — do not route scene dialogue to generate_speech or generate_lipsync; write it in ENGLISH
|
|
620
|
+
'Generate a video from a text prompt using Kolbo AI. For SEVERAL different videos, pass all their prompts in `prompts` in ONE call (one combined widget) — never a series of separate calls. For animating an existing still image into motion, use generate_video_from_image instead. For a coordinated multi-scene video campaign, use generate_creative_director with workflow_type="video". Supports reference images (for style/composition guidance) and Visual DNA for character consistency. Seedance 2/2.5 PERFORM quoted dialogue natively (synced voice, lip movement, room tone) — do not route scene dialogue to generate_speech or generate_lipsync; write it in ENGLISH or Latin transliteration of Hebrew ("shalom"), never Hebrew script — Seedance 2/2.5 do not speak Hebrew; prefer Gemini Omni Flash 1.1 or Gemini Omni 1 for native Hebrew. Resolution is a credit MULTIPLIER (vs 720p: 480p x0.44, 1080p x2.25, 4k x4.95), so draft at 480p and re-run only the approved cut at delivery resolution. ROUTE BEFORE CALLING: when reference images anchor IDENTITY (specific characters, a specific product, a location that must match) — especially 2+ of them — that is generate_elements, not this tool; reference_images here are loose style/composition hints. Decide the right tool FIRST: a mis-routed call still starts a PAID generation, and switching tools afterwards without cancel_generation leaves the user paying for both. Returns the final video URL when complete.',
|
|
621
621
|
{
|
|
622
622
|
prompt: z.string().optional().describe('Text description of the video to generate. Required unless `prompts` is provided.'),
|
|
623
623
|
prompts: promptsField('videos'),
|
|
@@ -1427,7 +1427,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
1427
1427
|
// ─── generate_elements ─────────────────────────────────────
|
|
1428
1428
|
server.tool(
|
|
1429
1429
|
'generate_elements',
|
|
1430
|
-
'Generate a video from reference elements (images, videos, and/or audio) + a text prompt. Use when the user wants to animate specific uploaded/referenced assets — e.g. "animate this product", "put these 3 characters into a scene". PRIMARY ROUTE FOR A DNA-ANCHORED MULTI-SHOT FILM: one call can carry the whole sequence — seedance-2-5 takes 4-30s, up to 30 shots and 20 Visual DNAs in a SINGLE generation (seedance-2: 4-15s, 9 DNAs) — instead of a stack of separate clips. DIALOGUE IS PERFORMED NATIVELY: quoted dialogue in the prompt comes back as synced voices with lip movement, room tone and the SFX named in the AUDIO block — never route scene dialogue to generate_speech or generate_lipsync. Write dialogue in ENGLISH
|
|
1430
|
+
'Generate a video from reference elements (images, videos, and/or audio) + a text prompt. Use when the user wants to animate specific uploaded/referenced assets — e.g. "animate this product", "put these 3 characters into a scene". PRIMARY ROUTE FOR A DNA-ANCHORED MULTI-SHOT FILM: one call can carry the whole sequence — seedance-2-5 takes 4-30s, up to 30 shots and 20 Visual DNAs in a SINGLE generation (seedance-2: 4-15s, 9 DNAs) — instead of a stack of separate clips. DIALOGUE IS PERFORMED NATIVELY: quoted dialogue in the prompt comes back as synced voices with lip movement, room tone and the SFX named in the AUDIO block — never route scene dialogue to generate_speech or generate_lipsync. Write dialogue in ENGLISH or Latin transliteration of Hebrew ("shalom"), never Hebrew script — Seedance does not speak Hebrew; prefer Gemini Omni Flash 1.1 or Gemini Omni 1 for native Hebrew. COST: resolution is a multiplier. When list_models publishes `video_input_credit` and this call carries videos, charge that rate against nominal input seconds + nominal output seconds; MP4 padding within 0.15s of an integer snaps to that integer and larger fractions round up. Otherwise use the normal output-second rate. PROMPT CONTRACT (Seedance / Elements): Locked Intro only — Total line, then [GLOBAL LOOK] / [CAST] / [LOCATION] / SHOT N. Do NOT write SCENE CONTEXT / OPTICS / ACTION department packs. Every Visual DNA in visual_dna_ids MUST also appear in the prompt as @ExactDNAName (e.g. "@Zohar walks…") — never "Zohar\'s" or "the man on the left" as a substitute. IMPORTANT: different models accept different numbers and durations of inputs — call list_models type="elements" and read elements_max_images / elements_max_videos / elements_max_audio plus min_video_duration / max_video_duration before generating. For text-only → video use generate_video instead. For animating a single still image use generate_video_from_image. Returns the final video URL when complete.',
|
|
1431
1431
|
{
|
|
1432
1432
|
prompt: z.string().describe('Locked Intro prompt (Seedance/Elements): Total line, [GLOBAL LOOK], [CAST] with @ExactDNAName for every visual_dna_ids entry, [LOCATION], then SHOT N. Not SCENE CONTEXT/OPTICS/ACTION packs. Never substitute "the left man" or "Zohar\'s" for @Name. EVERY attached reference must also be tagged by its 1-based array position — `@Image 1`/`@Image 2` (reference_images), `@Video 1` (reference_videos), `@Audio 1` (reference_audio_urls) — and its job stated ("@Image 1 defines the character\'s face and wardrobe", "@Video 1 defines the camera move"). An untagged attachment is ignored by the engine even though it was uploaded and billed.'),
|
|
1433
1433
|
model: z.string().optional().describe('Model identifier. If the user already named a family (Grok / Kling / Veo / Seedance / …), pass THAT family — never default to Seedance because Elements often uses it. Use list_models type="elements" for exact ids and elements_max_* caps. Do NOT omit (omitting = Smart Select).'),
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
# After Effects Motion Graphics
|
|
2
|
-
|
|
3
|
-
Read this before calling `adobe_run_script` for motion graphics. Connection, approval and completion rules are in `references/workflows/adobe.md`; ordinary cuts, titles and fades belong in `adobe_edit_composition` instead of a script.
|
|
4
|
-
|
|
5
|
-
Every snippet below was run in After Effects 26.3 through `adobe_run_script`.
|
|
6
|
-
|
|
7
|
-
## Design before code
|
|
8
|
-
|
|
9
|
-
Plan the piece as beats before writing anything: what the viewer should notice first, second and last, with times.
|
|
10
|
-
|
|
11
|
-
- **Timing.** UI and title moves: 0.3–0.6 s. Logo builds and reveals: 1–2 s. Hold readable text for at least 1.5 s plus 0.3 s per word. Leave 0.5 s of breathing room before the end.
|
|
12
|
-
- **Easing.** Nothing real moves at constant speed. Ease into rests (`KeyframeEase` influence 70–90). Use linear only for continuous motion (spins, scrolling, constant drift).
|
|
13
|
-
- **Overlap and offset.** Stagger related elements by 2–4 frames (0.07–0.13 s) instead of moving them together. Let secondary elements settle after the primary one.
|
|
14
|
-
- **Overshoot.** A pop reads as alive when scale goes 0 → 115 → 100 within about 0.6 s. Use it sparingly: one hero element per beat.
|
|
15
|
-
- **Hierarchy.** One dominant element per frame. Size, contrast and motion should all agree on what matters.
|
|
16
|
-
- **Legibility.** Text needs contrast: dark scrim, stroke or shadow over busy footage. Keep text inside title-safe (about 10% margin: x 192–1728, y 108–972 at 1080p).
|
|
17
|
-
- **Restraint.** Two typefaces maximum, a palette of 2–4 colours, and one idea per shot. Remove before adding.
|
|
18
|
-
|
|
19
|
-
## Build loop
|
|
20
|
-
|
|
21
|
-
1. `adobe_get_timeline` to see what exists.
|
|
22
|
-
2. Write the script in named sections (background, main element, typography, outro). Name every layer.
|
|
23
|
-
3. `adobe_run_script` with a clear `purpose`. Return a small summary (comp name, layer names).
|
|
24
|
-
4. `adobe_capture_frame` at the key beats (mid-reveal, settled, outro) and look at every image.
|
|
25
|
-
5. Fix in a follow-up script that edits the named layers; do not rebuild everything.
|
|
26
|
-
|
|
27
|
-
## ExtendScript rules
|
|
28
|
-
|
|
29
|
-
After Effects scripting is ES3: use `var` and `function`. There is no `let`/`const`, arrow functions, template strings, `Array.prototype.forEach/map/indexOf`, or `Object.keys` - use `for` loops. `JSON` is available. The script body receives `log()` and must `return` its result.
|
|
30
|
-
|
|
31
|
-
Use property **match names** (`'ADBE Transform Group'`, `'ADBE Position'`), not display names; they work in every UI language.
|
|
32
|
-
|
|
33
|
-
## Foundation
|
|
34
|
-
|
|
35
|
-
```js
|
|
36
|
-
var W = 1920, H = 1080, DUR = 6, FPS = 30;
|
|
37
|
-
var comp = app.project.items.addComp('Logo Reveal', W, H, 1, DUR, FPS);
|
|
38
|
-
comp.bgColor = [0.02, 0.02, 0.05];
|
|
39
|
-
comp.motionBlur = true; // also set layer.motionBlur = true on moving layers
|
|
40
|
-
comp.openInViewer();
|
|
41
|
-
|
|
42
|
-
function tr(layer, name) { return layer.property('ADBE Transform Group').property(name); }
|
|
43
|
-
// 'ADBE Anchor Point', 'ADBE Position', 'ADBE Scale', 'ADBE Rotate Z', 'ADBE Opacity'
|
|
44
|
-
|
|
45
|
-
// Keys with ease on every dimension (spatial properties take one ease value).
|
|
46
|
-
function ease(prop, times, values, influence) {
|
|
47
|
-
for (var i = 0; i < times.length; i++) prop.setValueAtTime(times[i], values[i]);
|
|
48
|
-
var spatial = prop.propertyValueType === PropertyValueType.TwoD_SPATIAL || prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL;
|
|
49
|
-
var dims = spatial || !(prop.value instanceof Array) ? 1 : prop.value.length;
|
|
50
|
-
for (var k = 1; k <= prop.numKeys; k++) {
|
|
51
|
-
var e = [];
|
|
52
|
-
for (var d = 0; d < dims; d++) e.push(new KeyframeEase(0, influence || 80));
|
|
53
|
-
prop.setTemporalEaseAtKey(k, e, e);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Backgrounds
|
|
59
|
-
|
|
60
|
-
```js
|
|
61
|
-
var bg = comp.layers.addSolid([0, 0, 0], 'Background', W, H, 1, DUR);
|
|
62
|
-
var ramp = bg.property('ADBE Effect Parade').addProperty('ADBE Ramp'); // Gradient Ramp
|
|
63
|
-
ramp.property('ADBE Ramp-0001').setValue([W / 2, H * 0.4]); // start point
|
|
64
|
-
ramp.property('ADBE Ramp-0002').setValue([0.16, 0.13, 0.42, 1]); // start colour (RGBA)
|
|
65
|
-
ramp.property('ADBE Ramp-0003').setValue([W / 2, H * 1.25]); // end point
|
|
66
|
-
ramp.property('ADBE Ramp-0004').setValue([0.01, 0.01, 0.03, 1]); // end colour
|
|
67
|
-
ramp.property('ADBE Ramp-0005').setValue(2); // 1 linear, 2 radial
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Shape layers
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
var ring = comp.layers.addShape();
|
|
74
|
-
ring.name = 'Ring';
|
|
75
|
-
var group = ring.property('ADBE Root Vectors Group').addProperty('ADBE Vector Group');
|
|
76
|
-
var contents = group.property('ADBE Vectors Group');
|
|
77
|
-
|
|
78
|
-
contents.addProperty('ADBE Vector Shape - Ellipse').property('ADBE Vector Ellipse Size').setValue([380, 380]);
|
|
79
|
-
// Rounded rectangle instead:
|
|
80
|
-
// var rect = contents.addProperty('ADBE Vector Shape - Rect');
|
|
81
|
-
// rect.property('ADBE Vector Rect Size').setValue([900, 500]);
|
|
82
|
-
// rect.property('ADBE Vector Rect Roundness').setValue(48);
|
|
83
|
-
// Custom path:
|
|
84
|
-
// var shape = new Shape(); shape.vertices = [[-200, 0], [0, -120], [200, 0]]; shape.closed = false;
|
|
85
|
-
// contents.addProperty('ADBE Vector Shape - Group').property('ADBE Vector Shape').setValue(shape);
|
|
86
|
-
|
|
87
|
-
var stroke = contents.addProperty('ADBE Vector Graphic - Stroke');
|
|
88
|
-
stroke.property('ADBE Vector Stroke Color').setValue([0.42, 0.55, 1, 1]);
|
|
89
|
-
stroke.property('ADBE Vector Stroke Width').setValue(16);
|
|
90
|
-
stroke.property('ADBE Vector Stroke Line Cap').setValue(2); // round caps
|
|
91
|
-
// Solid fill: contents.addProperty('ADBE Vector Graphic - Fill').property('ADBE Vector Fill Color').setValue([1, 1, 1, 1]);
|
|
92
|
-
// Gradient fill: contents.addProperty('ADBE Vector Graphic - G-Fill') with 'ADBE Vector Grad Start Pt' / 'ADBE Vector Grad End Pt'
|
|
93
|
-
|
|
94
|
-
// Draw-on with Trim Paths (add it after the shape and stroke).
|
|
95
|
-
var trim = contents.addProperty('ADBE Vector Filter - Trim');
|
|
96
|
-
ease(trim.property('ADBE Vector Trim End'), [0.2, 1.5], [0, 100], 85);
|
|
97
|
-
// Endless loader: trim.property('ADBE Vector Trim End').setValue(25); trim.property('ADBE Vector Trim Offset').expression = 'time * 180';
|
|
98
|
-
|
|
99
|
-
tr(ring, 'ADBE Position').setValue([W / 2, 420]); // shape contents are centred on the layer position
|
|
100
|
-
ring.motionBlur = true;
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Overshoot pop on a second shape: `ease(tr(core, 'ADBE Scale'), [1.2, 1.55, 1.8], [[0, 0], [118, 118], [100, 100]], 70);`
|
|
104
|
-
|
|
105
|
-
## Typography
|
|
106
|
-
|
|
107
|
-
```js
|
|
108
|
-
var word = comp.layers.addText('KOLBO'); // use '\r' for line breaks
|
|
109
|
-
var textProp = word.property('ADBE Text Properties').property('ADBE Text Document');
|
|
110
|
-
var doc = textProp.value;
|
|
111
|
-
doc.resetCharStyle();
|
|
112
|
-
doc.font = 'Arial-BoldMT'; // PostScript name
|
|
113
|
-
doc.fontSize = 190;
|
|
114
|
-
doc.tracking = 180;
|
|
115
|
-
doc.autoLeading = false; doc.leading = 110; // multi-line spacing
|
|
116
|
-
doc.fontCapsOption = FontCapsOption.FONT_ALL_CAPS; // doc.allCaps is read-only
|
|
117
|
-
doc.applyFill = true; doc.fillColor = [1, 1, 1];
|
|
118
|
-
// Outline for busy backgrounds: doc.applyStroke = true; doc.strokeColor = [0, 0, 0]; doc.strokeWidth = 5; doc.strokeOverFill = false;
|
|
119
|
-
doc.justification = ParagraphJustification.CENTER_JUSTIFY;
|
|
120
|
-
textProp.setValue(doc);
|
|
121
|
-
|
|
122
|
-
// Centre the anchor on the visible text so Position means "centre of the text".
|
|
123
|
-
var box = word.sourceRectAtTime(0, false);
|
|
124
|
-
tr(word, 'ADBE Anchor Point').setValue([box.left + box.width / 2, box.top + box.height / 2]);
|
|
125
|
-
tr(word, 'ADBE Position').setValue([W / 2, 760]);
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Per-character reveal with a text animator (characters rise and fade in left to right):
|
|
129
|
-
|
|
130
|
-
```js
|
|
131
|
-
var animator = word.property('ADBE Text Properties').property('ADBE Text Animators').addProperty('ADBE Text Animator');
|
|
132
|
-
var animProps = animator.property('ADBE Text Animator Properties');
|
|
133
|
-
animProps.addProperty('ADBE Text Position 3D').setValue([0, 140, 0]); // offset while inside the range
|
|
134
|
-
animProps.addProperty('ADBE Text Opacity').setValue(0);
|
|
135
|
-
// Pop instead of rise: animProps.addProperty('ADBE Text Scale 3D').setValue([0, 0, 100]);
|
|
136
|
-
var selector = animator.property('ADBE Text Selectors').addProperty('ADBE Text Selector');
|
|
137
|
-
// Softer falloff: selector.property('ADBE Text Range Advanced').property('ADBE Text Range Shape').setValue(2); // ramp up
|
|
138
|
-
ease(selector.property('ADBE Text Percent Offset'), [1.6, 2.7], [0, 100], 75);
|
|
139
|
-
word.motionBlur = true;
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## Effects
|
|
143
|
-
|
|
144
|
-
```js
|
|
145
|
-
var fx = layer.property('ADBE Effect Parade');
|
|
146
|
-
var glow = fx.addProperty('ADBE Glo2'); // Glow
|
|
147
|
-
glow.property('ADBE Glo2-0003').setValue(70); // radius
|
|
148
|
-
glow.property('ADBE Glo2-0004').setValue(1.6); // intensity
|
|
149
|
-
fx.addProperty('ADBE Gaussian Blur 2').property('ADBE Gaussian Blur 2-0001').setValue(8); // blurriness
|
|
150
|
-
fx.addProperty('ADBE Drop Shadow').property('ADBE Drop Shadow-0005').setValue(40); // softness
|
|
151
|
-
fx.addProperty('ADBE Fill').property('ADBE Fill-0002').setValue([1, 0.4, 0.2, 1]); // colour
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Structure, mattes and 3D
|
|
155
|
-
|
|
156
|
-
```js
|
|
157
|
-
var ctrl = comp.layers.addNull(); ctrl.name = 'Controller';
|
|
158
|
-
card.parent = ctrl; // move everything together
|
|
159
|
-
|
|
160
|
-
tr(ctrl, 'ADBE Position').expression = 'wiggle(2, 12)'; // organic drift
|
|
161
|
-
tr(card, 'ADBE Rotate Z').expression = 'loopOut("pingpong")'; // after at least two keys
|
|
162
|
-
tr(ring, 'ADBE Rotate Z').expression = 'time * 24'; // constant spin
|
|
163
|
-
|
|
164
|
-
var pre = comp.layers.precompose([card.index], 'Card Precomp', true); // returns the new CompItem
|
|
165
|
-
|
|
166
|
-
fill.moveAfter(matte);
|
|
167
|
-
fill.setTrackMatte(matte, TrackMatteType.ALPHA); // reveal fill through the matte's alpha
|
|
168
|
-
|
|
169
|
-
floor.threeDLayer = true;
|
|
170
|
-
var cam = comp.layers.addCamera('Camera', [W / 2, H / 2]);
|
|
171
|
-
ease(tr(cam, 'ADBE Position'), [0, 5], [[W / 2, H / 2, -2400], [W / 2, H / 2, -1800]], 60); // slow push-in
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## Outro
|
|
175
|
-
|
|
176
|
-
Fade the group together over the last 0.5–0.7 s, holding the current value first so earlier animation is kept:
|
|
177
|
-
|
|
178
|
-
```js
|
|
179
|
-
var layers = [ring, core, word, tag];
|
|
180
|
-
for (var i = 0; i < layers.length; i++) {
|
|
181
|
-
var op = tr(layers[i], 'ADBE Opacity');
|
|
182
|
-
op.setValueAtTime(DUR - 0.7, op.valueAtTime(DUR - 0.7, false));
|
|
183
|
-
op.setValueAtTime(DUR, 0);
|
|
184
|
-
}
|
|
185
|
-
return { comp: comp.name, layers: comp.numLayers };
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
## Checklist before reporting
|
|
189
|
-
|
|
190
|
-
- Captured frames at mid-reveal, settled state and outro, and looked at them.
|
|
191
|
-
- Text is legible over its background and inside title-safe.
|
|
192
|
-
- Every moving element eases; stagger and overshoot are deliberate, not everywhere.
|
|
193
|
-
- Layers are named and the script returned a summary the user can read.
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# DaVinci Resolve Workflow
|
|
2
|
-
|
|
3
|
-
Use this when the user wants Kolbo media edited, cut, titled, graded or rendered in DaVinci Resolve. There are two ways to reach Resolve; pick by what is connected.
|
|
4
|
-
|
|
5
|
-
| Path | Works from | Use it for |
|
|
6
|
-
|---|---|---|
|
|
7
|
-
| **Kolbo Resolve plugin** (`resolve_*` tools, this server) | Any agent, including ChatGPT and claude.ai | Reading the project, importing Kolbo media, building timeline edits, titles, frame checks - every change approved by the editor |
|
|
8
|
-
| **Blackmagic's DaVinci Resolve MCP** (their own server) | Local agents only (Claude Desktop, Claude Code, Codex) | Deep scripting, colour, LUTs/DCTLs, rendering |
|
|
9
|
-
|
|
10
|
-
Both need **DaVinci Resolve Studio**; the free edition has no plugins and no external scripting. If `resolve_list_sessions` returns a session, prefer the Kolbo plugin.
|
|
11
|
-
|
|
12
|
-
## Kolbo Resolve plugin
|
|
13
|
-
|
|
14
|
-
Everything in this section was run end to end through Kolbo MCP against DaVinci Resolve Studio 21.1.
|
|
15
|
-
|
|
16
|
-
### Connect and target safely
|
|
17
|
-
|
|
18
|
-
1. Call `resolve_list_sessions` before the first Resolve action.
|
|
19
|
-
2. If no session is listed, ask the user to open **Workspace → Workflow Integrations → Kolbo AI** in Resolve Studio and sign in with the same Kolbo account as this connector. **AI agents** in the plugin header connects automatically; if its dot is not green, ask them to click it.
|
|
20
|
-
3. One session: `session_id` may be omitted. Several: show each and ask. Keep the chosen `session_id` on every later call; re-list after Resolve or the plugin restarts.
|
|
21
|
-
|
|
22
|
-
Every tool except `resolve_list_sessions` and `resolve_get_command_status` returns a command record. Poll `resolve_get_command_status` until `succeeded`, `failed`, `denied` or `canceled`. Reads run without approval; everything else waits for **Allow once / Allow for this session / Deny** in the plugin window. `awaiting_approval` is not a polling state: tell the user to approve in the Kolbo AI window (it may be behind Resolve), then check again. `denied` is final.
|
|
23
|
-
|
|
24
|
-
### Tools
|
|
25
|
-
|
|
26
|
-
| Goal | Tool |
|
|
27
|
-
|---|---|
|
|
28
|
-
| Project name, timelines, frame rate, resolution, playhead | `resolve_get_project` |
|
|
29
|
-
| Clips on every track (position, start/end seconds), markers | `resolve_get_timeline` |
|
|
30
|
-
| Kolbo media into the Media Pool only | `resolve_import_media` |
|
|
31
|
-
| Build or change an edit | `resolve_edit_timeline` |
|
|
32
|
-
| Anything else in Resolve's scripting API | `resolve_run_script` |
|
|
33
|
-
| See the result | `resolve_capture_frame` → look at the returned `url` |
|
|
34
|
-
|
|
35
|
-
### Timeline edits (`resolve_edit_timeline`)
|
|
36
|
-
|
|
37
|
-
- Up to 100 operations run in order and stop at the first failure; earlier operations stay applied. Fix the failing one and continue - do not replay the batch.
|
|
38
|
-
- Start new work with `timeline.create` so the user's existing timelines stay untouched. It uses the project's frame rate and resolution.
|
|
39
|
-
- Times are seconds from the timeline start. `clip.append`: `record_seconds` = where it lands (default: end of that track), `trim_start_seconds` = seconds skipped at the head of the source, `duration_seconds` = length on the timeline (stills default to 5 s). media_type "video" keeps a clip's audio off the timeline; audio files always go to audio tracks. Missing tracks are added.
|
|
40
|
-
- Clips are addressed by track plus position (1 = leftmost media clip on that track; transitions do not count) or exact clip name. Clip names are file names, and a file imported again gets a short prefix, so prefer positions. Positions change after inserts and deletes - re-read with `resolve_get_timeline` when unsure.
|
|
41
|
-
- `clip.transition` needs handles: trim the head of the next shot (`trim_start_seconds` ≥ half the transition) or the transition will be refused.
|
|
42
|
-
- `audio.fade` is for clips on audio tracks. `title.add` builds the title inside that clip's Fusion comp (`position` [0.5, 0.5] = centre, y grows upward) with a fade in and out; keep it inside title-safe (x and y between 0.1 and 0.9).
|
|
43
|
-
- `clip.delete` is destructive; only delete what the user asked for.
|
|
44
|
-
- The Kolbo AI window must stay open while you work; it can sit behind Resolve.
|
|
45
|
-
|
|
46
|
-
### Scripts (`resolve_run_script`)
|
|
47
|
-
|
|
48
|
-
- `code` is an **async JavaScript function body** with `resolve`, `project`, `timeline` and `log(...)` in scope. Every Resolve call returns a promise - `await` each one - and `return` a JSON-serialisable result.
|
|
49
|
-
- The editor reads the exact code before approving. Give a plain `purpose`. Never touch files, the network or other projects unless the user asked for exactly that.
|
|
50
|
-
|
|
51
|
-
## Blackmagic's DaVinci Resolve MCP
|
|
52
|
-
|
|
53
|
-
Verified against DaVinci Resolve Studio 21.1.0.17.
|
|
54
|
-
|
|
55
|
-
### Requirements - check before promising anything
|
|
56
|
-
|
|
57
|
-
- **DaVinci Resolve Studio 21.1 or later.** The free edition has no MCP server and no external scripting.
|
|
58
|
-
- A **local** agent: Claude Desktop, Claude Code or Codex on the same computer as Resolve. Browser ChatGPT and claude.ai cannot reach this server; use the Kolbo Resolve plugin from there.
|
|
59
|
-
- Connect Resolve's server from **File → Setup AI Assistants** in Resolve, and set **Preferences → System → General → External scripting using** to **Local**.
|
|
60
|
-
- Resolve must be running; the server's `launch_resolve` tool can start it.
|
|
61
|
-
|
|
62
|
-
If neither the Kolbo plugin session nor Blackmagic's tools are available, say so and give the setup steps for the path that fits the user. Do not try to control Resolve any other way.
|
|
63
|
-
|
|
64
|
-
### Blackmagic's tools (not Kolbo's)
|
|
65
|
-
|
|
66
|
-
| Tool | Use |
|
|
67
|
-
|---|---|
|
|
68
|
-
| `get_resolve_status`, `launch_resolve` | Is Resolve running / start it |
|
|
69
|
-
| `get_whats_new` (`since` is required, e.g. `"21.0"`) | Features newer than your training |
|
|
70
|
-
| `search_scripting_api`, `get_scripting_api`, `get_scripting_docs` | Look up exact API signatures before writing a script |
|
|
71
|
-
| `run_script` | Sandboxed Python: Resolve API only, no files, network or processes |
|
|
72
|
-
| `run_script_unsafe` | Python with full system access - required for importing files or downloading media |
|
|
73
|
-
| `generate_lut`, `update_dctl`, `list_luts`, `list_dctls` | Colour transforms |
|
|
74
|
-
|
|
75
|
-
Scripts get `resolve` and the current `project` pre-injected and return data by assigning `result`.
|
|
76
|
-
|
|
77
|
-
### Workflow
|
|
78
|
-
|
|
79
|
-
1. **Generate or find media with Kolbo** (`generate_video`, `generate_music`, `list_media`, …) and wait for success.
|
|
80
|
-
2. **Get the files onto disk.** In Claude Code or Codex, download the Kolbo URLs with the shell. In Claude Desktop, download inside `run_script_unsafe` with `urllib.request`. Only download Kolbo-hosted URLs.
|
|
81
|
-
3. **Protect the user's work.** Call `pm.SaveProject()` first. For anything experimental, build in a new project (`pm.CreateProject(name)`) and reload the original project at the end. Projects opened in 21.1 cannot be opened in 20.x, so never convert a user's project as a side effect.
|
|
82
|
-
4. **Import, cut and finish** with `run_script_unsafe` (see recipe).
|
|
83
|
-
5. **Verify visually.** Set the playhead and call `project.ExportCurrentFrameAsStill(path)` at representative times, then look at the stills before reporting.
|
|
84
|
-
6. Optionally render (`AddRenderJob` / `StartRendering`) and upload the result back to Kolbo with `upload_media` so it lands in the user's library.
|
|
85
|
-
|
|
86
|
-
### Verified gotchas
|
|
87
|
-
|
|
88
|
-
- **`MediaPool.ImportMedia` needs plain path strings.** The dict form in the 21.1 stubs (`[{"FilePath": ...}]`) returned `None`. On Windows, backslash paths worked.
|
|
89
|
-
- **File import fails in `run_script`**; use `run_script_unsafe` for anything that touches files.
|
|
90
|
-
- **`Timeline.InsertFusionTitleIntoTimeline("Text+")` is a ripple insert** into every unlocked track: it splits the clips and music under the playhead. With those tracks locked it inserts nothing. For a title over a shot, build it inside that clip's Fusion comp (recipe below).
|
|
91
|
-
- `AppendToTimeline` `startFrame` / `endFrame` are **source frames** at the clip's own frame rate (`GetClipProperty("FPS")`). `recordFrame` is a timeline frame; timelines start at `timeline.GetStartFrame()` (86400 = 01:00:00:00 at 24 fps).
|
|
92
|
-
- New projects default to 24 fps and UHD output.
|
|
93
|
-
|
|
94
|
-
### Recipe: cut, transition, music fade, title
|
|
95
|
-
|
|
96
|
-
```python
|
|
97
|
-
pm = resolve.GetProjectManager()
|
|
98
|
-
original = project.GetName()
|
|
99
|
-
pm.SaveProject()
|
|
100
|
-
proj = pm.CreateProject("Kolbo Edit") or pm.LoadProject("Kolbo Edit")
|
|
101
|
-
mp = proj.GetMediaPool()
|
|
102
|
-
|
|
103
|
-
paths = [r"C:\media\shot1.mp4", r"C:\media\shot2.mp4", r"C:\media\music.mp3"]
|
|
104
|
-
items = {item.GetName(): item for item in mp.ImportMedia(paths)}
|
|
105
|
-
shot1, shot2, music = items["shot1.mp4"], items["shot2.mp4"], items["music.mp3"]
|
|
106
|
-
|
|
107
|
-
tl = mp.CreateEmptyTimeline("Kolbo Promo")
|
|
108
|
-
proj.SetCurrentTimeline(tl)
|
|
109
|
-
fps = float(proj.GetSetting("timelineFrameRate"))
|
|
110
|
-
start = tl.GetStartFrame()
|
|
111
|
-
|
|
112
|
-
def src(item, a, b):
|
|
113
|
-
clip_fps = float(item.GetClipProperty("FPS") or fps)
|
|
114
|
-
return int(a * clip_fps), int(b * clip_fps) - 1
|
|
115
|
-
|
|
116
|
-
s1, e1 = src(shot1, 0.5, 6.5)
|
|
117
|
-
s2, e2 = src(shot2, 1.0, 7.0)
|
|
118
|
-
clips = mp.AppendToTimeline([
|
|
119
|
-
{"mediaPoolItem": shot1, "startFrame": s1, "endFrame": e1, "mediaType": 1, "trackIndex": 1, "recordFrame": start},
|
|
120
|
-
{"mediaPoolItem": shot2, "startFrame": s2, "endFrame": e2, "mediaType": 1, "trackIndex": 1, "recordFrame": start + int(6 * fps)},
|
|
121
|
-
])
|
|
122
|
-
audio = mp.AppendToTimeline([{"mediaPoolItem": music, "startFrame": 0, "endFrame": int(12 * fps) - 1,
|
|
123
|
-
"mediaType": 2, "trackIndex": 1, "recordFrame": start}])
|
|
124
|
-
|
|
125
|
-
clips[0].AddTransition({"type": "Cross Dissolve", "category": "simple", "position": "end",
|
|
126
|
-
"alignment": "center", "duration": int(fps)})
|
|
127
|
-
audio[0].SetFades({"FadeIn": int(0.5 * fps), "FadeOut": int(2 * fps)})
|
|
128
|
-
|
|
129
|
-
# Title inside shot 1's Fusion comp, fading in and out (Blend keyframes are clip frames).
|
|
130
|
-
comp = clips[0].AddFusionComp()
|
|
131
|
-
media_in, media_out = comp.FindTool("MediaIn1"), comp.FindTool("MediaOut1")
|
|
132
|
-
text = comp.AddTool("TextPlus", -32768, -32768)
|
|
133
|
-
text.SetInput("StyledText", "KOLBO x DAVINCI RESOLVE")
|
|
134
|
-
text.SetInput("Size", 0.085)
|
|
135
|
-
text.SetInput("Font", "Arial")
|
|
136
|
-
text.SetInput("Style", "Bold")
|
|
137
|
-
merge = comp.AddTool("Merge", -32768, -32768)
|
|
138
|
-
merge.ConnectInput("Background", media_in)
|
|
139
|
-
merge.ConnectInput("Foreground", text)
|
|
140
|
-
media_out.ConnectInput("Input", merge)
|
|
141
|
-
merge.AddModifier("Blend", "BezierSpline")
|
|
142
|
-
for value, frame in ((0.0, 6), (1.0, 24), (1.0, 96), (0.0, 120)):
|
|
143
|
-
merge.SetInput("Blend", value, frame)
|
|
144
|
-
|
|
145
|
-
pm.SaveProject()
|
|
146
|
-
result = {"project": proj.GetName(), "timeline": tl.GetName(), "original": original}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Then verify, and restore the user's project when you are done:
|
|
150
|
-
|
|
151
|
-
```python
|
|
152
|
-
tl = project.GetCurrentTimeline()
|
|
153
|
-
tl.SetCurrentTimecode("01:00:02:00")
|
|
154
|
-
ok = project.ExportCurrentFrameAsStill(r"C:\media\check-2s.png")
|
|
155
|
-
resolve.GetProjectManager().SaveProject()
|
|
156
|
-
resolve.GetProjectManager().LoadProject("<original project name>")
|
|
157
|
-
result = {"still": ok}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Completion proof
|
|
161
|
-
|
|
162
|
-
- Look at exported stills at the title, the transition and the end before reporting.
|
|
163
|
-
- Report which project and timeline you built, that the original project was saved and restored, and where any render landed.
|