davinci-resolve-mcp 2.68.1 → 2.69.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/CHANGELOG.md +213 -0
- package/README.md +46 -3
- package/docs/SKILL.md +181 -1
- package/docs/install.md +27 -1
- package/install.py +26 -1
- package/package.json +1 -1
- package/resolve-advanced/LICENSE +21 -0
- package/resolve-advanced/package.json +2 -1
- package/resolve-advanced/vendor/conform-qc/package.json +1 -0
- package/resolve-advanced/vendor/drp-format/package.json +1 -0
- package/resolve-advanced/vendor/drt-format/package.json +1 -0
- package/scripts/bridge_differential.py +22 -4
- package/scripts/doctor.py +129 -3
- package/scripts/install_resolve_bridge.py +13 -3
- package/src/granular/common.py +1 -1
- package/src/server.py +639 -18
- package/src/utils/beat_detection.py +242 -0
- package/src/utils/bridge_differential.py +27 -1
- package/src/utils/broll_placement.py +201 -0
- package/src/utils/conform_lint.py +437 -0
- package/src/utils/edit_engine.py +633 -1
- package/src/utils/edit_handles.py +206 -0
- package/src/utils/edit_report.py +360 -0
- package/src/utils/first_impression.py +212 -0
- package/src/utils/prebalance.py +471 -0
- package/src/utils/project_journal.py +360 -0
- package/src/utils/reference_match.py +203 -0
- package/src/utils/rhythm_audit.py +252 -0
- package/src/utils/rule_of_six.py +217 -0
- package/src/utils/setup_sheet.py +121 -0
- package/src/utils/shot_assembly.py +259 -0
- package/src/utils/silence_ripple.py +89 -2
- package/src/utils/sound_density.py +253 -0
- package/src/utils/split_edits.py +180 -0
- package/src/utils/take_ranking.py +206 -0
- package/src/utils/transcript_edit.py +101 -5
- package/src/utils/turnover.py +187 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,219 @@
|
|
|
2
2
|
|
|
3
3
|
Release history for the DaVinci Resolve MCP Server. The latest release is summarized in the root README; older entries live here to keep the README focused.
|
|
4
4
|
|
|
5
|
+
## What's New in v2.69.0
|
|
6
|
+
|
|
7
|
+
The free edition is documented as reachable, silence ripple stops clipping
|
|
8
|
+
speech at the cut, and the editorial surface grows a set of review-first
|
|
9
|
+
planners: dead-space markers, craft-aware cut points, conform QC, colour
|
|
10
|
+
pre-balance, beat detection, turnover manifests, and a project journal.
|
|
11
|
+
|
|
12
|
+
Two themes run through the additions. **Nothing new executes** — every planner
|
|
13
|
+
proposes and reports, and the existing plan → confirm → execute path is
|
|
14
|
+
unchanged. And **unverified is never reported as clean**: an item that could not
|
|
15
|
+
be analysed, a check that could not run, a handle that could not be measured and
|
|
16
|
+
a take with no transcript are each reported as such rather than folded into a
|
|
17
|
+
passing result.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **`plan_silence_ripple` guard bands are now 2 pre-head / 4 post-tail frames**
|
|
22
|
+
(previously 0 and 1 — effectively none). This changes default output for any
|
|
23
|
+
caller that does not pass explicit handles.
|
|
24
|
+
|
|
25
|
+
The old defaults cut exactly on `silencedetect`'s gate crossings, which are not
|
|
26
|
+
word boundaries. `s` is marked when amplitude falls below the gate, but a
|
|
27
|
+
word's decay and the room reverb after it stay audible below it, so cutting
|
|
28
|
+
from `s` clipped the release. `e` is marked when amplitude rises back above the
|
|
29
|
+
gate, and a soft attack (s, f, th, or any unstressed syllable) crosses later
|
|
30
|
+
than the word actually begins, so `e` sat *inside* the next word and cutting up
|
|
31
|
+
to it ate the onset.
|
|
32
|
+
|
|
33
|
+
The onset guard is the larger of the two because that is the asymmetry users
|
|
34
|
+
hear: reviewers of the first public tutorial for this project independently
|
|
35
|
+
reported that "the first split seconds of your clips are trimmed so the audio
|
|
36
|
+
is a bit cut off". At 24 fps the new guards are 83 ms and 167 ms; at 30 fps,
|
|
37
|
+
67 ms and 133 ms — both inside the range dialogue editors use by hand.
|
|
38
|
+
|
|
39
|
+
Pass `pre_head_frames` / `post_tail_frames` explicitly to restore the previous
|
|
40
|
+
behaviour.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **The docs told free-edition users the door was closed.** v2.68.0 shipped the
|
|
45
|
+
in-app bridge, which reaches the free edition through the ungated
|
|
46
|
+
**Workspace > Scripts** menu, but README's Requirements section still said "the
|
|
47
|
+
free edition does not support external scripting" 195 lines below the section
|
|
48
|
+
documenting the bridge, and `docs/install.md` said the same with no mention of
|
|
49
|
+
the bridge at all. The claim is true about *external* scripting and false as
|
|
50
|
+
users read it — the first large public tutorial for this project pinned a
|
|
51
|
+
correction telling viewers the method "REQUIRES the Studio Version".
|
|
52
|
+
|
|
53
|
+
README, `docs/install.md`, `install.py` and the MCP server's own `instructions`
|
|
54
|
+
now state the limit and the remedy together. `install.py` also grew the branch
|
|
55
|
+
it was missing: Resolve running, healthy interpreter, no connection is the
|
|
56
|
+
free-edition signature, and it used to print "Not running — start Resolve".
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
**Editorial**
|
|
61
|
+
|
|
62
|
+
- `edit_engine.plan_dead_space_markers` — **the review gate.** Finds dead space
|
|
63
|
+
with the same calibrated detection as `plan_silence_ripple`, but proposes
|
|
64
|
+
Resolve markers instead of assembling a variant, so an editor can see every
|
|
65
|
+
gap before agreeing to lose it. Red = confident; yellow = the gate only just
|
|
66
|
+
cleared its separation floor. Items that could not be analysed are reported
|
|
67
|
+
and are explicitly **not** certified clean.
|
|
68
|
+
- `tightness` (`generous` default | `balanced` | `tight`) on the dead-space
|
|
69
|
+
planner. The default is deliberately the loosest: a first assembly is meant to
|
|
70
|
+
run long, because trimming is fast and visible while recovering material the
|
|
71
|
+
machine discarded is slow and invisible. Guard bands are floored regardless of
|
|
72
|
+
preset — `tight` removes more *gaps*, never more *speech*.
|
|
73
|
+
- Syntactic pause classification in `plan_transcript_tighten`. A pause after a
|
|
74
|
+
full stop must be markedly longer before it is proposed for removal than the
|
|
75
|
+
acoustically identical pause mid-phrase; the first is usually breathing room
|
|
76
|
+
and the second usually is not. Unpunctuated transcripts are flagged low
|
|
77
|
+
confidence rather than treated as all-removable.
|
|
78
|
+
- `edit_engine.rank_takes` — ranks takes on **measurable fluency** (fillers,
|
|
79
|
+
restarts, script coverage) and states in every response that fluency is not
|
|
80
|
+
quality. It never names a best take.
|
|
81
|
+
- `edit_engine.plan_beat_cuts` — beat, bar and phrase cut points for
|
|
82
|
+
music-driven cutting, frame-snapped. Requires the optional `librosa` extra and
|
|
83
|
+
honest-refuses without it.
|
|
84
|
+
- `edit_engine.plan_string_out` / `propose_structure` — assembly for footage
|
|
85
|
+
with no speech, from shots and motion rather than silence; and a no-script
|
|
86
|
+
mode that proposes a structure and requires approval.
|
|
87
|
+
- `edit_engine.plan_broll` — places B-roll against A-roll beats. Placement only:
|
|
88
|
+
relevance is the caller's and is never re-scored, protected beats are never
|
|
89
|
+
covered, and an explicit beat choice is honoured or refused, never moved.
|
|
90
|
+
- `edit_engine.rule_of_six_audit` and `split_edit_audit` — audits against the
|
|
91
|
+
classical weighted cut criteria, and J/L-cut classification. The audit is
|
|
92
|
+
explicit that the two heaviest criteria are not measurable and reports its own
|
|
93
|
+
coverage; there is deliberately no composite score.
|
|
94
|
+
|
|
95
|
+
**Finishing and colour**
|
|
96
|
+
|
|
97
|
+
- `edit_engine.conform_lint` — the online editor's pre-turnover checklist:
|
|
98
|
+
frame-rate mismatch, offline media, duplicate source timecode, buried layers,
|
|
99
|
+
fragile effects, missing reel names, duplicate usage. Checks that could not run
|
|
100
|
+
are listed in `not_checked`.
|
|
101
|
+
- `edit_engine.plan_prebalance` and `plan_reference_match` — neutral technical
|
|
102
|
+
pre-balance, and matching to a graded reference still. Curves, vignettes,
|
|
103
|
+
saturation, qualifiers and windows are refused **in code**; midtones are left
|
|
104
|
+
warm by design. Reference matching is end-points-only and says so.
|
|
105
|
+
- `edit_engine.plan_turnover` — sound / VFX / colour turnover manifests with
|
|
106
|
+
per-destination handle floors and a timecode-burned picture reference required
|
|
107
|
+
in all three. Manifests, not exports.
|
|
108
|
+
- Plans now carry a `handle_report`: keep ranges that leave too little source
|
|
109
|
+
media at a join for a dissolve, a slip or an audio crossfade.
|
|
110
|
+
|
|
111
|
+
**Reporting**
|
|
112
|
+
|
|
113
|
+
- `edit_engine.plan_report` and `include_report` on every audit — Markdown
|
|
114
|
+
renderings covering what would change (in timecode, with a reason per cut),
|
|
115
|
+
what was deliberately left alone, what could not be verified, and what needs a
|
|
116
|
+
human. Off by default for token cost; every audit advertises it.
|
|
117
|
+
- `journal` — ingest log, append-only known issues, session-prep summary with
|
|
118
|
+
value figures, technical handoff document, status summary, and a picture-lock
|
|
119
|
+
fingerprint with drift detection.
|
|
120
|
+
- `first_impression` — timestamped capture of a first viewing, sealed once
|
|
121
|
+
locked. There is deliberately no unlock.
|
|
122
|
+
|
|
123
|
+
**Documentation**
|
|
124
|
+
|
|
125
|
+
- **Optional extras are now documented up front** — README and `docs/install.md`
|
|
126
|
+
list what each extra unlocks and under which licence, and `scripts/doctor.py`
|
|
127
|
+
reports which are present. Four of the features added in this release need
|
|
128
|
+
`numpy` or `librosa`; they refuse honestly with the install line, but a user
|
|
129
|
+
reading the README previously had no way to know before hitting the refusal.
|
|
130
|
+
"Setup too hard" was one of the loudest complaints this release answers, and
|
|
131
|
+
shipping features behind an undocumented `pip install` is the same failure.
|
|
132
|
+
|
|
133
|
+
**Guards**
|
|
134
|
+
|
|
135
|
+
- `tests/test_free_edition_docs_drift.py` — a guard that does not forbid stating
|
|
136
|
+
the free-edition limitation, but requires that any file stating it also names
|
|
137
|
+
the bridge. Broad enough to catch a new phrasing rather than only the sentences
|
|
138
|
+
fixed here, and it asserts the remedy exists (the README anchor and the
|
|
139
|
+
installer script the docs promise).
|
|
140
|
+
- `tests/test_attribution_drift.py` — keeps named third parties out of the
|
|
141
|
+
committed tree entirely. Stores SHA-256 digests rather than the names it
|
|
142
|
+
forbids, so the guard is not itself the one file containing them.
|
|
143
|
+
- `resolve-advanced` now carries an MIT `LICENSE` in its published tarball, and
|
|
144
|
+
the three vendored workspaces declare `"license": "MIT"`.
|
|
145
|
+
|
|
146
|
+
## What's New in v2.68.2
|
|
147
|
+
|
|
148
|
+
Bug fixes. The server no longer opens a second DaVinci Resolve, and a failed
|
|
149
|
+
connection now tells the caller what is actually wrong.
|
|
150
|
+
|
|
151
|
+
### Fixed
|
|
152
|
+
|
|
153
|
+
- **The server launched Resolve when one was already running — usually the wrong
|
|
154
|
+
one.** The free edition refuses external scripting by design, so on a machine
|
|
155
|
+
where only it is running `scriptapp("Resolve")` always returns None.
|
|
156
|
+
`get_resolve()` read that as *"Resolve is not running"* and ran `open` on the
|
|
157
|
+
application; with both editions installed that started **Studio**, a second and
|
|
158
|
+
different application, on every tool call.
|
|
159
|
+
|
|
160
|
+
`resolve_is_running()` now answers the question that was being assumed. It
|
|
161
|
+
returns None when it cannot tell, deliberately — "cannot tell" must never decay
|
|
162
|
+
into "nothing is running", because that is the answer that leads to launching
|
|
163
|
+
something. A genuinely absent Resolve is still launched, as documented, and the
|
|
164
|
+
macOS candidate list now contains **both** editions rather than only the
|
|
165
|
+
installer path.
|
|
166
|
+
- **The error a caller received described something that had not happened.**
|
|
167
|
+
Eleven sites asserted that Resolve was not running, that starting it had been
|
|
168
|
+
tried and failed, and that the reader should check their Studio install. After
|
|
169
|
+
the fix above none of that was true, and the accurate guidance was only reaching
|
|
170
|
+
the log. `_not_connected_error()` derives the message from the situation and
|
|
171
|
+
names the applicable remedy — external scripting on Studio, or the in-app bridge
|
|
172
|
+
on the free edition, including the framework-Python prerequisite. Three codes:
|
|
173
|
+
`SCRIPTING_UNAVAILABLE`, `BRIDGE_UNAVAILABLE`, `RESOLVE_NOT_RUNNING`.
|
|
174
|
+
- **Those two are marked `retryable: false`.** The `not_connected` category
|
|
175
|
+
defaults to retryable because auto-launch may succeed next time; neither of
|
|
176
|
+
these can — one needs a preference changed, the other a script started inside
|
|
177
|
+
Resolve — and reporting them as retryable sends an agent into a loop it cannot
|
|
178
|
+
win.
|
|
179
|
+
- **The offline test suite opened Resolve, and connected to whatever was running.**
|
|
180
|
+
A stub-based audio test reached for `AUDIO_SYNC_*`, which are attributes on the
|
|
181
|
+
*live* object, so it called `get_resolve()`, found nothing, and started Resolve;
|
|
182
|
+
when Resolve *was* open it connected instead, making the test's result depend on
|
|
183
|
+
the state of the machine. `tests/conftest.py` closes both suite-wide and names
|
|
184
|
+
any launch attempt in the terminal summary.
|
|
185
|
+
- **`src/server.py` reported the wrong tool count to every agent.** Its module
|
|
186
|
+
docstring said "34 compound tools" while the agent-facing workflow prompt and
|
|
187
|
+
the startup log line said 32. The drift guard only required the correct number
|
|
188
|
+
to appear *somewhere* in the file, so the wrong one shipped. It now rejects any
|
|
189
|
+
other count in front of that phrase, and counts decorators from the parsed
|
|
190
|
+
syntax tree rather than by matching text — a docstring mentioning
|
|
191
|
+
`@mcp.tool()` had been counted as a 35th tool.
|
|
192
|
+
- **The bridge harness graded the wrong clip and reported a known trap as a
|
|
193
|
+
finding.** It took the first video item, which is often a generator or title
|
|
194
|
+
that has no MediaPoolItem and answers None to every node query, so the grading
|
|
195
|
+
surface read as unreachable; it now takes the first gradeable item. And it
|
|
196
|
+
passed the codec *description* `"H.264"` to `SetCurrentRenderFormatAndCodec`,
|
|
197
|
+
which only accepts the id `"H264"`, making that observation permanently false
|
|
198
|
+
for a documented reason.
|
|
199
|
+
|
|
200
|
+
### Changed
|
|
201
|
+
|
|
202
|
+
- `scripts/install_resolve_bridge.py` no longer claims Resolve ignores Fusion's
|
|
203
|
+
standalone script tree. Measured on free 21.0.3.7: markers left in two
|
|
204
|
+
undocumented container paths both appeared under Workspace ▸ Scripts, so Lite
|
|
205
|
+
scans more locations than the README documents. Install behaviour is unchanged —
|
|
206
|
+
the documented paths work, and each extra target is another chance for the macOS
|
|
207
|
+
App Management prompt to stall the copy — but the stated reason is now the true
|
|
208
|
+
one.
|
|
209
|
+
|
|
210
|
+
### Validated
|
|
211
|
+
|
|
212
|
+
Free edition alone (21.0.3.7, App Store), Studio never launched at any point,
|
|
213
|
+
confirmed by process check after every stage: 165/165 read-shaped MCP actions
|
|
214
|
+
clean with Blackmagic's module blocked; 109/112 API read methods exercised; render
|
|
215
|
+
to a non-empty file with `set_format` true; AAF/DRT/EDL/FCPXML all written;
|
|
216
|
+
SetLUT clears and reads back. Suite 1913 passing.
|
|
217
|
+
|
|
5
218
|
## What's New in v2.68.1
|
|
6
219
|
|
|
7
220
|
Bug fix. A missing tool argument now returns the structured error envelope the
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DaVinci Resolve MCP Server
|
|
2
2
|
|
|
3
|
-
[](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
|
|
4
4
|
[](https://www.npmjs.com/package/davinci-resolve-mcp)
|
|
5
5
|
[](docs/reference/api-coverage.md)
|
|
6
6
|
[-blue.svg)](#server-modes)
|
|
@@ -185,6 +185,47 @@ The open-source servers are complete and fully functional on their own.
|
|
|
185
185
|
| Render and deliver | Format/codec matrix probing, render settings validation, queued job lifecycle checks, guarded Quick Export |
|
|
186
186
|
| Extension authoring | Fuse, DCTL, ACES DCTL, and Resolve-page Lua/Python script lifecycle helpers with safe MCP-marked install/remove |
|
|
187
187
|
|
|
188
|
+
## Optional Extras
|
|
189
|
+
|
|
190
|
+
The core install is deliberately small: Python, ffmpeg, and the Resolve scripting
|
|
191
|
+
API. Some features need more, and **each one refuses honestly with its own
|
|
192
|
+
install line rather than degrading into a guess** — a fabricated tempo or an
|
|
193
|
+
invented level produces confident, wrong output, which is worse than no feature.
|
|
194
|
+
|
|
195
|
+
Run `python scripts/doctor.py` to see which of these you have.
|
|
196
|
+
|
|
197
|
+
| Extra | Unlocks | Licence |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| **ffmpeg** on PATH | Silence detection, dead-space markers, level measurement, audio analysis. The single most useful thing to install. | LGPL/GPL — invoked as a subprocess, never bundled |
|
|
200
|
+
| `pip install numpy` | Colour pre-balance, reference-still matching, sound-density audit | BSD |
|
|
201
|
+
| `pip install librosa` | Beat, bar and phrase detection for music-driven cutting | ISC |
|
|
202
|
+
| `pip install -U openai-whisper` | Transcription, and everything word-level built on it | MIT |
|
|
203
|
+
| `pip install open_clip_torch` | Visual similarity and `find_similar` | MIT |
|
|
204
|
+
| `pip install transformers` | CLAP audio embeddings | Apache-2.0 |
|
|
205
|
+
| `pip install opencv-python` | Additional frame analysis | Apache-2.0 |
|
|
206
|
+
|
|
207
|
+
`media_analysis` action `capabilities` reports the analysis stack in detail and
|
|
208
|
+
tells you what each missing piece would enable.
|
|
209
|
+
|
|
210
|
+
**Nothing here is bundled.** Model weights carry their own licences separate from
|
|
211
|
+
the code that loads them; check them before commercial use.
|
|
212
|
+
|
|
213
|
+
## What This Does Not Do
|
|
214
|
+
|
|
215
|
+
Knowing where a tool stops is worth as much as knowing what it does, and it is
|
|
216
|
+
cheaper to read it here than to discover it mid-project.
|
|
217
|
+
|
|
218
|
+
| Not supported | Why, and what you get instead |
|
|
219
|
+
|---|---|
|
|
220
|
+
| **Choosing the best take** | Performance is most of what makes a take right, and none of it is measurable from a waveform or a transcript. `rank_takes` ranks *fluency* — fillers, restarts, script coverage — and says so in every response. The take that plays is regularly the least fluent one, because the hesitation is often the acting. Use it to find the clean safety take, not to choose the read. |
|
|
221
|
+
| **Cutting to music** | No beat or downbeat detection yet. Speech-driven tools will read a music bed as one long region and are the wrong instrument for it. |
|
|
222
|
+
| **Judging a cut** | Nothing here has an opinion about whether an edit is good. Every destructive action is plan → review → confirm for that reason. |
|
|
223
|
+
| **Replacing an editor** | The output is a first-pass assembly, in the assistant-editor sense: ingest, sync, organize, string out, flag problems. It is a starting point you cut, not a finished cut. Defaults are deliberately **generous** — a first assembly is supposed to run long, because trimming is fast and visible while recovering discarded material is slow and invisible. |
|
|
224
|
+
| **Modifying your source media** | By design and without exception — see below. |
|
|
225
|
+
|
|
226
|
+
Anything analyzed but unverifiable is reported as unverified, never folded into
|
|
227
|
+
"fine". An empty result means "nothing found", never "nothing to find".
|
|
228
|
+
|
|
188
229
|
## Source Media Safety
|
|
189
230
|
|
|
190
231
|
This project treats camera originals and source media as immutable. Analysis tools read source files and write reports only to sidecar, scratch, or project analysis directories; confirmed metadata publishing writes only to Resolve's project database. The server must not modify, transcode, proxy, or create derivatives of source media unless the user explicitly asks for that. See [Media Analysis Guide](docs/guides/media-analysis-guide.md) for the detailed source-safe workflow.
|
|
@@ -231,9 +272,11 @@ Extension authoring references live in [docs/authoring](docs/authoring/). Resolv
|
|
|
231
272
|
|
|
232
273
|
## Requirements
|
|
233
274
|
|
|
234
|
-
- DaVinci Resolve
|
|
275
|
+
- DaVinci Resolve 18.5+ on macOS, Windows, or Linux. **Studio** supports external scripting directly. The **free edition** does not — Blackmagic gates external scripting to Studio — but it is still reachable through the [in-app bridge](#free-edition-in-app-bridge), which runs inside Resolve from the ungated **Workspace ▸ Scripts** menu.
|
|
235
276
|
- Python 3.10+ (3.10-3.12 is the lowest-risk range). Python 3.13/3.14 also work on recent Resolve builds (verified on Studio 20.3.2); older builds may fail to connect on 3.13+, in which case use 3.10-3.12.
|
|
236
|
-
- Resolve external scripting set to **Local
|
|
277
|
+
- Resolve external scripting set to **Local** (Studio). On the free edition this
|
|
278
|
+
preference has no effect — use the [in-app bridge](#free-edition-in-app-bridge)
|
|
279
|
+
instead.
|
|
237
280
|
|
|
238
281
|
Resolve 19.1.3 remains the compatibility baseline. Resolve 20.x scripting calls are additive, version-guarded, and live-tested on 20.3.2. Resolve 21.0 scripting additions (audio classification, speaker-detection transcription, IntelliSearch, slate analysis, motion-deblur, speech generation, session background-task control) are exposed behind runtime capability detection, so they stay inert on older builds and activate automatically on Resolve 21+.
|
|
239
282
|
|
package/docs/SKILL.md
CHANGED
|
@@ -850,11 +850,191 @@ clip-count readback plus `brain_edits` rationale rows.
|
|
|
850
850
|
min_strip_frames?, pre_head_frames?, post_tail_frames?, include_audio?)` —
|
|
851
851
|
waveform silence strips via ffmpeg `silencedetect`, mirroring Resolve's
|
|
852
852
|
*Clip → Audio Operations → Ripple Delete Silence* (defaults: −30 dB,
|
|
853
|
-
10-frame minimum strip,
|
|
853
|
+
10-frame minimum strip, 2 pre-head, 4 post-tail frames — guard bands that
|
|
854
|
+
keep the cut off the outgoing word's decay and the incoming word's attack).
|
|
855
|
+
Items without
|
|
854
856
|
readable file paths ride along whole (reported in `skipped`), so the
|
|
855
857
|
variant never silently loses content. `execute_silence_ripple(plan_id)`
|
|
856
858
|
assembles a tightened VARIANT timeline from keep ranges — same safety model
|
|
857
859
|
as `execute_tighten` (original untouched, confirm token, audio mirroring).
|
|
860
|
+
- `plan_dead_space_markers(timeline_name?, track_index?, threshold_db?,
|
|
861
|
+
tightness?, min_strip_frames?, pre_head_frames?, post_tail_frames?)` —
|
|
862
|
+
**review before you cut.** Finds dead space with the *same* calibrated gate as
|
|
863
|
+
`plan_silence_ripple` but proposes Resolve **markers** instead of an edit, so
|
|
864
|
+
an editor can look at every gap, delete the markers they disagree with, and
|
|
865
|
+
only then tighten. Reach for this whenever the ask is "show me the gaps
|
|
866
|
+
first" — it is the review gate, and without it an agent will invent its own
|
|
867
|
+
detection and mark the wrong spots. Red = confident; **Yellow = the gate only
|
|
868
|
+
just cleared its separation floor, so speech and room are close together and
|
|
869
|
+
the call deserves a second look.** Nothing is written: pair the returned
|
|
870
|
+
marker specs with `timeline_markers`. Items in `skipped` were *not* analyzed
|
|
871
|
+
and are explicitly **not** certified clean.
|
|
872
|
+
`tightness` (`generous` default | `balanced` | `tight`) scales the guard bands
|
|
873
|
+
and the minimum gap length — see below.
|
|
874
|
+
- `plan_report(plan_id, max_detail_rows?)` — **render any plan as a reviewable
|
|
875
|
+
Markdown report.** A 340-entry `keep_ranges` array is not reviewable, and the
|
|
876
|
+
rational response to a machine you cannot audit is to re-check it by hand,
|
|
877
|
+
which is the cost the tool was meant to remove. The report states: what would
|
|
878
|
+
change (in **timecode**, with a reason per cut), what was **deliberately left
|
|
879
|
+
alone** (invisible in the output, and the half people distrust most), what
|
|
880
|
+
could **not** be verified (never folded into "fine"), and what **needs a
|
|
881
|
+
human**. Returns both `report_markdown` and a one-line `summary` for chat.
|
|
882
|
+
Every plan kind renders, including ones this renderer does not know about.
|
|
883
|
+
- `rank_takes(clip_refs[], script?)` — rank several clips of the same material by
|
|
884
|
+
**measurable fluency**: filler density, stammered restarts, longest clean run,
|
|
885
|
+
and (with a `script`) how much of the intended line got said. **It ranks
|
|
886
|
+
fluency, not quality, and says so in every response.** Performance is most of
|
|
887
|
+
what makes a take right and none of it is measurable here — the take that
|
|
888
|
+
plays is regularly the least fluent one, because the hesitation is often the
|
|
889
|
+
acting. Use it to find the clean safety take or skip the warm-ups, never to
|
|
890
|
+
choose the read. Clips without transcripts are listed in `unavailable`
|
|
891
|
+
(**absent from the ranking, not last in it**), and takes too short to score
|
|
892
|
+
are flagged rather than dropped.
|
|
893
|
+
- `plan_beat_cuts(clip_ref | media_path, mode?, beats_per_bar?, bars_per_phrase?,
|
|
894
|
+
beat_offset?, min_shot_seconds?, timeline_fps?)` — **cut points from the music's
|
|
895
|
+
own pulse**, for footage with no speech. The speech tools find edit points in
|
|
896
|
+
words and pauses; music has neither, and pointing a silence gate at it makes
|
|
897
|
+
engine noise read as content and quiet read as dead space. `mode`: `beat` (every
|
|
898
|
+
beat — relentless), `bar` (downbeats), **`phrase` (default)** — music resolves at
|
|
899
|
+
phrase boundaries, which is what makes a cut feel inevitable rather than merely
|
|
900
|
+
synchronised. Frame-snapped. **Downbeats are inferred, not detected** (the first
|
|
901
|
+
beat is assumed to start a bar) — a track with a pickup needs `beat_offset`, and
|
|
902
|
+
that is the first thing to check if cuts feel consistently one beat early.
|
|
903
|
+
Reports its own tracking confidence. Requires the optional `librosa` extra
|
|
904
|
+
(`pip install librosa`, ISC) and **honest-refuses without it** rather than
|
|
905
|
+
inventing a tempo. Returns cut POINTS, not an assembly.
|
|
906
|
+
- `plan_prebalance(timeline_name?, track_index?, max_items?)` — **neutral technical
|
|
907
|
+
pre-balance**, the assistant colorist's highest-leverage pass. Measures black and
|
|
908
|
+
white points per channel off a mid-shot frame, groups by setup, picks a hero, and
|
|
909
|
+
proposes one bypassable **`ASST: Balance`** node per clip. Black balance on the
|
|
910
|
+
parade first, then white point. **Midtones are deliberately left warm** — skin
|
|
911
|
+
belongs near 11 o'clock on the vectorscope, and neutralizing midtones is the
|
|
912
|
+
fastest way to make everyone grey. Curves, vignettes, saturation, qualifiers and
|
|
913
|
+
windows are **refused in code**, not merely discouraged. Clipped highlights and
|
|
914
|
+
crushed shadows are flagged as `ASST: TECH/CREATIVE` markers, never silently
|
|
915
|
+
fixed. It has scopes and no eyes: numeric balance is defensible, look development
|
|
916
|
+
is not, and it cannot know the dim shot was dim on purpose.
|
|
917
|
+
- `rule_of_six_audit(timeline_name?, track_index?)` — audits a timeline against
|
|
918
|
+
the **Rule of Six** — the classical weighted cut criteria — and is loud about
|
|
919
|
+
what it cannot see. Those weights
|
|
920
|
+
are inverted against measurability: **everything computable is the bottom 26%**.
|
|
921
|
+
So **emotion (51%) and story (23%) appear in every response as `NOT_ASSESSED`
|
|
922
|
+
and cannot be suppressed**, criteria this build does not compute report
|
|
923
|
+
`NOT_IMPLEMENTED` (never a pass), and coverage is stated outright — *"1 of 6
|
|
924
|
+
criteria assessed, covering 10% of the decision."* **There is deliberately no
|
|
925
|
+
composite score**; averaging 26% into one number implies it describes the cut.
|
|
926
|
+
Findings order by scope ("movie first, scene second, moment third")
|
|
927
|
+
then by criterion weight — never by volume, so a rhythm problem (10%) always
|
|
928
|
+
outranks a screen-geography one (5%). Rhythm is implemented: metronomic runs
|
|
929
|
+
are flagged, and a pattern break landing on a marker is reported as **craft,
|
|
930
|
+
not a finding** — the break is where meaning lives. Cuts/min is compared to
|
|
931
|
+
the 14–16 commonly observed in dialogue, explicitly **descriptive not
|
|
932
|
+
prescriptive**.
|
|
933
|
+
- `split_edit_audit(timeline_name?, track_index?)` — **sound leads picture**.
|
|
934
|
+
The ear is faster than the eye, so the classical advice is to treat the cut as
|
|
935
|
+
a sound event first. Classifies every join: **L-cut** (audio edit later — outgoing
|
|
936
|
+
sound lingers), **J-cut** (audio earlier — incoming sound pulls forward), or
|
|
937
|
+
straight. A picture cut with no nearby audio edit is reported as **unpaired,
|
|
938
|
+
not straight** — sound running continuously across a join is a *stronger* form
|
|
939
|
+
of sound carrying picture. Flags a timeline where every join is straight: that
|
|
940
|
+
is where the NLE puts audio edits by default, and a dialogue sequence with no
|
|
941
|
+
split edits anywhere is usually one nobody has listened to yet. **No correct
|
|
942
|
+
ratio is suggested and none exists** — a montage, a two-hander and an
|
|
943
|
+
interview all want different distributions.
|
|
944
|
+
- `sound_density_audit(track_media, stream_limit?, duration_seconds?)` — the
|
|
945
|
+
**two-and-a-half rule**: an audience follows roughly 2.5 simultaneous sound
|
|
946
|
+
streams before the rest becomes texture. The distinction that makes this usable
|
|
947
|
+
is **competing vs. layered** — a music bed under dialogue is one stream plus
|
|
948
|
+
texture, not two competitors, and a version that counted active tracks would
|
|
949
|
+
flag every mixed timeline ever made. A stream within 12 dB of the loudest
|
|
950
|
+
counts as competing; further under counts as a bed. **2.5 is a long-standing
|
|
951
|
+
observation in sound editing, not a measured constant** — it is a parameter and its provenance
|
|
952
|
+
travels with every result. Pass rendered stems for a true reading; source clips
|
|
953
|
+
give a reading of the sources, and the response says which it got.
|
|
954
|
+
- `setup_sheet(timeline_name?, track_index?)` — **the wall of stills**: one
|
|
955
|
+
representative frame per *setup*, not per shot, so twenty images stand for the
|
|
956
|
+
whole film instead of two hundred reproducing the timeline at higher
|
|
957
|
+
resolution. Frame taken from the middle of that setup's longest usage (heads
|
|
958
|
+
and tails catch fades, slates and handles); ordered by **first appearance** so
|
|
959
|
+
the sheet reads in the direction the film does. Grouping is reel-name-else-
|
|
960
|
+
folder — a stated proxy for lighting setup, which Resolve does not expose.
|
|
961
|
+
- `first_impression(op=start|record|lock|get|list|diff, …)` — the editor is the
|
|
962
|
+
only person who gets to be a first-time audience, and that perception is
|
|
963
|
+
destroyed by the second viewing. Captures timestamped reactions during a first
|
|
964
|
+
pass and then **seals them**. `record` on a locked log raises; **there is
|
|
965
|
+
deliberately no unlock** — an impression that can be revised later is
|
|
966
|
+
worthless, because by then what changed is the viewer, not the film. Free text,
|
|
967
|
+
**no schema and no sentiment scoring** — the words are the artifact. `diff`
|
|
968
|
+
reports whether a later pass **revisited** each reaction and explicitly refuses
|
|
969
|
+
to claim anything was *fixed*.
|
|
970
|
+
- `plan_reference_match(reference_media, reference_at_seconds?, timeline_name?, max_items?)`
|
|
971
|
+
— match clips to a **graded reference still**, the way a colorist actually
|
|
972
|
+
communicates ("make it look like this one"). Reuses `prebalance.validate_plan`
|
|
973
|
+
rather than reimplementing the guardrails, so this path cannot permit what the
|
|
974
|
+
neutral path forbids. **END POINTS ONLY, stated in every response** — it puts
|
|
975
|
+
a shot in the reference's tonal neighbourhood and does **not** transfer the
|
|
976
|
+
reference's grade; curves, vignettes and secondaries stay where they are.
|
|
977
|
+
Matching across dissimilar subject matter (night exterior vs white cyc) is
|
|
978
|
+
reported as **low confidence** rather than delivered with a straight face.
|
|
979
|
+
- `plan_string_out(shots, order?)` — assembly for footage that does not talk.
|
|
980
|
+
Speechless material is cut from **shots and motion**, not silence: point a
|
|
981
|
+
speech gate at motorsport and engine noise reads as content while a quiet
|
|
982
|
+
straight reads as dead space. `order`: `chronological` (default) or
|
|
983
|
+
`activity`. **Unmeasured motion is never treated as static**, a locked-off
|
|
984
|
+
shot is described rather than penalised, and ranking by movement is a
|
|
985
|
+
measurement not an edit — the most important shot may rank last. Returns a
|
|
986
|
+
string-out, never a cut.
|
|
987
|
+
- `propose_structure(topics)` — **no-script mode**. Orders topics by coverage,
|
|
988
|
+
which measures what was *shot* and not what matters, and says so.
|
|
989
|
+
`requires_approval` is always true: a structure inferred from clustering is a
|
|
990
|
+
hypothesis about what the piece is, and the decision least safe to take
|
|
991
|
+
silently.
|
|
992
|
+
- `plan_broll(beats, candidates, allow_reuse?)` — place B-roll against A-roll
|
|
993
|
+
beats. **Placement only: relevance is whatever your matcher said and is never
|
|
994
|
+
re-scored here**, because whether a shot illustrates a line is not something
|
|
995
|
+
this can see. Cutaways sit *inside* a beat rather than straddling one; a beat
|
|
996
|
+
marked `protected` is never covered; an explicit `beat_index` is honoured
|
|
997
|
+
there or not at all, never silently moved somewhere it fits better.
|
|
998
|
+
- `plan_turnover(destinations, contents, version?, handle_frames?)` — validate
|
|
999
|
+
**sound / VFX / colour turnover manifests** against spec. Per-destination
|
|
1000
|
+
handle floors (sound 48 frames, picture 8 — crossfades and room tone reach
|
|
1001
|
+
past the picture cut), and a **timecode-burned picture reference is required
|
|
1002
|
+
in all three**, its absence a blocker: without one the receiving editor cannot
|
|
1003
|
+
verify anything against your intent. Includes the burn-in spec (both source
|
|
1004
|
+
*and* record timecode). **Manifests, not exports** — an export that runs
|
|
1005
|
+
perfectly and omits the textless is still a failed turnover, and rendering
|
|
1006
|
+
needs a live Resolve.
|
|
1007
|
+
- `journal(op=append|read|known_issues|ingest_log|session_prep|handoff|status|
|
|
1008
|
+
picture_lock|check_lock, …)` — the paperwork every craft role keeps and every
|
|
1009
|
+
tool skips. **Append-only:** resolving an issue appends a resolution and never
|
|
1010
|
+
deletes the issue, so the one nobody got round to is still there when someone
|
|
1011
|
+
asks why a shot shipped soft. `session_prep` carries open issues plus the value
|
|
1012
|
+
figures (prep hours, hours saved, rate) because the prep has to justify itself
|
|
1013
|
+
in the next budget round. `handoff` prints missing fields as **NOT STATED**
|
|
1014
|
+
rather than omitting them — a handoff that silently drops the frame rate reads
|
|
1015
|
+
as complete and the gap surfaces after work has started. `picture_lock` records
|
|
1016
|
+
a fingerprint of the cut and `check_lock` reports drift; the fingerprint hashes
|
|
1017
|
+
the **edit points**, not just counts and totals, so shots redistributed inside
|
|
1018
|
+
an unchanged runtime — exactly what a trim pass produces — still trip it.
|
|
1019
|
+
- **All audits accept `include_report=true`** for a Markdown rendering (what
|
|
1020
|
+
changed, what was deliberately left alone, what could not be verified, what
|
|
1021
|
+
needs a human). Off by default because rendering costs tokens on every call;
|
|
1022
|
+
every audit advertises it in `report_available`.
|
|
1023
|
+
- `conform_lint(timeline_name?, track_index?)` — **the online editor's checklist,
|
|
1024
|
+
run before turnover** instead of discovered after picture lock in someone else's
|
|
1025
|
+
suite. Blockers: frame-rate mismatch, offline media, two sources claiming one
|
|
1026
|
+
source timecode (misnamed cards — the most common reason a relink fails).
|
|
1027
|
+
Warnings: items buried under opaque layers, track overlaps, missing reel names,
|
|
1028
|
+
and effects that will not survive interchange (Premiere's *Scale to Frame Size*
|
|
1029
|
+
is the classic — its sizing data does not reach Resolve at all). It reports, it
|
|
1030
|
+
does not fix, and **checks that could not run for want of data are listed in
|
|
1031
|
+
`not_checked`** rather than counted as passes.
|
|
1032
|
+
- Plans now carry a **`handle_report`**: keep ranges that leave too little source
|
|
1033
|
+
media at a join for a dissolve, a slip or an audio crossfade. Picture floor 8
|
|
1034
|
+
frames, audio 48 — audio is far larger because crossfades and room tone reach
|
|
1035
|
+
past the picture cut. It reports rather than blocks (cutting to the head of a
|
|
1036
|
+
clip is often unavoidable), but **an unverified handle is never reported as a
|
|
1037
|
+
passing one**.
|
|
858
1038
|
- `plan_swap(timeline_start_frame | item_name, kind="visual"|"text",
|
|
859
1039
|
limit?)` — alternates for one timeline item via the similarity index,
|
|
860
1040
|
filtered to shots long enough to fill the slot exactly.
|
package/docs/install.md
CHANGED
|
@@ -4,13 +4,39 @@ This guide covers Resolve requirements, the universal installer, supported MCP c
|
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
7
|
-
- **DaVinci Resolve
|
|
7
|
+
- **DaVinci Resolve** 18.5+ (macOS, Windows, or Linux). **Studio** supports
|
|
8
|
+
external scripting directly. The **free edition** does not — Blackmagic gates
|
|
9
|
+
external scripting to Studio — but it is still reachable through the
|
|
10
|
+
[free-edition in-app bridge](../README.md#free-edition-in-app-bridge), which
|
|
11
|
+
runs inside Resolve from the ungated **Workspace ▸ Scripts** menu. Everything
|
|
12
|
+
below assumes Studio unless the bridge is in use
|
|
8
13
|
- **Python 3.10+** (the MCP SDK requires 3.10). **3.10–3.12 is the lowest-risk
|
|
9
14
|
choice**; 3.13/3.14 also work on recent Resolve builds — see below
|
|
10
15
|
- DaVinci Resolve running with **Preferences > General > "External scripting using"**
|
|
11
16
|
set to **Local**, or **Network** with `RESOLVE_SCRIPT_HOST` set to the Resolve
|
|
12
17
|
host IP (`127.0.0.1` when Resolve and the MCP run on the same machine)
|
|
13
18
|
|
|
19
|
+
### Optional extras
|
|
20
|
+
|
|
21
|
+
The core install needs only Python, ffmpeg and the Resolve scripting API.
|
|
22
|
+
Several features need an additional package and **refuse with the install line
|
|
23
|
+
rather than guessing** if it is absent:
|
|
24
|
+
|
|
25
|
+
| Extra | Unlocks | Licence |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| **ffmpeg** on PATH | silence detection, dead-space markers, level measurement | LGPL/GPL, subprocess only |
|
|
28
|
+
| `numpy` | `plan_prebalance`, `plan_reference_match`, `sound_density_audit` | BSD |
|
|
29
|
+
| `librosa` | `plan_beat_cuts` (beat / bar / phrase detection) | ISC |
|
|
30
|
+
| `openai-whisper` | transcription and the word-level tools built on it | MIT |
|
|
31
|
+
| `open_clip_torch` | visual similarity, `find_similar` | MIT |
|
|
32
|
+
| `transformers` | CLAP audio embeddings | Apache-2.0 |
|
|
33
|
+
| `opencv-python` | additional frame analysis | Apache-2.0 |
|
|
34
|
+
|
|
35
|
+
`python scripts/doctor.py` reports which are present. `media_analysis`
|
|
36
|
+
`capabilities` covers the analysis stack in more detail.
|
|
37
|
+
|
|
38
|
+
Model weights carry their own licences, separate from the code that loads them.
|
|
39
|
+
|
|
14
40
|
> **Python 3.13 / 3.14:** these are **allowed** — setup will use them and warn.
|
|
15
41
|
> Python 3.14 is verified working against DaVinci Resolve Studio 20.3.2. On
|
|
16
42
|
> *older* Resolve builds the scripting bridge may fail to load on 3.13+
|
package/install.py
CHANGED
|
@@ -36,7 +36,7 @@ from src.utils.update_check import (
|
|
|
36
36
|
|
|
37
37
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
38
38
|
|
|
39
|
-
VERSION = "2.
|
|
39
|
+
VERSION = "2.69.0"
|
|
40
40
|
# Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
|
|
41
41
|
# Resolve's scripting bridge loads into newer interpreters on recent builds
|
|
42
42
|
# (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
|
|
@@ -1721,6 +1721,31 @@ def main():
|
|
|
1721
1721
|
f" This can happen on Python 3.13+ with older Resolve builds. "
|
|
1722
1722
|
f"If MCP tools fail, recreate the venv with Python 3.10-3.12."
|
|
1723
1723
|
)
|
|
1724
|
+
elif resolve_running:
|
|
1725
|
+
# Running, healthy interpreter, still no connection. Reporting
|
|
1726
|
+
# "Not running — start Resolve" here (as this branch used to)
|
|
1727
|
+
# is both wrong and a dead end: Resolve *is* running. This is
|
|
1728
|
+
# the free-edition signature — external scripting is gated to
|
|
1729
|
+
# Studio — and the bridge is the way through, so say so
|
|
1730
|
+
# rather than sending the user to restart an app that is up.
|
|
1731
|
+
print(
|
|
1732
|
+
f" Resolve: {yellow('Running, but external scripting returned no connection')}"
|
|
1733
|
+
)
|
|
1734
|
+
print(
|
|
1735
|
+
" On Studio: Preferences > General > "
|
|
1736
|
+
"'External scripting using' = Local."
|
|
1737
|
+
)
|
|
1738
|
+
print(
|
|
1739
|
+
" On the free edition: external scripting is gated to Studio, "
|
|
1740
|
+
"but the in-app bridge works —"
|
|
1741
|
+
)
|
|
1742
|
+
print(
|
|
1743
|
+
" python scripts/install_resolve_bridge.py"
|
|
1744
|
+
)
|
|
1745
|
+
print(
|
|
1746
|
+
" then Workspace > Scripts > resolve_bridge, "
|
|
1747
|
+
"and set DAVINCI_RESOLVE_BRIDGE=1"
|
|
1748
|
+
)
|
|
1724
1749
|
else:
|
|
1725
1750
|
print(f" Resolve: {yellow('Not running')} — start Resolve to use MCP tools")
|
|
1726
1751
|
else:
|
package/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 DaVinci Resolve MCP Contributors and Bradford Operations LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"description": "Conform QC & repair engine: parse a turnover, derive the frame the target tool actually shows (the Oracle), frame-compare to a reference (brightness-robust), repair resourcefully, and deliver a verified package. Pure core + injected adapters. See docs/design/conform-qc-repair-engine-2026-06-16.md.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"private": true,
|
|
7
|
+
"license": "MIT",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"test": "node --test test/"
|
|
9
10
|
},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"description": "DaVinci Resolve DRP (Project) format \u2014 XML/binary serialization, asset packaging, grade node encoders/decoders, validation. Layer 2 (drp-validator + grade-node-extractor read from fs / zip archives).",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"private": true,
|
|
7
|
+
"license": "MIT",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"test": "echo 'see grade-encoder.test.js \u2014 runs via root jest config' && exit 0"
|
|
9
10
|
},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"description": "DaVinci Resolve DRT (Timeline-only) format — same SeqContainer/MpFolder schema as DRP, no project shell. Parser + builder + validator delegate to drp-format primitives.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"private": true,
|
|
7
|
+
"license": "MIT",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"test": "node --test __tests__/"
|
|
9
10
|
},
|