davinci-resolve-mcp 2.129.0 → 2.131.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,8 @@ 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 |
56
+ | Compound authoring | `spec.compounds` (one per archive; nested edit renders) | v2.131 |
55
57
  | Fusion titles | `elements: [{type:'title', text}]` — **21-gen hosts only** | v2.108 |
56
58
 
57
59
  `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.129.0"
40
+ VERSION = "2.131.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davinci-resolve-mcp",
3
- "version": "2.129.0",
3
+ "version": "2.131.0",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
@@ -51,7 +51,7 @@ const assembleSchema = z.object({
51
51
  spec: z
52
52
  .object({})
53
53
  .passthrough()
54
- .describe("assembleTimeline spec: { timelineName?, startFrame? (timeline start frame @24, default 86400=01:00:00:00 — sets the start TIMECODE, render-verified on 19), media?: {mediaFilePath, spec:{width,height,frameCount,fps}, cuts:[{startFrame,durationFrames,srcIn?,track? (1-based video track; >1 = video-only, render-verified stacking),speed?/reverse? (constant retime, e.g. 0.5, forward or backwards; video-only; readback+render-verified on 19),audioOnly?+track? (explicit AUDIO placement on audio track 1-8; presence suppresses the A1 mirror; render-verified on 19)}]} | [same, ...] (multi-source needs media_pool.capture_media_template run once per file), transitions?: [{track, atFrame, durationFrames?, trackType? ('video' dissolve | 'audio' cross-fade, both render-verified on 19)}], markers?: [{frame (timeline-absolute), color? (16 names), name?, note?, duration?, customData?}] (readback-verified on 19), subtitles?: [{startFrame (timeline-absolute), durationFrames, text}] + subtitlesSrt? (raw SRT, cues anchor at the origin; readback-verified on 19; angle-bracket runs read as SRT markup), elements?: [{type:'title'|'generator', track, startFrame, durationFrames?, text?, generatorName? ('Solid Color'|'SMPTE Color Bar'|'Grey Scale' render-verified on 19), ...}] }. startFrame is timeline-absolute (origin 86400)."),
54
+ .describe("assembleTimeline spec: { timelineName?, startFrame? (timeline start frame @24, default 86400=01:00:00:00 — sets the start TIMECODE, render-verified on 19), media?: {mediaFilePath, spec:{width,height,frameCount,fps}, cuts:[{startFrame,durationFrames,srcIn?,track? (1-based video track; >1 = video-only, render-verified stacking),speed?/reverse? (constant retime, e.g. 0.5, forward or backwards; video-only; readback+render-verified on 19),audioOnly?+track? (explicit AUDIO placement on audio track 1-8; presence suppresses the A1 mirror; render-verified on 19)}]} | [same, ...] (multi-source needs media_pool.capture_media_template run once per file), transitions?: [{track, atFrame, durationFrames?, trackType? ('video' dissolve | 'audio' cross-fade, both render-verified on 19)}], markers?: [{frame (timeline-absolute), color? (16 names), name?, note?, duration?, customData?}] (readback-verified on 19), compounds?: [{name, startFrame (parent, absolute), durationFrames, track?, cuts:[{mediaFilePath, startFrame (INNER, 0-based), durationFrames, srcIn?}]}] (ONE per archive; inner cuts need captured templates w/ native clips; render-verified nested playback on 19), subtitles?: [{startFrame (timeline-absolute), durationFrames, text}] + subtitlesSrt? (raw SRT, cues anchor at the origin; readback-verified on 19; angle-bracket runs read as SRT markup), elements?: [{type:'title'|'generator', track, startFrame, durationFrames?, text?, generatorName? ('Solid Color'|'SMPTE Color Bar'|'Grey Scale' render-verified on 19), ...}] }. startFrame is timeline-absolute (origin 86400)."),
55
55
  outputPath: z.string().describe('Absolute path where the importable .drt will be written'),
56
56
  targetAppVersion: z
57
57
  .union([z.string(), z.number()])
@@ -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 !== keepEntry) continue;
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(
@@ -28,6 +28,7 @@ const { cutSourceIntoClips } = require('./cut-media');
28
28
  const { buildConstantSpeedTimemapKeyed } = require('./media-timemap');
29
29
  const { encodeTimelineMarkersBlob } = require('./timeline-markers-blob');
30
30
  const { placeSubtitles, parseSrt } = require('./place-subtitles');
31
+ const { placeCompound } = require('./place-compound');
31
32
  const { randomUUID } = require('node:crypto');
32
33
  const { placeFusionTitle } = require('./place-fusion-title');
33
34
  const { placeGenerator } = require('./place-generator');
@@ -199,6 +200,64 @@ async function assembleTimeline(spec = {}) {
199
200
  }));
200
201
  }
201
202
 
203
+ // Compound clips: an empty nested timeline is spliced in from the
204
+ // harvested donor shape, then its content is placed with the ORDINARY cuts
205
+ // machinery targeting the inner container (inner origin is FRAME 0).
206
+ // Inner cuts must reference files with captured native templates.
207
+ if (Array.isArray(spec.compounds) && spec.compounds.length) {
208
+ // Pool elements for compound-only sources (files not in spec.media).
209
+ const specFiles = new Set((Array.isArray(media) ? media : media ? [media] : []).map((src) => src.mediaFilePath));
210
+ const insertedExtra = new Set();
211
+ for (const comp of spec.compounds) {
212
+ for (const cut of comp.cuts || []) {
213
+ const fp = cut.mediaFilePath;
214
+ if (!fp || specFiles.has(fp) || insertedExtra.has(fp)) continue;
215
+ const cache = loadMediaTemplate(fp);
216
+ if (!cache) continue; // the per-cut refusal below names it properly
217
+ const zipC = await JSZip.loadAsync(buffer);
218
+ const mpP = 'MediaPool/Master/MpFolder.xml';
219
+ zipC.file(mpP, insertMediaElement(await zipC.file(mpP).async('string'), cache.poolElement));
220
+ buffer = await zipC.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
221
+ insertedExtra.add(fp);
222
+ }
223
+ }
224
+ for (const [ci, comp] of spec.compounds.entries()) {
225
+ if (!comp || typeof comp !== 'object') throw new TypeError(`assembleTimeline: compounds[${ci}] must be an object`);
226
+ const res = await placeCompound(buffer, {
227
+ name: comp.name || `Compound ${ci + 1}`,
228
+ startFrame: comp.startFrame,
229
+ durationFrames: comp.durationFrames,
230
+ track: comp.track,
231
+ });
232
+ buffer = res.buffer;
233
+ const innerCuts = (comp.cuts || []).map((cut, i) => {
234
+ if (!cut.mediaFilePath) throw new TypeError(`assembleTimeline: compounds[${ci}].cuts[${i}].mediaFilePath is required`);
235
+ if (!Number.isInteger(cut.startFrame) || cut.startFrame < 0 || (cut.startFrame + (cut.durationFrames || 0)) > comp.durationFrames) {
236
+ throw new RangeError(`assembleTimeline: compounds[${ci}].cuts[${i}] must sit inside [0, ${comp.durationFrames}) — inner frames are 0-based`);
237
+ }
238
+ const cache = loadMediaTemplate(cut.mediaFilePath);
239
+ if (!cache) {
240
+ throw new Error(`assembleTimeline: compounds[${ci}].cuts[${i}] — no captured native media template for ${cut.mediaFilePath}. Run media_pool.capture_media_template(path) with Resolve open.`);
241
+ }
242
+ if (!cache.videoClipElement) {
243
+ throw new Error(`assembleTimeline: compounds[${ci}].cuts[${i}] — the media template for ${cut.mediaFilePath} predates native clip capture. Re-run media_pool.capture_media_template(path) with Resolve open.`);
244
+ }
245
+ const out = { ...cut, mediaRef: cache.mediaRef };
246
+ delete out.mediaFilePath;
247
+ if (cache.mediaStartTime) out.mediaStartTime = cache.mediaStartTime;
248
+ out.donorClipVideo = cache.videoClipElement;
249
+ if (cache.audioClipElement) out.donorClipAudio = cache.audioClipElement;
250
+ return out;
251
+ });
252
+ if (innerCuts.length) {
253
+ // The inner container has no donor items — clones come from the
254
+ // captured native clip elements, so the template donor is unused.
255
+ const cutRes = await cutSourceIntoClips(buffer, { cuts: innerCuts, timelineUuid: res.innerContainerId });
256
+ buffer = cutRes.buffer;
257
+ }
258
+ }
259
+ }
260
+
202
261
  // Subtitles: plain Sm2TiGenerator items (text in <Name>, no blobs — the
203
262
  // cache law does not apply; the payload is API-visible after import).
204
263
  // spec.subtitles frames are timeline-ABSOLUTE; spec.subtitlesSrt is raw SRT
@@ -139,8 +139,18 @@ async function cutSourceIntoClips(drpInput, opts = {}) {
139
139
  if (!tracks.length) continue;
140
140
  const items = getItemsInner(tracks[0]);
141
141
  const clips = splitClipElements(items);
142
- if (!clips.length) continue; // audio-less media: nothing to cut on A1
143
- const donor = clips[0];
142
+ // No donor items is fine when every cut carries its own captured native
143
+ // clip (compound inner containers start EMPTY by design); the template
144
+ // donor is only required for cuts without one.
145
+ const donor = clips[0] || null;
146
+ if (!donor) {
147
+ const donorless = cuts.filter((cut) => !(trackType === 'audio' ? cut.donorClipAudio : cut.donorClipVideo));
148
+ if (trackType === 'audio' && !cuts.some((cut) => cut.audioOnly)) continue; // no donor, no explicit audio: nothing to mirror
149
+ if (donorless.length) {
150
+ if (trackType === 'audio') continue; // audio-less media: nothing to cut on A1
151
+ throw new Error('cutSourceIntoClips: the target timeline has no donor clip and some cuts carry no captured native clip element — re-capture the media template');
152
+ }
153
+ }
144
154
  if (trackType === 'audio') {
145
155
  const audioCuts = cuts.filter((cut) => cut.audioOnly);
146
156
  if (audioCuts.length) {
@@ -0,0 +1,123 @@
1
+ /**
2
+ * place-compound — author a COMPOUND CLIP (nested timeline) into a .drp,
3
+ * offline.
4
+ *
5
+ * Anatomy (harvested live from Studio 19.1.3.7, CreateCompoundClip +
6
+ * ExportProject; extraction of this shape render-verified — the compound's
7
+ * inner content plays):
8
+ * - pool: `Sm2MpCompoundClip` EMBEDDING a full `Sm2Sequence` (its own
9
+ * FrameRate/Resolution/MediaExtents + Fairlight FieldsBlob, EMPTY track
10
+ * vecs);
11
+ * - the inner tracks live in their OWN SeqContainer whose `<Sequence>`
12
+ * values reference the embedded Sm2Sequence DbId; the inner timeline's
13
+ * ORIGIN IS FRAME 0 (unlike top-level timelines at 86400);
14
+ * - the parent-timeline item is a plain `Sm2TiVideoClip` with `MediaRef`
15
+ * → the compound's pool DbId, `MediaStartTime` 0, and an identity
16
+ * `MediaTimemapBA` of [0x02][doubleBE((innerFrames − 0.5) / fps)].
17
+ *
18
+ * All three pieces ride as harvested templates (compound-pool-r19 /
19
+ * compound-inner-r19 / compound-item-r19); this module rewires identities
20
+ * and empties the inner Items — the caller then places content INSIDE the
21
+ * compound with the ordinary cuts machinery, passing the returned
22
+ * `innerContainerId` as `timelineUuid` (0-based frames).
23
+ *
24
+ * @module drp-format/place-compound
25
+ */
26
+
27
+ const fs = require('node:fs');
28
+ const path = require('node:path');
29
+ const crypto = require('node:crypto');
30
+ const { escapeXml } = require('./xml-builder');
31
+ const { loadDrpZip, selectTargetSeq, getTrackVec, replaceTrackVec, getItemsInner, setItemsInner, freshDbIds } = require('./seq-surgery');
32
+
33
+ const T = (f) => path.join(__dirname, 'templates', f);
34
+
35
+ /**
36
+ * Insert an EMPTY compound (pool object + inner container + parent item).
37
+ *
38
+ * @param {Buffer|string} drpInput
39
+ * @param {object} opts
40
+ * @param {string} opts.name - compound name (parent item + pool).
41
+ * @param {number} opts.startFrame - parent placement (timeline-absolute).
42
+ * @param {number} opts.durationFrames - parent item duration AND the inner
43
+ * timeline's content length.
44
+ * @param {number} [opts.track=1] - parent video track (must exist).
45
+ * @param {number} [opts.fps=24]
46
+ * @param {string} [opts.timelineUuid] - parent container DbId.
47
+ * @returns {Promise<{buffer:Buffer, compoundId:string, innerContainerId:string, innerSequenceId:string}>}
48
+ */
49
+ async function placeCompound(drpInput, opts = {}) {
50
+ const { name, startFrame, durationFrames, track = 1, fps = 24, timelineUuid } = opts;
51
+ if (typeof name !== 'string' || !name.length) throw new TypeError('placeCompound: name is required');
52
+ if (!Number.isInteger(startFrame) || !Number.isInteger(durationFrames) || durationFrames <= 0) {
53
+ throw new TypeError('placeCompound: integer startFrame and positive durationFrames are required');
54
+ }
55
+
56
+ const zip = await loadDrpZip(drpInput);
57
+ const { entry, xml: parentXml } = await selectTargetSeq(zip, timelineUuid);
58
+
59
+ // The harvested compound cluster keeps its ORIGINAL GUIDs verbatim: the
60
+ // embedded Sm2Sequence FieldsBlob almost certainly encodes cluster
61
+ // identities, and freshening the XML ids around an unchanged blob CRASHED
62
+ // Resolve on import (measured, E47/E47c — the app died, twice). The
63
+ // harvest GUIDs cannot collide with an assembled archive's fresh ids, so
64
+ // verbatim is safe — but it limits authoring to ONE compound per archive.
65
+ const pool0 = fs.readFileSync(T('compound-pool-r19.xml'), 'utf8');
66
+ const compoundId = pool0.match(/<Sm2MpCompoundClip DbId="([^"]+)"/)[1];
67
+ const innerSequenceId = pool0.match(/<Sm2Sequence DbId="([^"]+)"/)[1];
68
+ const inner0 = fs.readFileSync(T('compound-inner-r19.xml'), 'utf8');
69
+ const innerContainerId = inner0.match(/<Sm2SequenceContainer DbId="([^"]+)"/)[1];
70
+ if (zip.file(`SeqContainer/${innerContainerId}.xml`)) {
71
+ throw new Error('placeCompound: only one compound per archive is supported (the harvested donor identities are kept verbatim)');
72
+ }
73
+
74
+ // 1) Inner container: template verbatim, Items emptied (content added by
75
+ // the caller via the cuts machinery, 0-based frames).
76
+ const inner = inner0.replace(/<Items>[\s\S]*?<\/Items>/g, '<Items/>');
77
+ zip.file(`SeqContainer/${innerContainerId}.xml`, inner);
78
+
79
+ // 2) Pool compound element: verbatim identities; only name + extents change.
80
+ let pool = pool0;
81
+ pool = pool.replace(/<Name>[^<]*<\/Name>/, `<Name>${escapeXml(name)}</Name>`);
82
+ // MediaExtents = [startSec, durationSec] LE doubles; inner starts at 0.
83
+ const me = Buffer.alloc(16);
84
+ me.writeDoubleLE(0, 0);
85
+ me.writeDoubleLE(durationFrames / fps, 8);
86
+ pool = pool.replace(/<MediaExtents>[0-9a-fA-F]*<\/MediaExtents>/, `<MediaExtents>${me.toString('hex')}</MediaExtents>`);
87
+ // Attach to the primary MediaPool folder — and point the element's
88
+ // <MpFolder> at THAT folder's DbId (the template's value references the
89
+ // harvest project's folder; a dangling folder ref CRASHES Resolve on
90
+ // import, measured E47).
91
+ const mpPath = 'MediaPool/Master/MpFolder.xml';
92
+ let mpXml = await zip.file(mpPath).async('string');
93
+ const folderId = (mpXml.match(/<Sm2MpFolder DbId="([^"]+)"/) || [])[1];
94
+ if (!folderId) throw new Error('placeCompound: target MpFolder has no Sm2MpFolder DbId');
95
+ pool = pool.replace(/<MpFolder>[0-9a-f-]{36}<\/MpFolder>/, `<MpFolder>${folderId}</MpFolder>`);
96
+ mpXml = mpXml.replace('</MediaVec>', `${pool}\n </MediaVec>`);
97
+ zip.file(mpPath, mpXml);
98
+
99
+ // 3) Parent item: template clone → fresh id, name, placement, MediaRef,
100
+ // identity timemap over the inner content ((frames − 0.5)/fps, measured).
101
+ let item = fs.readFileSync(T('compound-item-r19.xml'), 'utf8').trim();
102
+ item = freshDbIds(item);
103
+ item = item.replace(/<Name>[^<]*<\/Name>/, `<Name>${escapeXml(name)}</Name>`);
104
+ item = item.replace(/<Start>\d+<\/Start>/, `<Start>${startFrame}</Start>`);
105
+ item = item.replace(/<Duration>\d+<\/Duration>/, `<Duration>${durationFrames}</Duration>`);
106
+ item = item.replace(/<MediaRef>[0-9a-f-]{36}<\/MediaRef>/, `<MediaRef>${compoundId}</MediaRef>`);
107
+ const tm = Buffer.alloc(9);
108
+ tm.writeUInt8(0x02, 0);
109
+ tm.writeDoubleBE((durationFrames - 0.5) / fps, 1);
110
+ item = item.replace(/<MediaTimemapBA>[0-9a-fA-F]*<\/MediaTimemapBA>/, `<MediaTimemapBA>${tm.toString('hex')}</MediaTimemapBA>`);
111
+
112
+ const { match: vec, tracks } = getTrackVec(parentXml, 'video');
113
+ if (track > tracks.length) throw new Error(`placeCompound: parent video track ${track} does not exist (${tracks.length})`);
114
+ const items = getItemsInner(tracks[track - 1]);
115
+ tracks[track - 1] = setItemsInner(tracks[track - 1], items + item);
116
+ const newParent = replaceTrackVec(parentXml, 'video', vec, tracks);
117
+ zip.file(entry, newParent);
118
+
119
+ const buffer = await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
120
+ return { buffer, compoundId, innerContainerId, innerSequenceId };
121
+ }
122
+
123
+ module.exports = { placeCompound };
@@ -0,0 +1,134 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--DbAppVer="19.1.3.0007" DbPrjVer="14"-->
3
+ <Sm2SequenceContainer DbId="35c74c4a-c3a0-4a78-961d-9594df684608">
4
+ <FieldsBlob/>
5
+ <VideoTrackVec>
6
+ <Element>
7
+ <Sm2TiTrack DbId="6b3d42a5-7300-4efd-95f2-867bbb2b5397">
8
+ <FieldsBlob>000000010000000100000012004e0075006d004c00610079006500720073000000020000000000</FieldsBlob>
9
+ <Type>0</Type>
10
+ <SubType>0</SubType>
11
+ <Flags>0</Flags>
12
+ <Sequence>d7cfd3f0-e8b9-4048-867c-30ed6c427d83</Sequence>
13
+ <Items>
14
+ <Element>
15
+ <Sm2TiVideoClip DbId="9d147500-16b2-46a2-a14e-8dd6e26b41df">
16
+ <FieldsBlob>0000000200000017800a02200112100000000000000005ffffffffffffffff</FieldsBlob>
17
+ <PrettyType/>
18
+ <Name>cut_src.mp4</Name>
19
+ <Start>0</Start>
20
+ <Duration>192</Duration>
21
+ <LinkedItemSync/>
22
+ <WasDisbanded>false</WasDisbanded>
23
+ <MarkersBA/>
24
+ <UiMemento>0</UiMemento>
25
+ <Flags>0</Flags>
26
+ <PriorityIndex>0</PriorityIndex>
27
+ <EffectFiltersBA/>
28
+ <ImportExportMetadataBA/>
29
+ <RenderTextEnabled>true</RenderTextEnabled>
30
+ <RenderTextGanged>true</RenderTextGanged>
31
+ <RenderTextPrefixed>true</RenderTextPrefixed>
32
+ <In/>
33
+ <MixedFrameRateAlignment>0</MixedFrameRateAlignment>
34
+ <MediaRef>bcbdc92a-1348-40eb-899d-1294a86f22c4</MediaRef>
35
+ <MediaStartTime>0</MediaStartTime>
36
+ <MediaFilePath>/Users/samuelgursky/Movies/mcp_probe_tmp/cut_src.mp4</MediaFilePath>
37
+ <MediaReelNumber/>
38
+ <MediaFrameRate>00000000000038400000000000000000</MediaFrameRate>
39
+ <MediaTimemapBA>02401fd55555555555</MediaTimemapBA>
40
+ <LastChangedTime>0</LastChangedTime>
41
+ <LastRenderedTime>0</LastRenderedTime>
42
+ <IsMarkedForCaching>false</IsMarkedForCaching>
43
+ <IsForceConformed>true</IsForceConformed>
44
+ <MatchConflictState>0</MatchConflictState>
45
+ <UseOppositeSrcForLeftEye>false</UseOppositeSrcForLeftEye>
46
+ <UseOppositeSrcForRightEye>false</UseOppositeSrcForRightEye>
47
+ <RenderCacheBA/>
48
+ <CurrentSelectorIdx>0</CurrentSelectorIdx>
49
+ <IsPreConformed>false</IsPreConformed>
50
+ <PreConformMediaExtents>00000100000030c20000010000003042</PreConformMediaExtents>
51
+ <MediaMetadata/>
52
+ <Thumbnail>
53
+ <BtThumnail DbId="3c6b3899-e59d-4d68-9dab-23e360098d00">
54
+ <FieldsBlob/>
55
+ <ImgWidth>-1</ImgWidth>
56
+ <ImgHeight>-1</ImgHeight>
57
+ <Buffer/>
58
+ </BtThumnail>
59
+ </Thumbnail>
60
+ <ThumbnailDirtyFlag>true</ThumbnailDirtyFlag>
61
+ </Sm2TiVideoClip>
62
+ </Element>
63
+ <Element>
64
+ <Sm2TiVideoClip DbId="1da3a8f4-f465-4773-b38a-d8b867b3963f">
65
+ <FieldsBlob>0000000200000017800a02200112100000000000000005ffffffffffffffff</FieldsBlob>
66
+ <PrettyType/>
67
+ <Name>white_src.mp4</Name>
68
+ <Start>192</Start>
69
+ <Duration>192</Duration>
70
+ <LinkedItemSync/>
71
+ <WasDisbanded>false</WasDisbanded>
72
+ <MarkersBA/>
73
+ <UiMemento>0</UiMemento>
74
+ <Flags>0</Flags>
75
+ <PriorityIndex>0</PriorityIndex>
76
+ <EffectFiltersBA/>
77
+ <ImportExportMetadataBA/>
78
+ <RenderTextEnabled>true</RenderTextEnabled>
79
+ <RenderTextGanged>true</RenderTextGanged>
80
+ <RenderTextPrefixed>true</RenderTextPrefixed>
81
+ <In/>
82
+ <MixedFrameRateAlignment>0</MixedFrameRateAlignment>
83
+ <MediaRef>f84ec51d-939c-4064-bfbc-ddef08cda41f</MediaRef>
84
+ <MediaStartTime>0</MediaStartTime>
85
+ <MediaFilePath>/Users/samuelgursky/Movies/mcp_probe_tmp/white_src.mp4</MediaFilePath>
86
+ <MediaReelNumber/>
87
+ <MediaFrameRate>00000000000038400000000000000000</MediaFrameRate>
88
+ <MediaTimemapBA>02401fd55555555555</MediaTimemapBA>
89
+ <LastChangedTime>0</LastChangedTime>
90
+ <LastRenderedTime>0</LastRenderedTime>
91
+ <IsMarkedForCaching>false</IsMarkedForCaching>
92
+ <IsForceConformed>true</IsForceConformed>
93
+ <MatchConflictState>0</MatchConflictState>
94
+ <UseOppositeSrcForLeftEye>false</UseOppositeSrcForLeftEye>
95
+ <UseOppositeSrcForRightEye>false</UseOppositeSrcForRightEye>
96
+ <RenderCacheBA/>
97
+ <CurrentSelectorIdx>0</CurrentSelectorIdx>
98
+ <IsPreConformed>false</IsPreConformed>
99
+ <PreConformMediaExtents>00000100000030c20000010000003042</PreConformMediaExtents>
100
+ <MediaMetadata/>
101
+ <Thumbnail>
102
+ <BtThumnail DbId="58e2f7aa-358c-4ddf-88ed-99811bcfe887">
103
+ <FieldsBlob/>
104
+ <ImgWidth>-1</ImgWidth>
105
+ <ImgHeight>-1</ImgHeight>
106
+ <Buffer/>
107
+ </BtThumnail>
108
+ </Thumbnail>
109
+ <ThumbnailDirtyFlag>true</ThumbnailDirtyFlag>
110
+ </Sm2TiVideoClip>
111
+ </Element>
112
+ </Items>
113
+ <UserDefinedName/>
114
+ <LayersVec/>
115
+ </Sm2TiTrack>
116
+ </Element>
117
+ </VideoTrackVec>
118
+ <AudioTrackVec>
119
+ <Element>
120
+ <Sm2TiTrack DbId="8857f9df-f547-4c9c-ac2e-bc0651436031">
121
+ <FieldsBlob>000000010000000100000012004e0075006d004c00610079006500720073000000020000000000</FieldsBlob>
122
+ <Type>1</Type>
123
+ <SubType>0</SubType>
124
+ <Flags>0</Flags>
125
+ <Sequence>d7cfd3f0-e8b9-4048-867c-30ed6c427d83</Sequence>
126
+ <Items/>
127
+ <UserDefinedName/>
128
+ <LayersVec/>
129
+ </Sm2TiTrack>
130
+ </Element>
131
+ </AudioTrackVec>
132
+ <SubtitleTrackVec/>
133
+ <DbSavedTime>20619279</DbSavedTime>
134
+ </Sm2SequenceContainer>
@@ -0,0 +1,49 @@
1
+ <Element>
2
+ <Sm2TiVideoClip DbId="c280763e-ffa1-4802-b439-6041817a64b4">
3
+ <FieldsBlob>0000000200000017800a02200112100000000000000005ffffffffffffffff</FieldsBlob>
4
+ <PrettyType/>
5
+ <Name>E44_COMPOUND</Name>
6
+ <Start>86400</Start>
7
+ <Duration>384</Duration>
8
+ <LinkedItemSync/>
9
+ <WasDisbanded>false</WasDisbanded>
10
+ <MarkersBA/>
11
+ <UiMemento>0</UiMemento>
12
+ <Flags>0</Flags>
13
+ <PriorityIndex>0</PriorityIndex>
14
+ <EffectFiltersBA/>
15
+ <ImportExportMetadataBA/>
16
+ <RenderTextEnabled>true</RenderTextEnabled>
17
+ <RenderTextGanged>true</RenderTextGanged>
18
+ <RenderTextPrefixed>true</RenderTextPrefixed>
19
+ <In/>
20
+ <MixedFrameRateAlignment>0</MixedFrameRateAlignment>
21
+ <MediaRef>033ee600-12a6-4f75-8232-b478aaa728a9</MediaRef>
22
+ <MediaStartTime>0</MediaStartTime>
23
+ <MediaFilePath/>
24
+ <MediaReelNumber/>
25
+ <MediaFrameRate>00000000000038400000000000000000</MediaFrameRate>
26
+ <MediaTimemapBA>02402feaaaaaaaaaab</MediaTimemapBA>
27
+ <LastChangedTime>0</LastChangedTime>
28
+ <LastRenderedTime>0</LastRenderedTime>
29
+ <IsMarkedForCaching>false</IsMarkedForCaching>
30
+ <IsForceConformed>true</IsForceConformed>
31
+ <MatchConflictState>0</MatchConflictState>
32
+ <UseOppositeSrcForLeftEye>false</UseOppositeSrcForLeftEye>
33
+ <UseOppositeSrcForRightEye>false</UseOppositeSrcForRightEye>
34
+ <RenderCacheBA/>
35
+ <CurrentSelectorIdx>0</CurrentSelectorIdx>
36
+ <IsPreConformed>false</IsPreConformed>
37
+ <PreConformMediaExtents>00000100000030c20000010000003042</PreConformMediaExtents>
38
+ <MediaMetadata/>
39
+ <Thumbnail>
40
+ <BtThumnail DbId="c5429bb1-6542-4a12-8cf0-49de595365e8">
41
+ <FieldsBlob/>
42
+ <ImgWidth>-1</ImgWidth>
43
+ <ImgHeight>-1</ImgHeight>
44
+ <Buffer/>
45
+ </BtThumnail>
46
+ </Thumbnail>
47
+ <ThumbnailDirtyFlag>true</ThumbnailDirtyFlag>
48
+ </Sm2TiVideoClip>
49
+ </Element>
@@ -0,0 +1,55 @@
1
+ <Element>
2
+ <Sm2MpCompoundClip DbId="033ee600-12a6-4f75-8232-b478aaa728a9">
3
+ <FieldsBlob>00000002000000e58128b52ffd60d400d50600224d272d804d9a0333849884002a8cc182401da7a7c91bc244b4e50b900ec453d0c848247b9b9f03e471ff2568d7de3b05efbdf7de7b0004cfc6cecc88822b50ad2ba6d5d2e2945aa5624e135a352da797576ae5b46d2f5db75a6d219e5dd39d903e5642870e1e860d2fba1535ba9b9b578c0e0b4dda9173d3e5ec7c78cd98e94a3470397aa4487904f25ce02df43c224118101909399102188545252c32610117005b4b48836c006fda05872efba2610a2ed66a9669fdd206c985e18311c0609d6c749c71900dab86390d4a1bae086e72c29a99bfcd9c9eb926</FieldsBlob>
4
+ <Name>E44_COMPOUND</Name>
5
+ <MpFolder>7d3048e9-199e-4146-8c04-d682d7aae234</MpFolder>
6
+ <UniqueMediaPoolItemId>0a380d87-9717-4b42-a279-3b6389f2b37d</UniqueMediaPoolItemId>
7
+ <MarkIn/>
8
+ <MarkInVideo/>
9
+ <MarkInAudio/>
10
+ <MarkOut/>
11
+ <MarkOutVideo/>
12
+ <MarkOutAudio/>
13
+ <CurPlayheadPosition/>
14
+ <PinsBA/>
15
+ <VirtualAudioTracksBA/>
16
+ <MatteVec/>
17
+ <AudioSource>AUDIO_SOURCE_EMBEDDED</AudioSource>
18
+ <PTZRPreset>
19
+ <SmPTZRPreset DbId="27cce4a2-3ef9-4eac-81a7-6bfceecabd08">
20
+ <FieldsBlob/>
21
+ <Name/>
22
+ <ID>100</ID>
23
+ <IsCustom>true</IsCustom>
24
+ <Producer>Producer@Resolve</Producer>
25
+ <Presets>7b7d</Presets>
26
+ </SmPTZRPreset>
27
+ </PTZRPreset>
28
+ <PTZRPresetType>0</PTZRPresetType>
29
+ <SlateTC>-68719476737</SlateTC>
30
+ <Sequence>
31
+ <Sm2Sequence DbId="d7cfd3f0-e8b9-4048-867c-30ed6c427d83">
32
+ <FieldsBlob>000000010000000500000012005400680075006d0062006e00610069006c0000000c00000015200000000100000006000000100055006e0069007100750065004900640000000a000000004800300061006500660031003000370064002d0030006600390035002d0034003800610034002d0061003500330032002d003200620037003500630032006100380030003900620035000000100049006d0067005700690064007400680000000200000000d0000000140049006d0067005100750061006c006900740079000000020000000001000000120049006d00670048006500690067006800740000000200000000750000000c0044006200540079007000650000000a000000001400420074005400680075006d006e00610069006c0000000c0042007500660066006500720000000c0000001410ffd8ffe000104a46494600010101004800480000ffdb004300080606070605080707070909080a0c140d0c0b0b0c1912130f141d1a1f1e1d1a1c1c20242e2720222c231c1c2837292c30313434341f27393d38323c2e333432ffdb0043010909090c0b0c180d0d1832211c213232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232ffc0001108007500d003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00f9fe8a28a002bb9f0fff00c80edbfe05ff00a11ae1abb9f0ff00fc80edbfe05ffa11ae1cc3f84bd7fccfaae10ff7e9ff0081fe7134ebb2f09f873784d4af63e383046ddffda23f97e7e9597e17d10ea97e25994fd9612198e061dbb2f3fafb7d457a4d74e4b972a9fed15568b65dfccf0bc4be3396113ca3032b4daf7e4b78a7f6579b5bf65a75d39af16ffcb9ff00c0ff00f65ae6aba5f16ffcb9ff00c0ff00f65ae6abf47c1ff063fd753def0f3fe49bc37fdbff00fa7241599e20ff00901dcffc07ff004215a7599e20ff00901dcffc07ff004215db43f8b1f547d3669fee35bfc12fc99c3514515f447e3615f62d7c755f62d7e1de33ff00cc0ffdc4ff00dc67a7977daf97ea1451457e1a7a670de20ff90e5cff00c07ff4115995a7e20ff90e5cff00c07ff4115995f4543f851f447e379a7fbf56ff001cbf3615cd78b3fe5cff00e07ffb2d74b5cd78b7fe5cff00e07ffb2d7760ff008d1feba1f4de1e7fc94986ff00b7ff00f4dc8b7e13f11323c7a65e3e50e16090f553d94fb7a7a74e9d3b7af18af46f0a6b6752b236d3b96ba8072ccd9322f63f8743f87ad7e8b92e62e7fecf55ebd1fe9fe47d1f89bc191a17ce7031b45bfde45746fedaf57a4bcf5eaced3c3fff0021cb6ff817fe826bb9ae1bc3ff00f21cb6ff00817fe826bb9aebcc3f8abd3fccf9de10ff00719ff8dfe510a28a2b84faa3e00a28a2800aef3c3313cfa4d9c312ee92462aa3d4972057075ec1f0a74e5bab58aedf056d836d07fbc59b07f000fe38ac2b5078870a4babfd1dcf532ecd619453c463a7f629b6bcdb945457cdb48f46d2b4f8f4bd3a1b54032a32ec3f89bb9ff3ed5768a2beae108c22a11d91f80e271357155a75eb3bca4db6fbb7ab39af16ff00cb9ffc0fff0065ae6aba5f16ff00cb9ffc0fff0065ae6abdec1ff063fd753fa57c3cff00926f0dff006fff00e9c905667883fe40773ff01ffd08569d667883fe40773ff01ffd08576d0fe2c7d51f4d9a7fb8d6ff0004bf2670d451457d11f8d857d8b5f1d57d8b5f8778cfff00303ff713ff00719e9e5df6be5fa8514515f869e99c37883fe43973ff0001ff00d04566569f883fe43973ff0001ff00d0456657d150fe147d11f8de69fefd5bfc72fcd85735e2dff973ff0081ff00ecb5d2d735e2dff973ff0081ff00ecb5dd83fe347fae87d37879ff0025261bfedfff00d37239aab5a75ec9a75fc37717de8db247f78771f88aab457bd1938494a2ecd1fd2f5e853c452951aaaf19269a7d53d1a3ddbc2f3c773aa594f136e8e452ca7d8a1aef6bc6be136a065d416c5d86612cf18279da55b200f63dff00daaf65afa9ab885888c2aaeabf1bbb9f81e0b279e4d57118196bc951d9f78b8c5c5fdcd5fcee828a28ac8f40f8028a28a002be89f873a5cda578234f49d1925b8537254b03f2bfcc8463d5369f5e7f0af9dabebbbbd3a1d2248b4cb72c60b3b786de32e724aa46aa33ef815db8049d5d7b1f2fc5b394700945ef249fdcdfe6915e8a28af64fcd8e6bc5bff002e7ff03ffd96b9aae97c5bff002e7ff03ffd96b9aaf7307fc18ff5d4fe9cf0f3fe49bc37fdbfff00a7241599e20ff901dcff00c07ff4215a7599e20ff901dcff00c07ff4215db43f8b1f547d3669fee35bfc12fc99c3514515f447e3615f62d7c755f62d7e1de33ffcc0ff00dc4ffdc67a7977daf97ea1451457e1a7a670de20ff0090e5cffc07ff004115995a7e20ff0090e5cffc07ff004115995f4543f851f447e379a7fbf56ff1cbf3615cd78b7fe5cffe07ff00b2d74b5cd78b7fe5cffe07ff00b2d7760ff8d1feba1f4de1e7fc94986ffb7fff004dc8e6a8ad0d134393c49ac5be9115efd8a4b9240b8f2bccd9805beee467a63af7a75f78ebc35e1bbfb8d0aefc109a8dce9b2b59cb7a75278bed2f1928d26c0a42ee2a5b6e4e338c9afa5a3859d68f3459fd039967b87cbeaaa5562db6afa5bcd756bb1a5e02d5d346f1ae99349bcc73cc2d1820049329d8bd7b066527be01ebd2be8faf99b46f10e89f10758b5f0ce91e1bff00847350ba7f320d5a2bf79dad9a2fdee4261724f978cee18ce7b57ae7c29d5b58d5346d6e3d6f526d42e6c3599ec96e1a258f7222a63e55e07249efd7ad7ab86a52a50e5933e073cc7d1c7e2556a316b449ded76f5d74bf4b2f91ded14515d078e7c0145145006ef82a259fc79e1d85c651f53b6561ec65515f54f883fe43973ff01ffd0457cb3e04ff009287e1affb0adaff00e8d5afa9bc41ff0021cb9ff80ffe822bbb2ffe2bf4ff0023e578bffdc61fe35f948cca28a2bd83f3839af16ffcb9ff00c0ff00f65ae6aba5f16ffcb9ff00c0ff00f65ae6abdcc1ff00063fd753fa73c3cff926f0dff6ff00fe9c905667883fe40773ff0001ff00d08569d667883fe40773ff0001ff00d08576d0fe2c7d51f4d9a7fb8d6ff04bf2670d451457d11f8d857d8b5f1d57d8b5f8778cff00f303ff00713ff719e9e5df6be5fa8514515f869e99c37883fe43973ff01ffd04566569f883fe43973ff01ffd0456657d150fe147d11f8de69fefd5bfc72fcd85735e2dff00973ff81ffecb5d2d735e2dff00973ff81ffecb5dd83fe347fae87d37879ff25261bfedff00fd3721ff000e7fe47ed2bfdf7ffd16d5e57e3bff009287e25ffb0add7fe8d6aeff00c3da55deb9aedae9b63aa4da5dcce484bc833be2c293918653c804751d6bcd3c4b67369fe2ad5ecae2ee4bc9edef668a4b9933ba665720b9c927248cf53d7ad7d9e5ff00c37ea7eafc61fefb0ff0afcd9d67c12ff92bda17fdbc7fe93c95ef3f083fe3cbc5dff6335e7f28ebe6ef877a3de6bde3bd374cb0d5a7d26ea6f3765ec19df16227638c329e4023a8eb5f447c0fb596cbc3de23b49ee5eea683c41731bdc3e774aca9182c724f248cf53d6bbcf933d3e8a28a00f8028a28a00d2f0f6a29a3f8974ad4e40e63b3bc86e18200588470c700f19e3bd7d69e20ff0090e5cffc07ff004115f1cd7d5b65ac7fc241a6586ac6485e4bab482494c272a24f2d77a8e4f46dc304e411835dd97ff15fa7f91f2bc5ff00ee30ff001afca44d451457b07e70735e2dff00973ff81ffecb5cd574be2dff00973ff81ffecb5cd57b983fe0c7faea7f4e7879ff0024de1bfedfff00d3920accf107fc80ee7fe03ffa10ad3accf107fc80ee7fe03ffa10aeda1fc58faa3e9b34ff0071adfe097e4ce1a8a28afa23f1b0afb16be3aafb16bf0ef19ffe607fee27fee33d3cbbed7cbf50a28a2bf0d3d3386f107fc872e7fe03ff00a08accad3f107fc872e7fe03ff00a08accafa2a1fc28fa23f1bcd3fdfab7f8e5f9b0ae6bc5bff2e7ff0003ff00d96ba5ae6bc5bff2e7ff0003ff00d96bbb07fc68ff005d0fa6f0f3fe4a4c37fdbfff00a6e43fe1cffc8fda57fbefff00a2dabcafc77ff250fc4bff00615baffd1ad5d6092e223bed2eee2d271f727b790a489f461c8f4fc6ba3b6f13d9456b0c775e11f0edfdc2a0596eeeec5649a7603992463cb3b1e493d4926beb30988a74a0d4bb9fb5f10e4d8bc7626352824d28db7b756721f04bfe4af685ff006f1ffa4f257bcfc21ff8f2f177fd8cf79fca3af359b5c4d55adb4dd2742d1741bebcba82da2d4f4cb4f26e2df7caaa4a3a90464120e0f2091debdb7c19e0fb6f05e9775656d7b7779f6abb7bb966bb60d233b2a839200cfddcf3ce49af4a9558d55cd13e331d80ad81a8a957566d5fbe9aff0091d1d14515a1c47c0383e9460fa1af5ab3c66b7ecfb578b5738e4fb1f8ff00c03ebeb70a7b3ff97dff0092ff00f6c78360fa57bcfc28bdf3fc1b15ab7deb677c71fc2ccc47ebbab7ecfb574167d4572478b1e1e6a4a95ffedeff00807cee71c2f4f17859d09d4d5dacedb34d6b6beba5d6eb7bf93868ae96d3eed1375aaff8885adbeadff93fff006a7c056e06f65ff3117ffb77ff00b63cd7c5bff2e7ff0003ff00d96b9aaf5e9ab3e6ef5ea61fc49e48287d57ff0027ff00ed0fb7c9388bfb072da780f67cfc97d6fcb7bc9cb6b3ef6dcf31accf107fc80ee7fe03ff00a10af5298d507fbd5df47c48f7d4beadb7f7ff00fb433cc3c49e7a13a3f55f89357e7eeadfc8781d15efcb532d7d1d0f11bdaffcc35bfedfff00ed0f837c4b6ff975ff00937fc03e7bc57d8b9ae112a64af9ee2c8ffad7ec3fe5d7b3e6fef5f9b97fc36b72f9ee6b438c7d85ff00737bff007bff00b53b5a2b8b9bfd5d61de7435f374bc36e7ff0098affc93ff00b73b6971b7b47fc0ff00c9bffb535fc41ff21cb9ff0080ff00e822b32b9bbcef58179d0d7d161fc37bc547eb3b7f73ff00b73c1a986fadd79d6bdb99b76ded777f23d0eb9af16ffcb9ff00c0ff00f65ae06f3bd67c7f78d7a987f0c7924aa7d6b6fee7ff006e7d370c617fb2f32a58fbf3725f4daf78b8efaf7bec7534562c3daafc3dabaa5c03cbff00311ff927ff006c7ecb438a3daffcbab7fdbdff0000f41f85566d3f8dedee39096e8e723a64a3003f224fe15efb5f29435a10f6ada9f0a2a10e5556ff00f6effc13cfc6e5f5335c4baf3a9cab4495af656daf757d6ef65bdba1f4ed15f33b542f5cb5f27f65f6eff2ff008242e13bff00cbeffc97ff00b633ad754d3d7ef5fda8faccbfe35b76bae690b8ddaa590fadc27f8d78a515f1d532884f79339eaf14d6a9bd35f7b3e87b4f12684b8ddad69c3eb749fe35d1586bda3c88244d5ac590f46170841fc735f2b5773e1fff00901db7fc0bff004235e4e3720a7087373b36ca6abcd7112a33f76cafa7aa5fa9f49e9dab69b73958350b594a8c90932b63eb83534d7501e93467fe042bc1b4ad4a5d2b508eea2e76f0c99c075ee0ff009eb8af52b1bd8351b38eeadd898dc77ea0f707de8cb7847098c4ef55a92e965b773e438e658ec86a4670a6a7467b4bb4bac5fe6bbebd99ab757d690e3cdba863ddd37c8067f3acc9752b039c5edb1ffb6abfe3581e2dff00973ff81ffecb5cd57d461bc39c2ce0a7ede5f723ab20e1ea79ee574b1f566e2e7cda25a2b49c7afa1dbcb7d667a5d407feda0aa13ea165129924bbb7441d59a4000fc735cbd667883fe40773ff0001ff00d08577d1f0eb0bcea3ede5abec8798787385850a95bdbcaf14decba2b9daaebba3ff00d056c7ff000213fc6a65d7f47ffa0b587fe04a7f8d785d15f4747c3bc352dab4bee47e7cf87293fb6cf795f1068a3fe62f61ff008129fe35bcb6775ff3ed37fdf06be68afb16be538d25feaafd5fd87ef3da736fa5b9797b7f88df0dc2142bdef51ab7923919acee8c7816d31ff801ac7bbd32fd81db65727e9137f857a3515f234fc46c5436a11fbd9dd4f82e8537a557f723c5efac6ed1ca3db4cae3aa94208fc2b02eb4fbd607167707e919ff000af4ef107fc872e7fe03ff00a08accafa2c3f88b8a5052f611d7cd9f2f5b10f09889d18aba8b6bee763ca6eb48d4db3b74ebb3f481bfc2b31b4cbfb761e7d95cc5bb38df132e7f315ed35cd78b7fe5cffe07ff00b2d7a987f12f1539a87b08ebe6cfa7e14c4bcd334a5819ae553e6d56fa45cbf43848ade61d6371f8569d9585e5ce7ecf693cdb71bbcb8cb633eb8ab36b6d35e5cc76f021796438503fcf4af53d274b8748b05b5889639dcee7f89bb9f6e95ef65fc578ac6c9de92515d6efee3ed78bb1984e17a3050973d69ed17a69d5bb74e8bbbf4679d5b689ab4b2048f4bbd773d156ddc93fa56ac5e1bd7475d17511ff006eaffe15ea3e1fff0090e5b7fc0bff004135dcd698bcfaa539f2a8239387b8cabe330eeb4a925676ddf64ff53e7a6f0e6b9ff405d47ff015ff00c2a26f0debbff404d4bff015ff00c2be8aa2bcaad9bceaef147d1ae2bacbfe5dafbd9f00514515e41f2815dcf87ffe4076dff02ffd08d14570e61fc25ebfe67d57087fbf4ffc0ff389a75b9e17d5a7d3f548add70f05cc8b1ba1ec49c061ee33f8fe4414579d85a92a75a3283b3b9f619f612862f2caf47111528b8bd1f92ba7ea9ea9f4674de2dff973ff0081ff00ecb5cd51457ec383fe0c7faea7c87879ff0024de1bfedfff00d3920accf107fc80ee7fe03ffa10a28aeda1fc58faa3e9b34ff71adfe097e4ce1a8a28afa23f1b0afb168a2bf0ef19ff00e607fee27fee33d3cbbed7cbf50a28a2bf0d3d3386f107fc872e7fe03ffa08acca28afa2a1fc28fa23f1bcd3fdfab7f8e5f9b0ae6bc5bff2e7ff0003ff00d968a2bbb07fc68ff5d0fa6f0f3fe4a4c37fdbff00fa6e474be17d1edf4fd362b95f9ee2e23576723a0201da3dbf9fe58dda28afd83094e34e84630565647c8e7f8caf8cccebd6c449ca5ccd5df64ec97a25b234fc3fff0021cb6ff817fe826bb9a28af3f30fe2af4ff33ebf843fdc67fe37f94428a28ae13ea8ffd90000001800530065007100750065006e0063006500540079007000650000000200000000010000000c0053006500710052006500660000000a000000004800330035006300370034006300340061002d0063003300610030002d0034006100370038002d0039003600310064002d003900350039003400640066003600380034003600300038000000300049007300520065006e006400650072004300610063006800650042004100560065007200730069006f006e006500640000000100010000002400460069007200730074004d00610069006e0042007500730046006f0072006d00610074000000020000000002</FieldsBlob>
33
+ <UniqueSequenceId>b84501d8-e67f-48a9-a6a2-dba874d6d8fd</UniqueSequenceId>
34
+ <MediaExtents>00000000000000000000000000003040</MediaExtents>
35
+ <FrameRate>00000000000038400000000000000000</FrameRate>
36
+ <Resolution>00000000000007800000000000000438</Resolution>
37
+ <VideoTrackVec/>
38
+ <AudioTrackVec/>
39
+ <Parent>033ee600-12a6-4f75-8232-b478aaa728a9</Parent>
40
+ <LastChangedTime>0</LastChangedTime>
41
+ <RenderCacheBA>00000024789c63666064000126b683360c3800001b02010a</RenderCacheBA>
42
+ <AuxRenderCacheBA>00000024789c63666064000126b683360c3800001b02010a</AuxRenderCacheBA>
43
+ <UIElementsState/>
44
+ <NumOutputAudioChannels>2</NumOutputAudioChannels>
45
+ <OutputAudioGain>0</OutputAudioGain>
46
+ <PinsBA/>
47
+ <ImportExportMetadataBA/>
48
+ <LockSysId/>
49
+ <DbSavedTime>20619279</DbSavedTime>
50
+ </Sm2Sequence>
51
+ </Sequence>
52
+ <VideoMetadata>0000000100000002000000100055006e0069007100750065004900640000000a000000004800340038003000640061003300660066002d0033006200370066002d0034006500340062002d0039006500380036002d0063003100620030003600310061003800650036003000610000000c0044006200540079007000650000000a000000001e004200740056006900640065006f004d0065007400610064006100740061</VideoMetadata>
53
+ <MediaMetadata/>
54
+ </Sm2MpCompoundClip>
55
+ </Element>
@@ -87,7 +87,7 @@ if not logging.getLogger().handlers:
87
87
  handlers=[logging.StreamHandler()],
88
88
  )
89
89
 
90
- VERSION = "2.129.0"
90
+ VERSION = "2.131.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()}")
package/src/server.py CHANGED
@@ -11,7 +11,7 @@ Usage:
11
11
  python src/server.py --full # Start the 353-tool granular server instead
12
12
  """
13
13
 
14
- VERSION = "2.129.0"
14
+ VERSION = "2.131.0"
15
15
 
16
16
  import base64
17
17
  import os