davinci-resolve-mcp 2.57.4 → 2.57.5
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 +31 -0
- package/README.md +1 -1
- package/docs/reference/api-limitations.md +38 -1
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +102 -5
- package/src/utils/api_truth.py +96 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
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.57.5
|
|
6
|
+
|
|
7
|
+
Fixes a silent data-loss bug on Reel Name writes (issue #77) and bundles the
|
|
8
|
+
community-contributed API-limitation entries from PR #76 (issue #75).
|
|
9
|
+
|
|
10
|
+
- **Fixed** (#77) `set_clip_property` / `set_metadata` reporting `success: true`
|
|
11
|
+
when writing the `Reel Name` clip property even though Resolve silently
|
|
12
|
+
dropped the value. Resolve gates `Reel Name` behind the project setting
|
|
13
|
+
*General Options > Assist using reel names from the:* — when that derives reel
|
|
14
|
+
names automatically, scripted writes are ignored but still return `True`. On a
|
|
15
|
+
batch ingest this meant hundreds of clips believed to have reel names assigned
|
|
16
|
+
when none actually stuck. The server now reads the value back after writing
|
|
17
|
+
known-unreliable keys and refuses to report success on mismatch, surfacing the
|
|
18
|
+
project-setting gate as a `hint`. Wired into `set_clip_property`,
|
|
19
|
+
`set_metadata` (both forms), and the bulk `normalize_metadata` path. Adds an
|
|
20
|
+
`api_truth` bug entry (report now lists 18 missing + 11 bugs) and 10 unit
|
|
21
|
+
tests.
|
|
22
|
+
- **Added** (PR #76, thanks @swayll) four `submit: missing` API-limitation
|
|
23
|
+
entries verified on Resolve 21.0.0: per-subtitle text/timing editing, subtitle
|
|
24
|
+
track styling/presets, speech-recognition engine selection + SRT import, and
|
|
25
|
+
Media Pool folder rename. These document the API ceiling behind the subtitle
|
|
26
|
+
feature request in #75 — direct subtitle text editing and SRT round-trip are
|
|
27
|
+
not exposed by the Blackmagic scripting API.
|
|
28
|
+
|
|
29
|
+
### Validation
|
|
30
|
+
|
|
31
|
+
- Offline: full unit suite green; new `tests/test_reel_name_writeback.py` (10
|
|
32
|
+
tests) plus the api_truth/limitations drift guards. Live Resolve validation of
|
|
33
|
+
the Reel Name read-back is recommended but not performed here — forcing the
|
|
34
|
+
gate would require writing reel names into a live project's media metadata.
|
|
35
|
+
|
|
5
36
|
## What's New in v2.57.4
|
|
6
37
|
|
|
7
38
|
Live mutating verification of the catalogued API gaps.
|
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)
|
|
@@ -12,7 +12,7 @@ that none exists).
|
|
|
12
12
|
|
|
13
13
|
**Verified on:** DaVinci Resolve Studio 21.0.0
|
|
14
14
|
|
|
15
|
-
**Totals:**
|
|
15
|
+
**Totals:** 18 missing capabilities, 11 bugs / unreliable behaviors.
|
|
16
16
|
|
|
17
17
|
The authoritative source is the runtime-queryable `api_truth` ledger
|
|
18
18
|
(`resolve_control api_truth "<query>"`); this document is generated from
|
|
@@ -141,6 +141,34 @@ equivalent, blocking full automation.
|
|
|
141
141
|
- **Workaround / current handling:** Create Smart/Power Bins in the Resolve UI; only regular bins are scriptable.
|
|
142
142
|
- **Tags:** missing-method, media-pool, bins
|
|
143
143
|
|
|
144
|
+
### Per-subtitle text content and timing editing
|
|
145
|
+
|
|
146
|
+
- **Object:** `TimelineItem (subtitle track)`
|
|
147
|
+
- **Behavior:** TimelineItem on a subtitle track exposes only 21 standard transform/composite properties (Pan, Tilt, ZoomX, Opacity, Crop, etc.). There are no methods to get or set subtitle text (GetText/SetText), start time, end time, or duration for individual subtitle items. Subtitles created via CreateSubtitlesFromAudio or imported via the Resolve UI cannot have their content or timing read or modified programmatically. Verified via dir() and GetProperty() on Resolve 21.0.0.48.
|
|
148
|
+
- **Workaround / current handling:** No workaround exists — subtitle text and timing are completely inaccessible from the scripting API. Must be edited in the Resolve UI.
|
|
149
|
+
- **Tags:** missing-method, subtitle, text, timing
|
|
150
|
+
|
|
151
|
+
### Subtitle track styling and presets
|
|
152
|
+
|
|
153
|
+
- **Object:** `TimelineItem / Timeline / Project`
|
|
154
|
+
- **Behavior:** There is no API method to set or query subtitle font family, font size, text color, background color, outline, shadow, position, alignment, or to apply/query subtitle style presets. TimelineItem.GetProperty() on subtitle items returns only transform/composite keys. Timeline.GetSetting() and Project.GetSetting() return None for all probed subtitle-style keys (e.g. 'subtitleFontName', 'subtitleFontSize', 'subtitleTextColor', 'subtitleBackgroundColor', 'subtitlePosition', 'subtitleAlignment', 'subtitlePreset', 'subtitleStyle'). Verified via dir(), GetProperty(), and GetSetting() on Resolve 21.0.0.48.
|
|
155
|
+
- **Workaround / current handling:** No workaround exists — subtitle styling is UI-only. Burn-in overlays via Fusion titles are a visual alternative but do not produce proper subtitle tracks.
|
|
156
|
+
- **Tags:** missing-method, subtitle, style, preset
|
|
157
|
+
|
|
158
|
+
### Speech recognition engine selection and SRT import
|
|
159
|
+
|
|
160
|
+
- **Object:** `Timeline`
|
|
161
|
+
- **Behavior:** Timeline.CreateSubtitlesFromAudio(autoCaptionSettings) always uses the built-in Resolve speech recognition engine. There is no API parameter to select an alternative provider (e.g. whisper-cli, Google Speech, AWS Transcribe). The language selection via resolve.AUTO_CAPTION_LANGUAGE_* is the only customization; the engine itself cannot be changed. Furthermore, there is no API method to import an SRT file into a subtitle track programmatically — File -> Import -> Subtitle is UI-only.
|
|
162
|
+
- **Workaround / current handling:** No workaround exists for provider selection or SRT import. External transcripts must be converted to SRT and imported through the Resolve UI.
|
|
163
|
+
- **Tags:** missing-method, subtitle, transcription, speech-recognition, asr
|
|
164
|
+
|
|
165
|
+
### Media Pool folder rename
|
|
166
|
+
|
|
167
|
+
- **Object:** `MediaPool`
|
|
168
|
+
- **Behavior:** MediaPool exposes AddSubFolder(name), DeleteSubFolders([names]), and MoveFolders([names], targetFolder) but no RenameSubFolder(oldName, newName) method. Folders can be created, deleted, and moved, but their names cannot be changed through the API. Verified via dir() on Resolve 21.0.0.
|
|
169
|
+
- **Workaround / current handling:** Delete and recreate the folder with the desired name, or rename in the Resolve UI.
|
|
170
|
+
- **Tags:** missing-method, media-pool, folder
|
|
171
|
+
|
|
144
172
|
## Bugs / Unreliable Behavior (please fix)
|
|
145
173
|
|
|
146
174
|
Methods that exist but misbehave — silent failures, unreliable return
|
|
@@ -220,3 +248,12 @@ values, or automation-hostile modal prompts.
|
|
|
220
248
|
- **Behavior:** The Python bridge returns a callable for ANY attribute name, so hasattr(obj, 'TotallyMadeUpMethod') is always True and getattr never raises. This makes capability detection by hasattr impossible — verified on 21.0.0 (hasattr reported SetStart, Razor, AddNode, GenerateProxy, AddSmartBin etc. as present though none exist). Only dir() lists the real methods.
|
|
221
249
|
- **Workaround / current handling:** Never probe method existence with hasattr/getattr; test membership against dir(obj) instead. Calling a fabricated method typically returns None/False with no error.
|
|
222
250
|
- **Tags:** bridge, introspection, silent-failure
|
|
251
|
+
|
|
252
|
+
### MediaPoolItem.SetClipProperty('Reel Name', ...)
|
|
253
|
+
|
|
254
|
+
- **Object:** `MediaPoolItem`
|
|
255
|
+
- **Signature:** `(propertyName, propertyValue) -> bool`
|
|
256
|
+
- **Behavior:** Setting the 'Reel Name' clip property returns True but the value is silently dropped on read-back when the project is configured to derive reel names automatically (General Options > 'Assist using reel names from the:' set to source clip file / embedding / filename pattern). The same True-but-unpersisted behavior occurs via SetMetadata('Reel Name', ...). Other clip properties on the same clip (e.g. 'Comments') write and persist normally, so this is field-specific, not a bridge/permission failure. Verified on Resolve 21.0.0; reported as issue #77.
|
|
257
|
+
- **Workaround / current handling:** After writing 'Reel Name', read it back with GetClipProperty('Reel Name') and refuse to report success on mismatch; surface the project-setting gate to the caller (server._verify_clip_property_writeback).
|
|
258
|
+
- **Reference:** [issue #77](https://github.com/samuelgursky/davinci-resolve-mcp/issues/77)
|
|
259
|
+
- **Tags:** unreliable-return, silent-failure, metadata, reel-name
|
package/install.py
CHANGED
|
@@ -35,7 +35,7 @@ from src.utils.update_check import (
|
|
|
35
35
|
|
|
36
36
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
37
37
|
|
|
38
|
-
VERSION = "2.57.
|
|
38
|
+
VERSION = "2.57.5"
|
|
39
39
|
# Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
|
|
40
40
|
# Resolve's scripting bridge loads into newer interpreters on recent builds
|
|
41
41
|
# (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
|
package/package.json
CHANGED
package/src/granular/common.py
CHANGED
|
@@ -80,7 +80,7 @@ if not logging.getLogger().handlers:
|
|
|
80
80
|
handlers=[logging.StreamHandler()],
|
|
81
81
|
)
|
|
82
82
|
|
|
83
|
-
VERSION = "2.57.
|
|
83
|
+
VERSION = "2.57.5"
|
|
84
84
|
logger = logging.getLogger("davinci-resolve-mcp")
|
|
85
85
|
logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
|
|
86
86
|
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 341-tool granular server instead
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
VERSION = "2.57.
|
|
14
|
+
VERSION = "2.57.5"
|
|
15
15
|
|
|
16
16
|
import base64
|
|
17
17
|
import os
|
|
@@ -6559,6 +6559,78 @@ def _safe_clip_call(clip, method_name: str, *args):
|
|
|
6559
6559
|
return None, str(exc)
|
|
6560
6560
|
|
|
6561
6561
|
|
|
6562
|
+
# Clip-property keys whose SetClipProperty/SetMetadata write returns True but is
|
|
6563
|
+
# silently dropped by Resolve under common project configurations (issue #77).
|
|
6564
|
+
# For these we read the value back and refuse to report success unless it stuck.
|
|
6565
|
+
_WRITEBACK_VERIFY_KEYS = frozenset({"Reel Name"})
|
|
6566
|
+
|
|
6567
|
+
# Per-key hint explaining the most common cause of a non-persisting write.
|
|
6568
|
+
_WRITEBACK_VERIFY_HINTS = {
|
|
6569
|
+
"Reel Name": (
|
|
6570
|
+
"Reel Name is commonly gated by the project setting "
|
|
6571
|
+
"'General Options > Assist using reel names from the:'. When that is "
|
|
6572
|
+
"set to derive reel names from the source clip / embedding / filename "
|
|
6573
|
+
"pattern, Resolve ignores scripted writes to 'Reel Name' (the call "
|
|
6574
|
+
"still returns True). Set that option to blank/manual, or assign reel "
|
|
6575
|
+
"names in the Resolve UI; the scripting API cannot override the gate."
|
|
6576
|
+
),
|
|
6577
|
+
}
|
|
6578
|
+
|
|
6579
|
+
|
|
6580
|
+
def _normalize_clip_property_value(value):
|
|
6581
|
+
"""Coerce a clip-property value to a comparable, trimmed string."""
|
|
6582
|
+
if value is None:
|
|
6583
|
+
return ""
|
|
6584
|
+
return str(value).strip()
|
|
6585
|
+
|
|
6586
|
+
|
|
6587
|
+
def _verify_clip_property_writeback(clip, key, value):
|
|
6588
|
+
"""Confirm a just-written, known-unreliable clip property actually persisted.
|
|
6589
|
+
|
|
6590
|
+
Returns a structured failure dict when Resolve accepted the write (returned
|
|
6591
|
+
True) but the value did not stick on read-back; returns ``None`` when the
|
|
6592
|
+
write verified, the key is not in the watch list, or we cannot read it back
|
|
6593
|
+
(in which case we don't override the original success). See issue #77.
|
|
6594
|
+
"""
|
|
6595
|
+
if key not in _WRITEBACK_VERIFY_KEYS:
|
|
6596
|
+
return None
|
|
6597
|
+
actual, err = _safe_clip_call(clip, "GetClipProperty", key)
|
|
6598
|
+
if err is not None:
|
|
6599
|
+
return None # can't read back — don't contradict the reported result
|
|
6600
|
+
if isinstance(actual, dict): # GetClipProperty('') style dict, just in case
|
|
6601
|
+
actual = actual.get(key)
|
|
6602
|
+
if _normalize_clip_property_value(actual) == _normalize_clip_property_value(value):
|
|
6603
|
+
return None
|
|
6604
|
+
return {
|
|
6605
|
+
"success": False,
|
|
6606
|
+
"verified": False,
|
|
6607
|
+
"key": key,
|
|
6608
|
+
"requested": value,
|
|
6609
|
+
"actual": actual,
|
|
6610
|
+
"error": (
|
|
6611
|
+
f"Resolve reported success writing {key!r} but the value did not "
|
|
6612
|
+
f"persist (read-back returned {actual!r})."
|
|
6613
|
+
),
|
|
6614
|
+
"hint": _WRITEBACK_VERIFY_HINTS.get(key),
|
|
6615
|
+
}
|
|
6616
|
+
|
|
6617
|
+
|
|
6618
|
+
def _verify_writeback(clip, written):
|
|
6619
|
+
"""Verify a batch of just-written {key: value} pairs.
|
|
6620
|
+
|
|
6621
|
+
Returns the first silent-revert failure dict, else ``None``. Only keys in
|
|
6622
|
+
``_WRITEBACK_VERIFY_KEYS`` are checked, so ordinary writes pay nothing.
|
|
6623
|
+
"""
|
|
6624
|
+
if not isinstance(written, dict):
|
|
6625
|
+
return None
|
|
6626
|
+
for key, value in written.items():
|
|
6627
|
+
if key in _WRITEBACK_VERIFY_KEYS:
|
|
6628
|
+
fail = _verify_clip_property_writeback(clip, key, value)
|
|
6629
|
+
if fail:
|
|
6630
|
+
return fail
|
|
6631
|
+
return None
|
|
6632
|
+
|
|
6633
|
+
|
|
6562
6634
|
def _media_pool_item_summary(clip):
|
|
6563
6635
|
if not clip:
|
|
6564
6636
|
return None
|
|
@@ -10213,7 +10285,17 @@ def _normalize_metadata(root, mp, p: Dict[str, Any]):
|
|
|
10213
10285
|
third_party_ok = True
|
|
10214
10286
|
for key, value in third_party.items():
|
|
10215
10287
|
third_party_ok = bool(clip.SetThirdPartyMetadata(key, value)) and third_party_ok
|
|
10216
|
-
|
|
10288
|
+
row = {"clip_id": clip_id, "success": ok and third_party_ok}
|
|
10289
|
+
if ok and metadata:
|
|
10290
|
+
silent = _verify_writeback(clip, metadata)
|
|
10291
|
+
if silent:
|
|
10292
|
+
row["success"] = False
|
|
10293
|
+
row["verified"] = False
|
|
10294
|
+
row["unpersisted"] = {silent["key"]: silent["actual"]}
|
|
10295
|
+
row["error"] = silent["error"]
|
|
10296
|
+
if silent.get("hint"):
|
|
10297
|
+
row["hint"] = silent["hint"]
|
|
10298
|
+
results.append(row)
|
|
10217
10299
|
return {"success": all(row.get("success") for row in results), "count": len(results), "missing": missing, "results": results}
|
|
10218
10300
|
|
|
10219
10301
|
|
|
@@ -15696,8 +15778,18 @@ def media_pool_item(action: str, params: Optional[Dict[str, Any]] = None) -> Dic
|
|
|
15696
15778
|
return {"metadata": _ser(clip.GetMetadata(p.get("key", "")))}
|
|
15697
15779
|
elif action == "set_metadata":
|
|
15698
15780
|
if "metadata" in p:
|
|
15699
|
-
|
|
15700
|
-
|
|
15781
|
+
ok = bool(clip.SetMetadata(p["metadata"]))
|
|
15782
|
+
if ok:
|
|
15783
|
+
silent = _verify_writeback(clip, p["metadata"])
|
|
15784
|
+
if silent:
|
|
15785
|
+
return silent
|
|
15786
|
+
return {"success": ok}
|
|
15787
|
+
ok = bool(clip.SetMetadata(p["key"], p["value"]))
|
|
15788
|
+
if ok:
|
|
15789
|
+
silent = _verify_clip_property_writeback(clip, p["key"], p["value"])
|
|
15790
|
+
if silent:
|
|
15791
|
+
return silent
|
|
15792
|
+
return {"success": ok}
|
|
15701
15793
|
elif action == "get_third_party_metadata":
|
|
15702
15794
|
return {"metadata": _ser(clip.GetThirdPartyMetadata(p.get("key", "")))}
|
|
15703
15795
|
elif action == "set_third_party_metadata":
|
|
@@ -15707,7 +15799,12 @@ def media_pool_item(action: str, params: Optional[Dict[str, Any]] = None) -> Dic
|
|
|
15707
15799
|
elif action == "get_clip_property":
|
|
15708
15800
|
return {"properties": _ser(clip.GetClipProperty(p.get("key", "")))}
|
|
15709
15801
|
elif action == "set_clip_property":
|
|
15710
|
-
|
|
15802
|
+
ok = bool(clip.SetClipProperty(p["key"], p["value"]))
|
|
15803
|
+
if ok:
|
|
15804
|
+
silent = _verify_clip_property_writeback(clip, p["key"], p["value"])
|
|
15805
|
+
if silent:
|
|
15806
|
+
return silent
|
|
15807
|
+
return {"success": ok}
|
|
15711
15808
|
elif action == "get_clip_color":
|
|
15712
15809
|
return {"color": clip.GetClipColor()}
|
|
15713
15810
|
elif action == "set_clip_color":
|
package/src/utils/api_truth.py
CHANGED
|
@@ -366,6 +366,79 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
366
366
|
"tags": ["missing-method", "media-pool", "bins"],
|
|
367
367
|
"submit": "missing",
|
|
368
368
|
},
|
|
369
|
+
{
|
|
370
|
+
"symbol": "Per-subtitle text content and timing editing",
|
|
371
|
+
"object": "TimelineItem (subtitle track)",
|
|
372
|
+
"reality": "TimelineItem on a subtitle track exposes only 21 standard "
|
|
373
|
+
"transform/composite properties (Pan, Tilt, ZoomX, Opacity, "
|
|
374
|
+
"Crop, etc.). There are no methods to get or set subtitle "
|
|
375
|
+
"text (GetText/SetText), start time, end time, or duration "
|
|
376
|
+
"for individual subtitle items. Subtitles created via "
|
|
377
|
+
"CreateSubtitlesFromAudio or imported via the Resolve UI "
|
|
378
|
+
"cannot have their content or timing read or modified "
|
|
379
|
+
"programmatically. Verified via dir() and GetProperty() on "
|
|
380
|
+
"Resolve 21.0.0.48.",
|
|
381
|
+
"recommended": "No workaround exists — subtitle text and timing are "
|
|
382
|
+
"completely inaccessible from the scripting API. Must "
|
|
383
|
+
"be edited in the Resolve UI.",
|
|
384
|
+
"tags": ["missing-method", "subtitle", "text", "timing"],
|
|
385
|
+
"submit": "missing",
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"symbol": "Subtitle track styling and presets",
|
|
389
|
+
"object": "TimelineItem / Timeline / Project",
|
|
390
|
+
"reality": "There is no API method to set or query subtitle font "
|
|
391
|
+
"family, font size, text color, background color, outline, "
|
|
392
|
+
"shadow, position, alignment, or to apply/query subtitle "
|
|
393
|
+
"style presets. TimelineItem.GetProperty() on subtitle "
|
|
394
|
+
"items returns only transform/composite keys. "
|
|
395
|
+
"Timeline.GetSetting() and Project.GetSetting() return "
|
|
396
|
+
"None for all probed subtitle-style keys (e.g. "
|
|
397
|
+
"'subtitleFontName', 'subtitleFontSize', "
|
|
398
|
+
"'subtitleTextColor', 'subtitleBackgroundColor', "
|
|
399
|
+
"'subtitlePosition', 'subtitleAlignment', "
|
|
400
|
+
"'subtitlePreset', 'subtitleStyle'). Verified via dir(), "
|
|
401
|
+
"GetProperty(), and GetSetting() on Resolve 21.0.0.48.",
|
|
402
|
+
"recommended": "No workaround exists — subtitle styling is UI-only. "
|
|
403
|
+
"Burn-in overlays via Fusion titles are a visual "
|
|
404
|
+
"alternative but do not produce proper subtitle tracks.",
|
|
405
|
+
"tags": ["missing-method", "subtitle", "style", "preset"],
|
|
406
|
+
"submit": "missing",
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"symbol": "Speech recognition engine selection and SRT import",
|
|
410
|
+
"object": "Timeline",
|
|
411
|
+
"reality": "Timeline.CreateSubtitlesFromAudio(autoCaptionSettings) "
|
|
412
|
+
"always uses the built-in Resolve speech recognition "
|
|
413
|
+
"engine. There is no API parameter to select an alternative "
|
|
414
|
+
"provider (e.g. whisper-cli, Google Speech, AWS Transcribe). "
|
|
415
|
+
"The language selection via resolve.AUTO_CAPTION_LANGUAGE_* "
|
|
416
|
+
"is the only customization; the engine itself cannot be "
|
|
417
|
+
"changed. Furthermore, there is no API method to import an "
|
|
418
|
+
"SRT file into a subtitle track programmatically — "
|
|
419
|
+
"File -> Import -> Subtitle is UI-only.",
|
|
420
|
+
"recommended": "No workaround exists for provider selection or SRT "
|
|
421
|
+
"import. External transcripts must be converted to SRT "
|
|
422
|
+
"and imported through the Resolve UI.",
|
|
423
|
+
"tags": ["missing-method", "subtitle", "transcription",
|
|
424
|
+
"speech-recognition", "asr"],
|
|
425
|
+
"submit": "missing",
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"symbol": "Media Pool folder rename",
|
|
429
|
+
"object": "MediaPool",
|
|
430
|
+
"reality": "MediaPool exposes AddSubFolder(name), "
|
|
431
|
+
"DeleteSubFolders([names]), and "
|
|
432
|
+
"MoveFolders([names], targetFolder) but no "
|
|
433
|
+
"RenameSubFolder(oldName, newName) method. Folders can be "
|
|
434
|
+
"created, deleted, and moved, but their names cannot be "
|
|
435
|
+
"changed through the API. Verified via dir() on Resolve "
|
|
436
|
+
"21.0.0.",
|
|
437
|
+
"recommended": "Delete and recreate the folder with the desired name, "
|
|
438
|
+
"or rename in the Resolve UI.",
|
|
439
|
+
"tags": ["missing-method", "media-pool", "folder"],
|
|
440
|
+
"submit": "missing",
|
|
441
|
+
},
|
|
369
442
|
{
|
|
370
443
|
"symbol": "hasattr() / getattr() on Resolve API objects (attribute fabrication)",
|
|
371
444
|
"object": "(all Resolve scripting objects)",
|
|
@@ -391,6 +464,29 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
391
464
|
"run while serving over stdio.",
|
|
392
465
|
"tags": ["runtime", "stdio", "subprocess"],
|
|
393
466
|
},
|
|
467
|
+
{
|
|
468
|
+
"symbol": "MediaPoolItem.SetClipProperty('Reel Name', ...)",
|
|
469
|
+
"object": "MediaPoolItem",
|
|
470
|
+
"signature": "(propertyName, propertyValue) -> bool",
|
|
471
|
+
"reality": "Setting the 'Reel Name' clip property returns True but the "
|
|
472
|
+
"value is silently dropped on read-back when the project is "
|
|
473
|
+
"configured to derive reel names automatically "
|
|
474
|
+
"(General Options > 'Assist using reel names from the:' set "
|
|
475
|
+
"to source clip file / embedding / filename pattern). The "
|
|
476
|
+
"same True-but-unpersisted behavior occurs via "
|
|
477
|
+
"SetMetadata('Reel Name', ...). Other clip properties on the "
|
|
478
|
+
"same clip (e.g. 'Comments') write and persist normally, so "
|
|
479
|
+
"this is field-specific, not a bridge/permission failure. "
|
|
480
|
+
"Verified on Resolve 21.0.0; reported as issue #77.",
|
|
481
|
+
"recommended": "After writing 'Reel Name', read it back with "
|
|
482
|
+
"GetClipProperty('Reel Name') and refuse to report "
|
|
483
|
+
"success on mismatch; surface the project-setting gate to "
|
|
484
|
+
"the caller (server._verify_clip_property_writeback).",
|
|
485
|
+
"tags": ["unreliable-return", "silent-failure", "metadata", "reel-name"],
|
|
486
|
+
"submit": "bug",
|
|
487
|
+
"issue": 77,
|
|
488
|
+
"mitigation": ["_verify_clip_property_writeback", "_verify_writeback"],
|
|
489
|
+
},
|
|
394
490
|
]
|
|
395
491
|
|
|
396
492
|
|