resolve-scripting
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseResolve scripting: what actually works (Resolve Studio 21)
Resolve 脚本:真正有效的方法(Resolve Studio 21)
Check the API for the installed version before trusting memory: the scripting docs ship with Resolve, and functions move (some changed between 20 and 21).
在依赖记忆之前,先检查已安装版本对应的 API:脚本文档随 Resolve 一同提供,而且函数会发生变化(有些在 20 和 21 之间发生了变化)。
Golden rules
黄金规则
- Only add. New timelines (never overwrite: "name v2"), imports into bins, clips on free tracks. Never touch the creator's template or their timelines/media. Never switch/create/close projects.
- Verify every write by reading it back. Many setters return True and do nothing.
- Save the project at the end of each step.
- 只做新增。 新建时间线(绝不覆盖:使用“name v2”),将素材导入 bin,并把片段放在空闲轨道上。绝不触碰创作者的模板或其时间线/媒体。绝不切换、创建或关闭项目。
- 每次写入后都要回读验证。 许多 setter 返回 True,却什么也没做。
- 每一步结束后保存项目。
Building the timeline
构建时间线
- Find bins by name recursively. Import files once (reuse the media pool item if the same path is already imported).
- Copy the template with , move it into the timelines bin, then empty every track (unlock locked tracks temporarily). The copy keeps the track FX chain (voice treatment on A1, music treatment on A2) - that's why we copy instead of creating.
DuplicateTimeline(name) - Frame rate mismatch footage vs template: stop and ask. If they choose the footage rate: ,
useCustomSettings=1,timelineFrameRate.timelinePlaybackFrameRate - Custom frame (e.g. 4:3 2880x2160): set and the output resolution, then input mismatch behaviour
timelineResolutionWidth/Height("scale full frame with crop"). The defaultscaleToCropletterboxes. Read it back.scaleToFit - :
AppendToTimelineis exclusive. For audio-only media, start/end frames count in the clip's own frame rate (a WAV reports 23.976), not the timeline's.endFrame - Audio duration from timecode: at 23.976, a timecode counts 24 frames per second. . Using 23.976 per second lost 16 frames on an 11-minute music bed.
seconds = ((h*3600+m*60+s)*round(fps) + f) / fps - Check after laying: piece count on V1 and A1, each duration, no gaps.
- 递归查找指定名称的 bin。文件只导入一次(如果同一路径已经导入,则复用媒体池中的项目)。
- 使用 复制模板,将其移动到 timelines bin,然后清空每条轨道(临时解锁锁定轨道)。副本会保留轨道 FX 链(A1 上的人声处理、A2 上的音乐处理)——因此选择复制而不是新建。
DuplicateTimeline(name) - **素材与模板的帧率不一致:**停止操作并询问。如果对方选择素材帧率:、
useCustomSettings=1、timelineFrameRate。timelinePlaybackFrameRate - **自定义画幅(如 4:3 2880x2160):**设置 和输出分辨率,然后将输入不匹配行为设为
timelineResolutionWidth/Height(“缩放完整画面并裁切”)。默认的scaleToCrop会产生黑边。回读确认。scaleToFit - :
AppendToTimeline是排他的(不包含该帧)。对于纯音频媒体,起始/结束帧按片段自身的帧率计算(一个 WAV 报告为 23.976),而不是时间线的帧率。endFrame - **根据 timecode 计算音频时长:**在 23.976 下,timecode 按每秒 24 帧计数。。如果按每秒 23.976 帧计算,一段 11 分钟的音乐会少 16 帧。
seconds = ((h*3600+m*60+s)*round(fps) + f) / fps - 铺设完成后检查:V1 和 A1 上的片段数量、各片段时长,以及是否存在空隙。
Picture
画面
- Zoom: and
item.SetProperty("ZoomX", z)(centre anchored). Works in 21."ZoomY" - Grades: fails in 21. Use each item's graph:
Timeline.ApplyGradeFromDRX. It occasionally fails on one piece and works on a retry: try twice, then count graded pieces (node count) and report.item.GetNodeGraph().ApplyGradeFromDRX(path, 0) - Never put a log look on non-log footage. Read the profile from the camera's sidecar XML, not from luma guesses.
- on B-roll pieces.
SetClipColor("Green")
- 缩放:和
item.SetProperty("ZoomX", z)(以中心点为锚点)。在 21 中有效。"ZoomY" - 调色:在 21 中无效。改用每个片段的 graph:
Timeline.ApplyGradeFromDRX。它偶尔会在某个片段上失败,但重试后又会成功:尝试两次,然后统计已调色片段的数量(节点数)并报告。item.GetNodeGraph().ApplyGradeFromDRX(path, 0) - 切勿对非 Log 素材套用 Log 风格。从相机的 sidecar XML 中读取 profile,而不是根据亮度猜测。
- 为 B-roll 片段调用 。
SetClipColor("Green")
Audio
音频
- Normalize: with
Timeline.NormalizeAudioLevel(items, {normalizationMode, targetLevel, targetLoudness, setLevelMode}). Seeresolve.NORMALIZE_AUDIO_SET_LEVEL_INDEPENDENTfor values.voice-and-audio - Per clip: (dB),
AudioVolume, Dialogue Leveler properties. EQ is not scriptable; Fairlight presets can be applied if the user saved some.SetVoiceIsolationState({"isEnabled": True, "amount": 50}) - Silent track trap: a template's music track had a track-level AI Music Remixer switched on (and a Stereo Width insert). Anything placed on that track rendered as silence while the same file played on another track. The API can't read or toggle it; it's in the Edit page → select the track header → Inspector → Audio. If music is silent, check that first.
- **标准化:**使用 ,并配合
Timeline.NormalizeAudioLevel(items, {normalizationMode, targetLevel, targetLoudness, setLevelMode})。具体数值参见resolve.NORMALIZE_AUDIO_SET_LEVEL_INDEPENDENT。voice-and-audio - 逐片段设置:(dB)、
AudioVolume、Dialogue Leveler 属性。EQ 无法通过脚本设置;如果用户保存了一些 Fairlight 预设,则可以应用。SetVoiceIsolationState({"isEnabled": True, "amount": 50}) - **静音轨道陷阱:**模板的音乐轨道启用了轨道级 AI Music Remixer(并带有 Stereo Width 插入效果)。放到该轨道上的内容渲染出来却是静音,而同一文件放在其他轨道上则正常。API 无法读取或切换它;需要在 Edit 页面 → 选择轨道头 → Inspector → Audio 中设置。如果音乐没有声音,首先检查这一点。
Diagnosing audio the reliable way
可靠诊断音频的方法
When "there's no sound", don't guess. Render a few seconds of audio from Resolve and compare it with the source file:
- Project render: ,
SetCurrentRenderFormatAndCodec("mov", "ProRes422LT"),SetRenderSettings({SelectAllFrames: False, MarkIn, MarkOut, TargetDir, CustomName, ExportVideo: False, ExportAudio: True, AudioCodec: "lpcm"}).AddRenderJob() - From an external script, rendering only starts with (isInteractiveMode False). Other forms return False and the job stays "Ready".
StartRendering([job], False) - Render into a folder without spaces (a path with spaces left the job unstarted).
- Wait on until "Complete", not on
GetRenderJobStatus(job)(it can be False before rendering begins).IsRenderingInProgress() - Correlate the rendered audio with the source (mono, 8 kHz, best lag): ~0.9 = present, ~0.0 = missing. Least-squares gain tells how much of an SFX is in the mix.
- Restore the Deliver settings afterwards (format, whole timeline, video+audio on, output folder): your test changes the creator's export settings.
- jumps to the Deliver page;
AddRenderJobonly works on the Edit page (on other pages it returns True and does nothing). Go back withSetTrackEnable.OpenPage("edit") - Timeline export () is a zip of XML with per-track fields; deeper mixer state is a compressed binary. Useful for diffing a working vs broken track.
Timeline.Export(path, EXPORT_DRT)
当“没有声音”时,不要靠猜。渲染几秒音频,并将结果与源文件进行比较:
- 项目渲染:、
SetCurrentRenderFormatAndCodec("mov", "ProRes422LT")、SetRenderSettings({SelectAllFrames: False, MarkIn, MarkOut, TargetDir, CustomName, ExportVideo: False, ExportAudio: True, AudioCodec: "lpcm"})。AddRenderJob() - **在外部脚本中,只有使用 (
StartRendering([job], False)为 False)才会真正开始渲染。**其他形式会返回 False,任务仍停留在“Ready”。isInteractiveMode - 渲染到不含空格的文件夹(路径中包含空格会导致任务无法启动)。
- 等待 返回“Complete”,不要依赖
GetRenderJobStatus(job)(渲染开始前它也可能为 False)。IsRenderingInProgress() - 将渲染音频与源文件做相关性分析(单声道、8 kHz、最佳偏移):约 0.9 表示存在,约 0.0 表示缺失。最小二乘增益可以反映混音中包含多少 SFX。
- 之后恢复 Deliver 设置(格式、整条时间线、视频和音频均开启、输出文件夹):测试操作会更改创作者的导出设置。
- 会跳转到 Deliver 页面;
AddRenderJob仅在 Edit 页面上有效(在其他页面上会返回 True,却什么也没做)。使用SetTrackEnable返回。OpenPage("edit") - 时间线导出()是一个包含逐轨道字段的 XML 压缩包;更深的混音器状态则存储为压缩二进制数据。适合对比正常轨道与故障轨道。
Timeline.Export(path, EXPORT_DRT)
Subtitles
字幕
- with an imported .srt ignores recordFrame and appends the subtitles after the end of the timeline. Passing start/end frames for it crashed Resolve 21.1.
MediaPool.AppendToTimeline - Use File > Import > Subtitle in the UI (the creator clicks it, or computer-use). It places the first cue at the playhead and shifts the rest relative to it, so make the SRT's first cue start at 00:00:00,000, or everything lands early.
- Subtitle track style can't be set by script; read it from a DRT export if you need to record it.
- 对已导入的 .srt 使用 时,会忽略
MediaPool.AppendToTimeline,并将字幕追加到时间线末尾。传入起始/结束帧会导致 Resolve 21.1 崩溃。recordFrame - 在 UI 中使用 File > Import > Subtitle(由创作者点击,或使用 computer-use)。它会将第一条字幕放在播放头位置,并以该位置为基准移动其余字幕,因此应确保 SRT 的第一条字幕从 00:00:00,000 开始,否则所有字幕都会提前出现。
- 无法通过脚本设置字幕轨道样式;如果需要记录该样式,可以从 DRT 导出中读取。
Overlays and media cache
叠加素材与媒体缓存
- Re-rendered files with the same name can keep playing stale cached frames: give each new render a new name () and replace the clip.
-v2 - Place overlays on the first free unlocked track from V2 up; never on V1.
- 重新渲染的文件如果使用相同名称,可能持续播放缓存中的旧帧:为每次新渲染使用新名称(),然后替换片段。
-v2 - 将叠加素材放到从 V2 向上找到的第一条空闲且未锁定的轨道上;绝不要放在 V1 上。
Reading the timeline the creator edited
读取创作者编辑后的时间线
Before music, captions or graphics, map the timeline as it is now: walk V1 items (name, start, left offset) to find where each kept word and each B-roll landed. They trim and delete things; follow their version.
在处理音乐、字幕或图形之前,先按当前状态梳理时间线:遍历 V1 片段(名称、起点、左侧偏移),确定每个保留的词和每个 B-roll 的实际落点。他们会裁剪和删除内容;以他们的版本为准。