davinci-resolve-mcp 2.129.0 → 2.130.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.
|
@@ -52,6 +52,7 @@ window. `render.verify_output` covers the container-level checks.
|
|
|
52
52
|
| Turnover markers | EDL `* LOC:` locators + OTIO markers → authored | v2.119 |
|
|
53
53
|
| TC-bearing sources (AAF route) | native clip capture (`MediaStartTime`), channel-leg merge | v2.120–2.122 |
|
|
54
54
|
| Subtitles | `spec.subtitles` / `spec.subtitlesSrt` (raw SRT) | v2.128 |
|
|
55
|
+
| Compound clips | survive `extract_from_drp` → `.drt` (inner containers kept, recursive) | v2.130 |
|
|
55
56
|
| Fusion titles | `elements: [{type:'title', text}]` — **21-gen hosts only** | v2.108 |
|
|
56
57
|
|
|
57
58
|
`assemble_from_interchange` drives the same engine from an EDL / OTIO /
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.
|
|
40
|
+
VERSION = "2.130.0"
|
|
41
41
|
# Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
|
|
42
42
|
# Resolve's scripting bridge loads into newer interpreters on recent builds
|
|
43
43
|
# (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
|
package/package.json
CHANGED
|
@@ -373,6 +373,45 @@ export const drtTool = {
|
|
|
373
373
|
const keepEntry = seqEntries[idx];
|
|
374
374
|
const keepXml = await drpZip.file(keepEntry).async('string');
|
|
375
375
|
const keepSeqIds = [...keepXml.matchAll(/<Sequence>([0-9a-f-]{36})<\/Sequence>/g)].map((m) => m[1]);
|
|
376
|
+
// COMPOUND CLIPS: a compound is a pool Sm2MpCompoundClip with an
|
|
377
|
+
// EMBEDDED Sm2Sequence whose tracks live in their OWN SeqContainer —
|
|
378
|
+
// dropping that container ships a compound that imports and reads back
|
|
379
|
+
// but is hollow. Walk MediaRefs of the kept container(s) → compound
|
|
380
|
+
// pool elements → embedded sequence ids → keep those containers too,
|
|
381
|
+
// recursively (compounds nest). Live-proven: a .drt that keeps the
|
|
382
|
+
// inner container renders the compound's content (E45, 19.1.3.7).
|
|
383
|
+
const mpXmlByName = {};
|
|
384
|
+
for (const name of Object.keys(drpZip.files)) {
|
|
385
|
+
if (!drpZip.files[name].dir && name.endsWith('MpFolder.xml')) {
|
|
386
|
+
mpXmlByName[name] = await drpZip.file(name).async('string');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const seqXmlByEntry = { [keepEntry]: keepXml };
|
|
390
|
+
const keepContainers = new Set([keepEntry]);
|
|
391
|
+
const compoundIds = new Set();
|
|
392
|
+
const queue = [keepXml];
|
|
393
|
+
while (queue.length) {
|
|
394
|
+
const xml = queue.pop();
|
|
395
|
+
for (const m of xml.matchAll(/<MediaRef>([0-9a-f-]{36})<\/MediaRef>/g)) {
|
|
396
|
+
const ref = m[1];
|
|
397
|
+
if (compoundIds.has(ref)) continue;
|
|
398
|
+
for (const mpXml of Object.values(mpXmlByName)) {
|
|
399
|
+
const cm = mpXml.match(new RegExp(`<Sm2MpCompoundClip DbId="${ref}">[\\s\\S]*?</Sm2MpCompoundClip>`));
|
|
400
|
+
if (!cm) continue;
|
|
401
|
+
compoundIds.add(ref);
|
|
402
|
+
const innerSeq = (cm[0].match(/<Sm2Sequence DbId="([0-9a-f-]{36})">/) || [])[1];
|
|
403
|
+
if (!innerSeq) continue;
|
|
404
|
+
for (const entryName of seqEntries) {
|
|
405
|
+
if (keepContainers.has(entryName)) continue;
|
|
406
|
+
const sx = seqXmlByEntry[entryName] ?? (seqXmlByEntry[entryName] = await drpZip.file(entryName).async('string'));
|
|
407
|
+
if (sx.includes(`<Sequence>${innerSeq}</Sequence>`)) {
|
|
408
|
+
keepContainers.add(entryName);
|
|
409
|
+
queue.push(sx);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
376
415
|
const out = new JSZip();
|
|
377
416
|
let droppedTimelines = 0;
|
|
378
417
|
for (const name of Object.keys(drpZip.files)) {
|
|
@@ -380,7 +419,7 @@ export const drtTool = {
|
|
|
380
419
|
if (entry.dir) continue;
|
|
381
420
|
if (name === 'Gallery.xml') continue;
|
|
382
421
|
const isSeq = seqEntries.includes(name);
|
|
383
|
-
if (isSeq && name
|
|
422
|
+
if (isSeq && !keepContainers.has(name)) continue;
|
|
384
423
|
let content = await entry.async(name.endsWith('.xml') ? 'string' : 'nodebuffer');
|
|
385
424
|
if (name.endsWith('MpFolder.xml') && seqEntries.length > 1) {
|
|
386
425
|
content = content.replace(
|
package/src/granular/common.py
CHANGED
|
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
|
|
|
87
87
|
handlers=[logging.StreamHandler()],
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
VERSION = "2.
|
|
90
|
+
VERSION = "2.130.0"
|
|
91
91
|
logger = logging.getLogger("davinci-resolve-mcp")
|
|
92
92
|
logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
|
|
93
93
|
logger.info(f"Detected platform: {get_platform()}")
|