davinci-resolve-mcp 2.78.1 → 2.79.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 +88 -0
- package/README.md +2 -1
- package/docs/guides/conforming-an-avid-aaf.md +91 -0
- package/docs/reference/api-limitations.md +32 -8
- package/install.py +1 -1
- package/package.json +1 -1
- package/resolve-advanced/README.md +3 -1
- package/resolve-advanced/server/author-interchange.mjs +154 -16
- package/resolve-advanced/server/tools/editorial.mjs +5 -1
- package/resolve-advanced/vendor/conform-qc/packaging/emit-fcp7.js +155 -3
- package/resolve-advanced/vendor/conform-qc/packaging/index.js +5 -1
- package/resolve-advanced/vendor/conform-qc/test/packaging.test.js +152 -13
- package/src/granular/common.py +1 -1
- package/src/server.py +79 -3
- package/src/utils/api_truth.py +174 -7
package/src/utils/api_truth.py
CHANGED
|
@@ -181,7 +181,14 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
181
181
|
"five consecutive imports with no media duplicated. Use DRT "
|
|
182
182
|
"for one-shot hand-offs only. For OTIO, pass "
|
|
183
183
|
"importSourceClips=True with a sourceClipsPath. See "
|
|
184
|
-
"docs/guides/headless-edit-loop.md."
|
|
184
|
+
"docs/guides/headless-edit-loop.md. For a consolidated Avid "
|
|
185
|
+
"AAF specifically, do NOT expect this call (or Reconform "
|
|
186
|
+
"from Bins, or the UI's 'Link to source camera files') to "
|
|
187
|
+
"conform it to camera originals — all three were measured "
|
|
188
|
+
"against a real turnover and all three fail, the UI option "
|
|
189
|
+
"linking 878 of 882 items with only 144 correct while "
|
|
190
|
+
"rendering as a fully conformed timeline. See "
|
|
191
|
+
"docs/guides/conforming-an-avid-aaf.md.",
|
|
185
192
|
"tags": ["timeline", "import", "interchange", "silent-failure", "conform"],
|
|
186
193
|
"submit": "bug",
|
|
187
194
|
},
|
|
@@ -274,11 +281,119 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
274
281
|
"— naming nothing actionable — when the Media Pool's CURRENT "
|
|
275
282
|
"folder is not the folder holding the clips, even though every "
|
|
276
283
|
"clip_id passed is valid and resolvable. Reported against "
|
|
277
|
-
"Resolve Studio in PR #99."
|
|
284
|
+
"Resolve Studio in PR #99. "
|
|
285
|
+
"SEPARATELY, its clipInfo HAS NO TRACK FIELD: there is no way "
|
|
286
|
+
"to say which video or audio track a clip should land on, so "
|
|
287
|
+
"this call cannot build a multi-track timeline. The asymmetry "
|
|
288
|
+
"is the surprise — MediaPool.AppendToTimeline's clipInfo DOES "
|
|
289
|
+
"take `trackIndex`, so the two clipInfo shapes are not the same "
|
|
290
|
+
"shape, and code that works against one silently loses track "
|
|
291
|
+
"assignment against the other.",
|
|
278
292
|
"recommended": "Call MediaPool.SetCurrentFolder() to the clips' bin "
|
|
279
293
|
"before creating the timeline (media_pool "
|
|
280
|
-
"set_current_folder). Valid ids are not sufficient."
|
|
281
|
-
|
|
294
|
+
"set_current_folder). Valid ids are not sufficient. "
|
|
295
|
+
"For multi-track placement do not use this call at all: "
|
|
296
|
+
"create an EMPTY timeline (media_pool create_timeline), add "
|
|
297
|
+
"the tracks you need (timeline add_track), then place each "
|
|
298
|
+
"clip with MediaPool.AppendToTimeline passing clipInfo "
|
|
299
|
+
"`trackIndex` (media_pool append_to_timeline with "
|
|
300
|
+
"track_index).",
|
|
301
|
+
"tags": ["media-pool", "timeline", "unhelpful-error", "missing-method", "conform"],
|
|
302
|
+
"submit": "bug",
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"symbol": "MediaPool.AppendToTimeline (overlapping records — earlier item wins)",
|
|
306
|
+
"object": "MediaPool",
|
|
307
|
+
"signature": "([{mediaPoolItem, startFrame, endFrame, recordFrame, "
|
|
308
|
+
"trackIndex, mediaType}]) -> [TimelineItem]",
|
|
309
|
+
"reality": "AppendToTimeline does NOT overwrite an overlapping record. "
|
|
310
|
+
"When two clipInfos resolve to record ranges that overlap on "
|
|
311
|
+
"the same track, the EARLIER item wins and the later append is "
|
|
312
|
+
"dropped — measured while placing a real turnover. There is no "
|
|
313
|
+
"overwrite edit mode to reach for either: AppendToTimeline is "
|
|
314
|
+
"the only programmatic placement the API offers, so a consumer "
|
|
315
|
+
"that assumes overwrite semantics gets a timeline that is "
|
|
316
|
+
"silently SHORT by the number of colliding events, with no "
|
|
317
|
+
"error to say which ones lost.",
|
|
318
|
+
"recommended": "Resolve collisions BEFORE appending — the API will not do "
|
|
319
|
+
"it for you. Cap each event's placed duration at the next "
|
|
320
|
+
"event's recordFrame on the same track, or place the "
|
|
321
|
+
"colliding events on separate tracks. Verify by comparing "
|
|
322
|
+
"the timeline's item count against the number of clipInfos "
|
|
323
|
+
"you sent, per track, and finish with detect_gaps_overlaps; "
|
|
324
|
+
"a count that matches is the only evidence nothing was "
|
|
325
|
+
"dropped.",
|
|
326
|
+
"tags": ["timeline", "edit", "silent-failure", "conform", "media-pool"],
|
|
327
|
+
"submit": "bug",
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"symbol": "MediaPool.AppendToTimeline (errored-chunk placements are not durable across a save)",
|
|
331
|
+
"object": "MediaPool",
|
|
332
|
+
"signature": "([clipInfos]) -> [TimelineItem]",
|
|
333
|
+
"reality": "Placements made by an append call whose response ERRORED are "
|
|
334
|
+
"not durable: they appear in the timeline, every in-session "
|
|
335
|
+
"read agrees they are there, and THE SAVE DISCARDS THEM. "
|
|
336
|
+
"Measured on a real turnover — a timeline verified at 573 items "
|
|
337
|
+
"immediately after construction held 500 after the save, a loss "
|
|
338
|
+
"of exactly one errored append chunk's worth. The API reported "
|
|
339
|
+
"the failure, the items appeared anyway, and nothing between "
|
|
340
|
+
"construction and the save disagreed with the wrong number. "
|
|
341
|
+
"This is the dangerous shape: the witness is derived from the "
|
|
342
|
+
"same unsaved state as the thing it is checking, so it cannot "
|
|
343
|
+
"contradict it. Only a POST-SAVE read can.",
|
|
344
|
+
"recommended": "Treat the save as the verification boundary, not the end "
|
|
345
|
+
"of the job. Save, RE-READ the timeline's item count from "
|
|
346
|
+
"the saved project, and re-append whatever is missing "
|
|
347
|
+
"(bounded — two rounds is enough in practice); only then "
|
|
348
|
+
"report success. A timeline that is still short after that, "
|
|
349
|
+
"or that will not save, is a FAILURE — report it as one "
|
|
350
|
+
"rather than returning the in-session count. Never claim a "
|
|
351
|
+
"construction succeeded on a pre-save read alone, and treat "
|
|
352
|
+
"any errored append chunk as suspect even when its items "
|
|
353
|
+
"are visibly present.",
|
|
354
|
+
"tags": ["timeline", "edit", "silent-failure", "data-loss", "conform",
|
|
355
|
+
"unreliable-return", "media-pool"],
|
|
356
|
+
"submit": "bug",
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"symbol": "MediaPool.ImportTimelineFromFile (.otio document shape)",
|
|
360
|
+
"object": "MediaPool",
|
|
361
|
+
"signature": "(filePath, {importOptions}) -> Timeline",
|
|
362
|
+
"reality": "Resolve DOES import OTIO through the scripting API — but only "
|
|
363
|
+
"a Resolve-shaped document, and it rejects anything else by "
|
|
364
|
+
"creating NO timeline and returning None, with no error naming "
|
|
365
|
+
"a cause. Established on 19.1.3.7 by exporting a timeline with "
|
|
366
|
+
"Timeline.Export(..., EXPORT_OTIO) and feeding Resolve's own "
|
|
367
|
+
"file straight back: it re-imports cleanly (3 items, 3 linked), "
|
|
368
|
+
"while a valid hand-authored OTIO of the same cut, same project, "
|
|
369
|
+
"same session, same three online media files, produced nothing. "
|
|
370
|
+
"So a refusal is a SHAPE problem, not a media problem. "
|
|
371
|
+
"The requirement that actually decides it is the SOURCE FRAME "
|
|
372
|
+
"ORIGIN: a clip's source_range must be expressed against the "
|
|
373
|
+
"media's own timecode range. Media carrying an embedded start "
|
|
374
|
+
"TC of 01:00:00:00 gets an available_range starting at frame "
|
|
375
|
+
"86400, and the clip's source_range must start there too — "
|
|
376
|
+
"0-based source offsets, the natural reading of 'source in "
|
|
377
|
+
"point', put the clip outside the media's real range and the "
|
|
378
|
+
"import dies. Isolated by bisection: 0-based fails and absolute "
|
|
379
|
+
"succeeds whether or not the stack/track source_range is null. "
|
|
380
|
+
"Resolve also writes (and expects) Clip.2 with a "
|
|
381
|
+
"`media_references` MAP plus `active_media_reference_key`, not "
|
|
382
|
+
"Clip.1 with a singular `media_reference`; an `available_range` "
|
|
383
|
+
"on each reference; a BARE path in `target_url`, not a file:// "
|
|
384
|
+
"URL; `enabled` and `metadata` throughout; `global_start_time`; "
|
|
385
|
+
"and track names in its own form ('Video 1').",
|
|
386
|
+
"recommended": "Author OTIO for Resolve by mirroring what Resolve itself "
|
|
387
|
+
"exports, and give every event its media timecode origin. "
|
|
388
|
+
"editorial.convert_to_interchange (target 'otio') does this "
|
|
389
|
+
"and reports any event whose origin had to be assumed in "
|
|
390
|
+
"`mediaOriginAssumed` — a non-empty list means the file will "
|
|
391
|
+
"only import if that media really starts at 00:00:00:00. To "
|
|
392
|
+
"debug a refusal, export any timeline with EXPORT_OTIO and "
|
|
393
|
+
"diff your document against it; do NOT chase missing media "
|
|
394
|
+
"or reach for sanitize_media, which cannot even parse a "
|
|
395
|
+
".otio (it is JSON, not XML).",
|
|
396
|
+
"tags": ["timeline", "import", "interchange", "otio", "silent-failure", "conform"],
|
|
282
397
|
"submit": "bug",
|
|
283
398
|
},
|
|
284
399
|
{
|
|
@@ -554,10 +669,62 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
554
669
|
"against the documented SetProperty key list AND by live "
|
|
555
670
|
"mutating attempt on 21.0.0: SetProperty('Speed'|'PlaybackSpeed'"
|
|
556
671
|
"|'RetimeSpeed'|'ClipSpeed', 50) all return False, while "
|
|
557
|
-
"SetProperty('RetimeProcess', 1) returns True."
|
|
672
|
+
"SetProperty('RetimeProcess', 1) returns True. "
|
|
673
|
+
"THE READ SIDE IS AS DEAD AS THE WRITE SIDE, which is easy to "
|
|
674
|
+
"miss: re-measured on Studio 19.1.3.7 against a placed item, "
|
|
675
|
+
"GetProperty('Speed'), GetProperty('PlaybackSpeed'), "
|
|
676
|
+
"GetProperty('RetimeSpeed') and GetProperty('ClipSpeed') ALL "
|
|
677
|
+
"return None, and the keyless GetProperty() dict (26 keys on "
|
|
678
|
+
"that item) carries no speed value at all — its only retime key "
|
|
679
|
+
"is RetimeProcess, which is quality, not ratio. SetProperty("
|
|
680
|
+
"'Speed', 1.75) returned False on 19.1.3.7 too, so the write "
|
|
681
|
+
"refusal is not specific to 21.0.0. Note the 21.0.0 stamp above "
|
|
682
|
+
"covers the SetProperty measurements only. "
|
|
683
|
+
"THE INTERCHANGE ROUTE IS ALSO CLOSED — carrying a retime in "
|
|
684
|
+
"through FCP7 XML does not work either, measured on 19.1.3 with "
|
|
685
|
+
"three real files, clips at 100/200/50% on V1, each variant "
|
|
686
|
+
"imported as its own timeline: (a) the importer IGNORES the "
|
|
687
|
+
"scalar Time Remap speed filter and the clips arrive at 100%; "
|
|
688
|
+
"(b) `graphdict` is dead in FOUR separate shapes — the full "
|
|
689
|
+
"Premiere form (variablespeed=0 + speed + reverse=FALSE + "
|
|
690
|
+
"frameblending + 4-keyframe graphdict + FCPCurve), graphdict "
|
|
691
|
+
"alone with no <speed> param, a 100% REVERSE (reverse=TRUE plus "
|
|
692
|
+
"a descending graphdict, the exact shape a real Premiere export "
|
|
693
|
+
"carries), and variablespeed=1 + graphdict — 0 of 2 retimes "
|
|
694
|
+
"landed in every one; (c) `reverse` did not survive either; "
|
|
695
|
+
"(d) any <in>/<pproTicksIn> inconsistency is silently REJECTED, "
|
|
696
|
+
"measured in BOTH orientations. The emitted maps were verified "
|
|
697
|
+
"constant-slope against real Premiere exports before importing, "
|
|
698
|
+
"and every imported clip came back consuming exactly its record "
|
|
699
|
+
"span of source (a 200% clip emitted in 200 / out 296 was "
|
|
700
|
+
"clamped to out 248 — 48 source frames over a 48-frame record "
|
|
701
|
+
"span). Placement is NOT the problem: the same route imported "
|
|
702
|
+
"573 clips with 572 of 573 matching by track and record position "
|
|
703
|
+
"with source frames exact, and the importer BUILT a 59-frame "
|
|
704
|
+
"dissolve. The retime gap is specific, not general. "
|
|
705
|
+
"TRAP: Resolve's own FCP7 export cannot witness a speed. It "
|
|
706
|
+
"writes a DEGENERATE Time Remap on every clip — `speed` value 0 "
|
|
707
|
+
"(not 100) and a graphdict whose keyframe `value`s are all 0 "
|
|
708
|
+
"while its `when`s carry the clip's source in/out — so anyone "
|
|
709
|
+
"verifying a retime by round-tripping through EXPORT_FCP_7_XML "
|
|
710
|
+
"is reading furniture, and the identity Time Remap blocks "
|
|
711
|
+
"present on every clip are what make the route look like it "
|
|
712
|
+
"should work.",
|
|
558
713
|
"recommended": "Set clip speed/retime in the Resolve UI; no scripted "
|
|
559
|
-
"equivalent exists
|
|
560
|
-
|
|
714
|
+
"equivalent exists, and no interchange route carries one "
|
|
715
|
+
"in. Do NOT read speed back with GetProperty (None) or "
|
|
716
|
+
"witness it via EXPORT_FCP_7_XML (degenerate). Read the "
|
|
717
|
+
"clip's GEOMETRY instead — GetLeftOffset / GetRightOffset, "
|
|
718
|
+
"which on the 200% clip read 200 / 248 and agreed with the "
|
|
719
|
+
"export's in/out. Caveat worth stating: no positive control "
|
|
720
|
+
"has been run — no clip KNOWN to be retimed has been read "
|
|
721
|
+
"back through those two witnesses, because there is no "
|
|
722
|
+
"scripting path to create one. So the geometry witness is "
|
|
723
|
+
"the best available, not a proven one. Either way the "
|
|
724
|
+
"interchange route is rejected: no retime was built, and "
|
|
725
|
+
"none could have been verified.",
|
|
726
|
+
"tags": ["missing-method", "timeline", "retime", "speed", "interchange",
|
|
727
|
+
"silent-failure", "unreliable-return"],
|
|
561
728
|
"submit": "missing",
|
|
562
729
|
},
|
|
563
730
|
{
|