背景と目的
DaVinci Resolve の FusionページではSpline Editor を使ってアニメーションを細かく制御できる(図1参照)。 これは Pythonスクリプトからでも実行可能だが、やり方が分かりづらかったので備忘録として記事を残しておく。
Pythonスクリプトを使って Spline Editor と同等の操作を行う方法
Pythonスクリプトを使って fusion composition や各種ノードを作成した上で、以下の手順を実行すれば良い。
- keyframe と Spline Editor の設定を辞書型の変数として定義しておく
- BezierSpline インスタンスを作成する
- BezierSpline インスタンスに対して
SetKeyFrames()
を使い 手順1. で作成した辞書型の変数を代入する - ノードのパラメータ(今回は
Width
)に対して BezierSpline インスタンスを代入する
冒頭の図1 に相当する Python の実装例は以下の通り。
# RectangleMask ノードは rect_mask という変数名で作成済みとする key_frames = { 0: { 1: 0.0, 'LH': {1: 0.0, 2: 0.0}, 'RH': {1: 20.0, 2: 0.0} }, 23: { 1: 1.0, 'LH': {1: -20.0, 2: 0.0}, 'RH': {1: 0.0, 2: 0.0} } } bezier_spline = fusion_comp.BezierSpline() bezier_spline.SetKeyFrames(key_frames) rect_mask["Width"] = bezier_spline
ここで、上記のコードで作成した変数key_frames
について軽く解説を行っておく*1。
まず0
や23
の数字は keyframe を意味する。上記のコードでは 0フレームと 23フレームに keyframe を打つことを意味する。
keyframe内部の 1: 0.0
や 1: 1.0
はターゲットとなるパラメータの値を意味する。
上記のコードでは 0フレームに Width=0.0 を、23フレームに Width=1.0 を設定している。
最後に 'LH': {1: 0.0, 2: 0.0}, 'RH': {1: 20.0, 2: 0.0}
や 'LH': {1: -20.0, 2: 0.0}, 'RH': {1: 0.0, 2: 0.0}
は Spline Editor で設定するハンドルの相対位置を意味している。
例えば'LH': {1: -20.0, 2: 0.0}
はレフトハンドルの x座標を -20だけ移動した場所に、y座標を 0だけ移動した場所に設定することを意味する。
以上がkey_frames
の説明である。
サンプルコード
プロジェクトの作成から図1の設定までを一通り実行するサンプルコードを以下に添付しておく。
# -*- coding: utf-8 -*- import sys import os if sys.platform == "darwin": # macOS resolve_script_api = ( "/Library/Application Support/Blackmagic Design/DaVinci Resolve/" "Developer/Scripting" ) sys.path.append(os.path.join(resolve_script_api, "Modules")) resolve_lut_path = \ "/Library/Application Support/Blackmagic Design/DaVinci Resolve/LUT/" elif sys.platform == "win32": # Windows resolve_script_api = os.path.expandvars( r"%PROGRAMDATA%\Blackmagic Design\DaVinci Resolve\Support" r"\Developer\Scripting" ) sys.path.append(os.path.join(resolve_script_api, "Modules")) resolve_lut_path = os.path.expandvars( r"%PROGRAMDATA%\Blackmagic Design\DaVinci Resolve\Support\LUT" ) elif sys.platform == "linux": # Linux resolve_script_api = "/opt/resolve/Developer/Scripting" sys.path.append(os.path.join(resolve_script_api, "Modules")) resolve_lut_path = "/home/resolve/LUT" ValueError("Linux platform is not supported") import DaVinciResolveScript as dvr_script resolve = dvr_script.scriptapp("Resolve") if resolve is None: raise ConnectionError("The DaVinci Resolve app is not running.") project_name = "Apply Spline Editor Result 20250215" project_manager = resolve.GetProjectManager() project = project_manager.GetCurrentProject() project_manager.CloseProject(project) project_manager.DeleteProject(project_name) project = project_manager.CreateProject(project_name) # add fusion composition resolve.OpenPage("edit") media_pool = project.GetMediaPool() timeline = media_pool.CreateEmptyTimeline("Timeline1") timeline_item = timeline.InsertFusionCompositionIntoTimeline() fusion_comp = timeline_item.AddFusionComp() fusion_comp.Lock() # add background node (tool) x_pos = 1 y_pos = 1 base_bg = fusion_comp.AddTool("Background", x_pos, y_pos) base_bg.SetInput("TopLeftRed", 0.5) base_bg.SetInput("TopLeftGreen", 0.5) base_bg.SetInput("TopLeftBlue", 0.5) # add merge node (tool) x_pos = 2 y_pos = 1 merge = fusion_comp.AddTool("Merge", x_pos, y_pos) # add rectangle mask (tool) x_pos = 2 y_pos = 3 rect_mask = fusion_comp.AddTool("RectangleMask", x_pos, y_pos) rect_mask.SetInput("Width", 0.3) rect_mask.SetInput("Height", 0.3) # rectangle background (tool) x_pos = 2 y_pos = 2 rect_bg = fusion_comp.AddTool("Background", x_pos, y_pos) rect_bg.SetInput("TopLeftRed", 0.6666666) rect_bg.SetInput("TopLeftGreen", 1.0) rect_bg.SetInput("TopLeftBlue", 0.0) rect_bg.SetInput("EffectMask", rect_mask) # get MediaOut1 tool_name = "MediaOut1" media_out = next( (vv for vv in fusion_comp.GetToolList().values() if vv.Name == tool_name), None ) # connect tools merge.ConnectInput("Background", base_bg) merge.ConnectInput("Foreground", rect_bg) media_out.ConnectInput("Input", merge) # set keyframes with bezier spline key_frames = { 0: { 1: 0.0, 'LH': {1: 0.0, 2: 0.0}, 'RH': {1: 20.0, 2: 0.0} }, 23: { 1: 1.0, 'LH': {1: -20.0, 2: 0.0}, 'RH': {1: 0.0, 2: 0.0} }, } bezier_spline = fusion_comp.BezierSpline() bezier_spline.SetKeyFrames(key_frames) rect_mask["Width"] = bezier_spline fusion_comp.Unlock() resolve.OpenPage("fusion")
感想
Spline Editor の横軸の単位がフレームになっているのが個人的には分かりやすくて助かった。 スクリプトを工夫すれば 24 fps / 30 fps / 60 fps の各種フレームレートで同じアニメーションを作成可能であり、テストパターン動画の作成で大いに役立った。
*1:分かりにくい、というか筆者は最初ちんぷんかんぷんだった