davinci-resolve-mcp 2.213.1 → 2.213.2
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 +50 -0
- package/README.md +1 -1
- package/README.zh-CN.md +2 -2
- package/docs/SKILL.md +6 -2
- package/docs/reference/api-limitations.md +8 -1
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +98 -16
- package/src/utils/api_truth.py +25 -0
- package/src/utils/resolve_versions.py +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
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.213.2 — the full transcript on 21.1, and a frame capture that puts the user's mark range back in the right frame space
|
|
6
|
+
|
|
7
|
+
Both contributed by @billcarroll (#199, #200).
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`media_pool_item get_transcription` reads the whole transcript on Resolve
|
|
12
|
+
21.1+** through `MediaPoolItem.GetTranscription`, which 21.1 added and which
|
|
13
|
+
does not truncate: `segments` carries `{start, end, text, speaker}` in
|
|
14
|
+
**source** timecode, `language` is reported, and `truncated` is False. Pass
|
|
15
|
+
`include_words` to keep each segment's per-word timings, which are several
|
|
16
|
+
times the bulk of the text. On 21.0.x it falls back to the `Transcription`
|
|
17
|
+
clip property exactly as before, and `source` says which route ran. The
|
|
18
|
+
method is registered in the version ledger as a reported 21.1 surface, so
|
|
19
|
+
`check_version_support` answers for it. (#199)
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **`timeline_frame capture` flattened a user's mark range to the whole
|
|
24
|
+
timeline.** Rendering one frame pins the project's render range to that
|
|
25
|
+
frame, and the cleanup could only reset it to the whole timeline because
|
|
26
|
+
there is no `GetRenderSettings` to read the previous range from. The mark
|
|
27
|
+
range is the exception: `Timeline.GetMarkInOut` can be read before the
|
|
28
|
+
capture, and the user's own range now goes back afterwards. A half-set range
|
|
29
|
+
(in point only) is still treated as no range, and with no marks set the old
|
|
30
|
+
whole-timeline fallback applies. (#200)
|
|
31
|
+
- **Adapted on landing: the two calls do not share a frame space.** Resolve
|
|
32
|
+
documents `GetMarkInOut` relative to the timeline start (its own example is
|
|
33
|
+
`in: 0, out: 134`), while `SetRenderSettings` takes absolute record frames —
|
|
34
|
+
measured on Studio 19.1.3.7: on an 86400-start timeline `MarkIn=MarkOut=86420`
|
|
35
|
+
rendered frame 20 and `MarkIn=MarkOut=20` was silently clamped to the start
|
|
36
|
+
and rendered frame 0, one frame, no error. Handed back verbatim, a UI-set
|
|
37
|
+
range would have been "restored" as a clamped range with every readback
|
|
38
|
+
agreeing. A mark below the timeline start is now offset by the start frame;
|
|
39
|
+
one at or above it was written absolute (`SetMarkInOut` stores whatever it
|
|
40
|
+
is given) and is kept. A unit test covers the relative case alongside the
|
|
41
|
+
PR's absolute, half-set and unreadable cases.
|
|
42
|
+
- **The clamp is now in the API ledger** as a measured bug, with the
|
|
43
|
+
relative-vs-absolute trap and the remedy, and
|
|
44
|
+
`docs/reference/api-limitations.md` is regenerated.
|
|
45
|
+
|
|
46
|
+
### Validation
|
|
47
|
+
|
|
48
|
+
- Both PRs' unit tests plus the relative-range test. Mark-range frame space
|
|
49
|
+
measured live on Studio 19.1.3.7 by rendering single frames under both
|
|
50
|
+
interpretations and matching each against the source frames. The 21.1
|
|
51
|
+
transcript route cannot be exercised here (no 21.1 build); its ledger entry
|
|
52
|
+
and `api_truth` say so. Full offline Python suite, drift guards and the
|
|
53
|
+
advanced Node suite green.
|
|
54
|
+
|
|
5
55
|
## What's New in v2.213.1 — Fusion keyframes reach the render; the contact sheet waits for the viewer; the ledger learns Resolve 21.1
|
|
6
56
|
|
|
7
57
|
Reported in #196 by @JosephConroy93, with a repro precise enough to reproduce
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
-
[](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
|
|
6
6
|
[](https://www.npmjs.com/package/davinci-resolve-mcp)
|
|
7
7
|
[](docs/reference/api-coverage.md)
|
|
8
8
|
[-blue.svg)](#server-modes)
|
package/README.zh-CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 简体中文
|
|
4
4
|
|
|
5
|
-
[](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
|
|
6
6
|
[](https://www.npmjs.com/package/davinci-resolve-mcp)
|
|
7
7
|
[](docs/reference/api-coverage.md)
|
|
8
8
|
[-blue.svg)](#服务器模式)
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
[](https://www.python.org/downloads/)
|
|
13
13
|
[](https://opensource.org/licenses/MIT)
|
|
14
14
|
|
|
15
|
-
> 本翻译对应 v2.213.
|
|
15
|
+
> 本翻译对应 v2.213.2 版 README。如与英文原版有出入,以 [英文原版](README.md) 为准。
|
|
16
16
|
|
|
17
17
|
一个 Model Context Protocol (MCP) 服务器,让 AI 助手通过官方脚本 API 控制 DaVinci Resolve Studio(达芬奇)。它提供完整的 API 覆盖,外加带护栏的工作流助手,涵盖剪辑、媒体池整理、渲染设置、审阅标记、调色、Fusion、Fairlight、项目生命周期任务、扩展开发,以及不碰源媒体的媒体分析。
|
|
18
18
|
|
package/docs/SKILL.md
CHANGED
|
@@ -909,8 +909,12 @@ Key actions: `get_name`, `get_metadata(key?)`, `set_metadata(key, value)`,
|
|
|
909
909
|
`set_name(name)`, `link_full_resolution_media(path)`,
|
|
910
910
|
`replace_clip_preserve_sub_clip(path)`, `monitor_growing_file`,
|
|
911
911
|
`transcribe_audio(use_speaker_detection?)`, `clear_transcription`,
|
|
912
|
-
`get_transcription` (read back
|
|
913
|
-
`
|
|
912
|
+
`get_transcription(include_words?, use_nested_clip_transcription?)` (read back
|
|
913
|
+
`{text, segments, language, source, truncated, status, has_transcription}`; on
|
|
914
|
+
Resolve 21.1+ it uses `MediaPoolItem.GetTranscription`, so `segments` carries
|
|
915
|
+
`{start, end, text, speaker}` in SOURCE timecode and nothing is truncated, and
|
|
916
|
+
on 21.0.x it falls back to the `Transcription` clip property, where `truncated`
|
|
917
|
+
flags a cut-off preview — `source` says which route ran),
|
|
914
918
|
`perform_audio_classification`,
|
|
915
919
|
`analyze_for_intellisearch(identify_faces?, is_better_mode?)`, `analyze_for_slate(marker_color?)`,
|
|
916
920
|
`remove_motion_blur(deblur_option?)` (Resolve 21+; AI Extras / confirm-token gated as noted above),
|
|
@@ -12,7 +12,7 @@ that none exists).
|
|
|
12
12
|
|
|
13
13
|
**Verified on:** DaVinci Resolve Studio 21.0.2
|
|
14
14
|
|
|
15
|
-
**Totals:** 41 missing capabilities,
|
|
15
|
+
**Totals:** 41 missing capabilities, 51 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
|
|
@@ -541,6 +541,13 @@ values, or automation-hostile modal prompts.
|
|
|
541
541
|
- **Workaround / current handling:** Detect the edition BEFORE calling Studio-gated features rather than discovering the gate by tripping it: the product name is 'DaVinci Resolve' on free and 'DaVinci Resolve Studio' on Studio (resolve_control get_version reports it). If a Studio-only call has already returned False on a free build, treat every following failure as suspect: re-run a known-good read, and if that fails too, a modal is blocking and only a human can dismiss it — no API closes it. Known Studio-gated so far: subtitle generation from audio, and audio transcription.
|
|
542
542
|
- **Tags:** free-edition, studio-only, silent-failure, modal, ai, subtitle, transcription
|
|
543
543
|
|
|
544
|
+
### SetRenderSettings MarkIn/MarkOut below the timeline start are clamped, not refused
|
|
545
|
+
|
|
546
|
+
- **Object:** `Project / Timeline`
|
|
547
|
+
- **Behavior:** SetRenderSettings takes MarkIn/MarkOut as ABSOLUTE record frames, and a value below the timeline's start frame is silently clamped to the start: measured on Studio 19.1.3.7 (2026-09-08) on an 86400-start timeline, MarkIn=MarkOut=86420 rendered timeline frame 20 and MarkIn=MarkOut=20 rendered frame 0 — one frame, True from SetRenderSettings, no error anywhere. The trap is that Timeline.GetMarkInOut reports the user's marks RELATIVE to the timeline start (Blackmagic's own README example is {'in': 0, 'out': 134}; the 21.1 stub says 'record frame relative to timeline start'), so feeding its output straight into SetRenderSettings renders the wrong range with every readback agreeing. SetMarkInOut itself stores whatever number it is given (10 reads back 10, 86410 reads back 86410), so a script-written range can be in either space.
|
|
548
|
+
- **Workaround / current handling:** Offset GetMarkInOut values by Timeline.GetStartFrame() before passing them to SetRenderSettings when they fall below the start frame (timeline_frame capture does this when it puts a user's range back). Verify a render range from the delivered frames, never from the settings call's return.
|
|
549
|
+
- **Tags:** render, silent-failure, frame-space, mark-range
|
|
550
|
+
|
|
544
551
|
### SetRenderSettings ExportSubtitle / SubtitleFormat had no observable effect
|
|
545
552
|
|
|
546
553
|
- **Object:** `Project (render settings)`
|
package/install.py
CHANGED
|
@@ -37,7 +37,7 @@ from src.utils.update_check import (
|
|
|
37
37
|
|
|
38
38
|
# ─── Version ──────────────────────────────────────────────────────────────────
|
|
39
39
|
|
|
40
|
-
VERSION = "2.213.
|
|
40
|
+
VERSION = "2.213.2"
|
|
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
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.213.
|
|
90
|
+
VERSION = "2.213.2"
|
|
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.213.
|
|
14
|
+
VERSION = "2.213.2"
|
|
15
15
|
|
|
16
16
|
import base64
|
|
17
17
|
import os
|
|
@@ -14934,6 +14934,40 @@ def _playhead_frame_render(proj, tl, p: Dict[str, Any]):
|
|
|
14934
14934
|
original_tc = tl.GetCurrentTimecode()
|
|
14935
14935
|
except Exception:
|
|
14936
14936
|
pass
|
|
14937
|
+
# The capture pins the render range to the captured frame, and there is no
|
|
14938
|
+
# GetRenderSettings to read the surrounding settings back from (still absent
|
|
14939
|
+
# in 21.1). The mark range is the exception: Timeline.GetMarkInOut reports it
|
|
14940
|
+
# in the same record-frame space SetRenderSettings takes, so a range the user
|
|
14941
|
+
# set can be captured here and put back below instead of being flattened to
|
|
14942
|
+
# the whole timeline.
|
|
14943
|
+
original_marks = None
|
|
14944
|
+
try:
|
|
14945
|
+
marks = (tl.GetMarkInOut() or {}).get("video") or {}
|
|
14946
|
+
if "in" in marks and "out" in marks:
|
|
14947
|
+
original_marks = marks
|
|
14948
|
+
except Exception:
|
|
14949
|
+
pass
|
|
14950
|
+
# GetMarkInOut reports marks RELATIVE to the timeline start (Blackmagic's
|
|
14951
|
+
# own example is {'in': 0, 'out': 134}; the 21.1 stub says "record frame
|
|
14952
|
+
# relative to timeline start"), while SetRenderSettings MarkIn/MarkOut are
|
|
14953
|
+
# ABSOLUTE record frames — measured on Studio 19.1.3.7: on an 86400-start
|
|
14954
|
+
# timeline MarkIn=MarkOut=86420 rendered frame 20, and MarkIn=MarkOut=20 was
|
|
14955
|
+
# silently clamped to the start and rendered frame 0, one frame, no error.
|
|
14956
|
+
# Handing a relative range straight back would "restore" a clamped range
|
|
14957
|
+
# with no signal. A mark below the timeline start is therefore relative and
|
|
14958
|
+
# is offset; one at or above it was written absolute (SetMarkInOut stores
|
|
14959
|
+
# whatever it is given) and is kept as-is.
|
|
14960
|
+
if original_marks:
|
|
14961
|
+
try:
|
|
14962
|
+
tl_start = int(round(float(tl.GetStartFrame())))
|
|
14963
|
+
original_marks = {
|
|
14964
|
+
key: (int(original_marks[key]) + tl_start
|
|
14965
|
+
if int(original_marks[key]) < tl_start
|
|
14966
|
+
else int(original_marks[key]))
|
|
14967
|
+
for key in ("in", "out")
|
|
14968
|
+
}
|
|
14969
|
+
except Exception:
|
|
14970
|
+
original_marks = None
|
|
14937
14971
|
|
|
14938
14972
|
job = None
|
|
14939
14973
|
try:
|
|
@@ -15027,16 +15061,28 @@ def _playhead_frame_render(proj, tl, p: Dict[str, Any]):
|
|
|
15027
15061
|
original_fc.get("format"), original_fc.get("codec"),
|
|
15028
15062
|
restore_exc or "SetCurrentRenderFormatAndCodec returned False",
|
|
15029
15063
|
)
|
|
15030
|
-
#
|
|
15031
|
-
#
|
|
15032
|
-
#
|
|
15064
|
+
# Still not a full restore — GetRenderSettings does not exist, so the
|
|
15065
|
+
# other settings cannot be read back. The mark range can: put the user's
|
|
15066
|
+
# own range back when they had one, and fall back to the whole timeline
|
|
15067
|
+
# when they did not, so the range is never left pinned to the captured
|
|
15068
|
+
# frame for the next render job to inherit.
|
|
15069
|
+
# (original_marks is already in SetRenderSettings' absolute space — see
|
|
15070
|
+
# the offset above.)
|
|
15033
15071
|
try:
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15072
|
+
if original_marks:
|
|
15073
|
+
restored_marks = {
|
|
15074
|
+
"SelectAllFrames": False,
|
|
15075
|
+
"MarkIn": original_marks["in"],
|
|
15076
|
+
"MarkOut": original_marks["out"],
|
|
15077
|
+
}
|
|
15078
|
+
else:
|
|
15079
|
+
restored_marks = {
|
|
15080
|
+
"SelectAllFrames": True,
|
|
15081
|
+
"MarkIn": tl.GetStartFrame(),
|
|
15082
|
+
"MarkOut": tl.GetEndFrame(),
|
|
15083
|
+
}
|
|
15084
|
+
restored_marks["CustomName"] = ""
|
|
15085
|
+
proj.SetRenderSettings(restored_marks)
|
|
15040
15086
|
except Exception:
|
|
15041
15087
|
pass
|
|
15042
15088
|
try:
|
|
@@ -21312,11 +21358,15 @@ def media_pool_item(action: str, params: Optional[Dict[str, Any]] = None) -> Dic
|
|
|
21312
21358
|
get_unique_id(clip_id) -> {id}
|
|
21313
21359
|
transcribe_audio(clip_id, use_speaker_detection?, background?) -> {success | job_id} — use_speaker_detection is Resolve 21+; background=true returns a job_id (poll resolve_control job_status)
|
|
21314
21360
|
clear_transcription(clip_id) -> {success}
|
|
21315
|
-
get_transcription(clip_id) -> {text, truncated, status, has_transcription}
|
|
21316
|
-
Read a clip's transcription.
|
|
21317
|
-
|
|
21318
|
-
|
|
21319
|
-
|
|
21361
|
+
get_transcription(clip_id, include_words?, use_nested_clip_transcription?) -> {text, segments, language, source, truncated, status, has_transcription}
|
|
21362
|
+
Read a clip's transcription. On Resolve 21.1+ this uses
|
|
21363
|
+
MediaPoolItem.GetTranscription, which does not truncate: `segments`
|
|
21364
|
+
carries {start, end, text, speaker} in SOURCE timecode and `truncated`
|
|
21365
|
+
is False. Pass include_words=true to keep each segment's per-word
|
|
21366
|
+
timings. On 21.0.x it falls back to the `Transcription` clip property,
|
|
21367
|
+
`segments` is null, and `truncated` flags a cut-off preview; `source`
|
|
21368
|
+
says which route ran. Clip-level and separate from the timeline subtitle
|
|
21369
|
+
transcript (timeline.get_transcript) that propose_cuts uses.
|
|
21320
21370
|
extract_frames(clip_id, timestamps, output_dir?) -> {frame_paths, output_dir, count, errors}
|
|
21321
21371
|
Extract still JPEGs from the clip's source at the given timestamps (seconds)
|
|
21322
21372
|
via ffmpeg. Source-safe: reads source, writes only to a scratch dir.
|
|
@@ -21569,13 +21619,45 @@ def media_pool_item(action: str, params: Optional[Dict[str, Any]] = None) -> Dic
|
|
|
21569
21619
|
status = clip.GetClipProperty("Transcription Status")
|
|
21570
21620
|
except Exception:
|
|
21571
21621
|
status = None
|
|
21572
|
-
|
|
21622
|
+
out = {
|
|
21573
21623
|
"clip_id": p.get("clip_id"),
|
|
21574
21624
|
"text": text,
|
|
21575
21625
|
"truncated": _is_truncated(text),
|
|
21576
21626
|
"status": status or None,
|
|
21577
21627
|
"has_transcription": bool(text.strip()),
|
|
21628
|
+
"segments": None,
|
|
21629
|
+
"language": None,
|
|
21630
|
+
"source": "clip_property",
|
|
21578
21631
|
}
|
|
21632
|
+
# The `Transcription` clip property is a preview and stops at an
|
|
21633
|
+
# ellipsis. Resolve 21.1 added a real accessor that does not truncate,
|
|
21634
|
+
# so prefer it and keep the property as the 21.0.x fallback. Verified on
|
|
21635
|
+
# Studio 21.1.0.14: 1550 segments with per-word start/end timecodes.
|
|
21636
|
+
# Segment timecodes are SOURCE timecodes, not timeline positions.
|
|
21637
|
+
if _has_method(clip, "GetTranscription"):
|
|
21638
|
+
try:
|
|
21639
|
+
full = clip.GetTranscription(bool(p.get("use_nested_clip_transcription", False)))
|
|
21640
|
+
except Exception:
|
|
21641
|
+
full = None
|
|
21642
|
+
segs = full.get("segments") if isinstance(full, dict) else None
|
|
21643
|
+
if segs:
|
|
21644
|
+
if not p.get("include_words"):
|
|
21645
|
+
# `words` is several times the bulk of the segment text and
|
|
21646
|
+
# most callers want segment-level timing. Opt in for it.
|
|
21647
|
+
segs = [{k: v for k, v in seg.items() if k != "words"}
|
|
21648
|
+
if isinstance(seg, dict) else seg for seg in segs]
|
|
21649
|
+
joined = " ".join(seg.get("text", "") for seg in segs
|
|
21650
|
+
if isinstance(seg, dict)).strip()
|
|
21651
|
+
out.update({
|
|
21652
|
+
"segments": segs,
|
|
21653
|
+
"language": full.get("language"),
|
|
21654
|
+
"source": "get_transcription",
|
|
21655
|
+
"truncated": False,
|
|
21656
|
+
})
|
|
21657
|
+
if joined:
|
|
21658
|
+
out["text"] = joined
|
|
21659
|
+
out["has_transcription"] = True
|
|
21660
|
+
return out
|
|
21579
21661
|
elif action == "extract_frames":
|
|
21580
21662
|
return _extract_clip_frames(clip, p)
|
|
21581
21663
|
elif action == "perform_audio_classification":
|
package/src/utils/api_truth.py
CHANGED
|
@@ -1495,6 +1495,31 @@ API_TRUTH: List[Dict[str, Any]] = [
|
|
|
1495
1495
|
"subtitle", "transcription"],
|
|
1496
1496
|
"submit": "bug",
|
|
1497
1497
|
},
|
|
1498
|
+
{
|
|
1499
|
+
"symbol": "SetRenderSettings MarkIn/MarkOut below the timeline start are clamped, not refused",
|
|
1500
|
+
"object": "Project / Timeline",
|
|
1501
|
+
"reality": "SetRenderSettings takes MarkIn/MarkOut as ABSOLUTE record "
|
|
1502
|
+
"frames, and a value below the timeline's start frame is "
|
|
1503
|
+
"silently clamped to the start: measured on Studio 19.1.3.7 "
|
|
1504
|
+
"(2026-09-08) on an 86400-start timeline, MarkIn=MarkOut=86420 "
|
|
1505
|
+
"rendered timeline frame 20 and MarkIn=MarkOut=20 rendered "
|
|
1506
|
+
"frame 0 — one frame, True from SetRenderSettings, no error "
|
|
1507
|
+
"anywhere. The trap is that Timeline.GetMarkInOut reports the "
|
|
1508
|
+
"user's marks RELATIVE to the timeline start (Blackmagic's own "
|
|
1509
|
+
"README example is {'in': 0, 'out': 134}; the 21.1 stub says "
|
|
1510
|
+
"'record frame relative to timeline start'), so feeding its "
|
|
1511
|
+
"output straight into SetRenderSettings renders the wrong range "
|
|
1512
|
+
"with every readback agreeing. SetMarkInOut itself stores "
|
|
1513
|
+
"whatever number it is given (10 reads back 10, 86410 reads "
|
|
1514
|
+
"back 86410), so a script-written range can be in either space.",
|
|
1515
|
+
"recommended": "Offset GetMarkInOut values by Timeline.GetStartFrame() before "
|
|
1516
|
+
"passing them to SetRenderSettings when they fall below the "
|
|
1517
|
+
"start frame (timeline_frame capture does this when it puts "
|
|
1518
|
+
"a user's range back). Verify a render range from the "
|
|
1519
|
+
"delivered frames, never from the settings call's return.",
|
|
1520
|
+
"tags": ["render", "silent-failure", "frame-space", "mark-range"],
|
|
1521
|
+
"submit": "bug",
|
|
1522
|
+
},
|
|
1498
1523
|
{
|
|
1499
1524
|
"symbol": "SetRenderSettings ExportSubtitle / SubtitleFormat had no observable effect",
|
|
1500
1525
|
"object": "Project (render settings)",
|
|
@@ -165,6 +165,18 @@ _EVIDENCE_GATES: List[Dict[str, Any]] = [
|
|
|
165
165
|
"note": "Reported against 21.0.4.5. Not reachable through this server yet.",
|
|
166
166
|
"issue": 131,
|
|
167
167
|
},
|
|
168
|
+
{
|
|
169
|
+
"symbol": "MediaPoolItem.GetTranscription",
|
|
170
|
+
"introduced_in": "21.1",
|
|
171
|
+
"source": "reported",
|
|
172
|
+
"note": "Reported against Studio 21.1.0.14 (PR #199): the untruncated "
|
|
173
|
+
"transcript, {language, segments[{start, end, text, speaker, "
|
|
174
|
+
"words[]}]} in SOURCE timecode. media_pool_item get_transcription "
|
|
175
|
+
"prefers it when present and falls back to the truncated "
|
|
176
|
+
"'Transcription' clip property below 21.1; `source` in the "
|
|
177
|
+
"result says which route ran.",
|
|
178
|
+
"issue": 199,
|
|
179
|
+
},
|
|
168
180
|
{
|
|
169
181
|
"symbol": "Project.SetRenderSettings UseFullExtents",
|
|
170
182
|
"introduced_in": "21.0.4",
|