⌨️

DaVinci Resolveのsettingファイルの再編集(文字列リテラル編)

に公開

settingファイルにおける文字列リテラル格納の問題点

DaVinci Resolveでテキストを入力するとマクロとして書き出した時にはダブルクオーテーションで囲まれた文字列リテラルに変換されて格納されます。

上画像のテキストをsettingファイルに書き出すと次のようになっています

StyledText = Input { Value = "Hello world\nこんにちは世界\nThis is a test\nこれはテストです", },

改行は文字列リテラル内でエスケープされて\nという形で格納されます。
マクロ内ではこの他にもCommentsなどのテキストコントロールの内容も上記のような方式で格納されます。

それらは普通のテキストですが、Expressionの式やRenderScriptやボタンコントロールのExecuteのスクリプトも同様の方式で文字列として格納されます。
こちらの場合はsettingファイルのデータに格納されている時はただの文字列ですが、DaVinci Resolveに読み込まれた時点でスクリプトとして評価されます。

上記画像のような比較的短い文字列ならば1行で出力されていてもさほど可読性に問題はありません。
しかし、スクリプトとなると多くの改行を含んでいたり、長文になったりする事も珍しくありません。
特にスクリプトではネスト状態を表すのにインデントを付けるので、インデントのスペースもそのままスペースという文字列として格納され、結果的に文字数は多くなる傾向にあります。

スクリプトとしてはとても短い部類になると思いますが、例えばこのようなスクリプトだと

local Mode = tonumber(self.ModeSelector) or 0
if self.Point0 and self.Point1 and self.Point2 then
    if Mode == 1 then
        self.Point1.Y = self.Point2.Y
    elseif Mode == 2 then
        self.Point1.Y = self.Point0.Y
    elseif Mode == 3 then
        self.Point1.X = self.Point0.X
        self.Point1.Y = self.Point0.Y
    elseif Mode == 4 then
        self.Point1.X = self.Point0.X
        self.Point1.Y = self.Point0.Y
        self.Point2.Y = self.Point0.Y
    end
end

settingファイルに書き出された時には文字列に変換されて1行で出力されるので以下のようになります。

"local Mode = tonumber(self.ModeSelector) or 0\nif self.Point0 and self.Point1 and self.Point2 then\n    if Mode == 1 then\n        self.Point1.Y = self.Point2.Y\n    elseif Mode == 2 then\n        self.Point1.Y = self.Point0.Y\n    elseif Mode == 3 then\n        self.Point1.X = self.Point0.X\n        self.Point1.Y = self.Point0.Y\n    elseif Mode == 4 then\n        self.Point1.X = self.Point0.X\n        self.Point1.Y = self.Point0.Y\n        self.Point2.Y = self.Point0.Y\n    end\nend"

非常に見辛いですね。
ただ、settingファイル内での視認性が悪くても読み込まれてしまえばDaVinci Resolve上のテキストエディタでは改行やインデントが元のスクリプトの状態で表示されます。
また、動作的にも全く問題ありません。正しく動作しています。

それでも、settingファイル内でスクリプトの内容をチェックしたい時があり、この様な出力状態では可読性がとても悪くて内容をチェックするのには不向きです。

打開案

[[ ]]を使用する

Lua言語では複数行の文字列を表す場合に[[ ]]を使用すると改行もそのまま見た目通りに表現することができます。
つまり、スクリプトの部分を[[ ]]で括ってやると元のスクリプトの見た目をそのままの形で表すことができます。

settingファイル内ではその文字列はデータ構造の中でネストされた状態で登場するのでこの方法を取った場合は以下のようになります。
但し、あくまでも文字列なのでテキストエディタでの色分けは文字列の色で表されます

                FrameRenderScript = Input { 
                    Value = [[
                        local Mode = tonumber(self.ModeSelector) or 0
                        if self.Point0 and self.Point1 and self.Point2 then
                            if Mode == 1 then
                                self.Point1.Y = self.Point2.Y
                            elseif Mode == 2 then
                                self.Point1.Y = self.Point0.Y
                            elseif Mode == 3 then
                                self.Point1.X = self.Point0.X
                                self.Point1.Y = self.Point0.Y
                            elseif Mode == 4 then
                                self.Point1.X = self.Point0.X
                                self.Point1.Y = self.Point0.Y
                                self.Point2.Y = self.Point0.Y
                            end
                        end
                    ]]
                },

通常のスクリプトのように予約語や関数等の色分けはなされませんが、コードの記述そのままで表されるので随分と見やすくなりました。
但しsettingファイル内では見やすくなりましたが、DaVinci Resolveに読み込んでみると以下のようになっています。

文字列の左側に大きな空間ができています。
これは文字通り見た目をそのまま反映するのでデータ上の空白も空白の文字列として読み取られてしまう為です。

そもそもDaVinci Resolve内のエディタは表示領域が非常に狭く視認性が悪いので、スクリプトを書く時はテキストエディタで編集して貼り付けるか、dofile()関数を利用してスクリプトを読み込む事が殆どなのでそこまで気にはなりませんが、DaVinci ResolveUI上では少し残念な表示になってしまいますね。
かと言って不必要な空白を削除しようと思ったら以下のようにしなければなりません。

                FrameRenderScript = Input { 
                    Value = 
[[
local Mode = tonumber(self.ModeSelector) or 0
if self.Point0 and self.Point1 and self.Point2 then
    if Mode == 1 then
        self.Point1.Y = self.Point2.Y
    elseif Mode == 2 then
        self.Point1.Y = self.Point0.Y
    elseif Mode == 3 then
        self.Point1.X = self.Point0.X
        self.Point1.Y = self.Point0.Y
    elseif Mode == 4 then
        self.Point1.X = self.Point0.X
        self.Point1.Y = self.Point0.Y
        self.Point2.Y = self.Point0.Y
    end
end
]]
                },

これもこれでsettingファイル内でのインデントが気持ち悪くて残念ですね。

文字列連結を使用する

JavaScriptPythonでは文字列の連結に+演算子を使用しますが、Lua言語では..演算子を使用します。

"Hello" .. " " .. "world"  -- Hello world

この方法を用いるとDaVinci ResolveUI上の見た目とsettingファイル内での見た目を近いものにできてインデントの問題も解決できます。

                FrameRenderScript = Input {
                    Value =
                        "local Mode = tonumber(self.ModeSelector) or 0\n" ..
                        "if self.Point0 and self.Point1 and self.Point2 then\n" ..
                        "    if Mode == 1 then\n" ..
                        "        self.Point1.Y = self.Point2.Y\n" ..
                        "    elseif Mode == 2 then\n" ..
                        "        self.Point1.Y = self.Point0.Y\n" ..
                        "    elseif Mode == 3 then\n" ..
                        "        self.Point1.X = self.Point0.X\n" ..
                        "        self.Point1.Y = self.Point0.Y\n" ..
                        "    elseif Mode == 4 then\n" ..
                        "        self.Point1.X = self.Point0.X\n" ..
                        "        self.Point1.Y = self.Point0.Y\n" ..
                        "        self.Point2.Y = self.Point0.Y\n" ..
                        "    end\n" ..
                        "end",
                },


1行で出力された文字列をエスケープされた改行\n毎に分割して..演算子で連結した後実改行を挿入するという方法で実現しています。
但し、この方法だと分割された文字列毎にダブルクオーテーションで囲まなければいけないし、エスケープされた文字も残しておかなくてはいけません。
settingファイル内においてのスクリプトの見易さで言えば[[ ]]を用いた方が優れています。
そして何より手間がかかってしまいます。手動でこの作業をするのはきついですね。

どの方法が良いかは人の好みにもよると思いますが、バランスとしては私は文字列分割連結の方法が好みです。

整形用Pythonスクリプト

流石に手動で整形するのは骨が折れてしまいます。そこで、settingファイルを読み込んで自動で整形するPythonスクリプトをAIに作ってもらいました。
settingfile_formatter
※以前は単独のスクリプトでしたが別の整形ルールと統合しました。
詳しい使い方等はリンク先のREADME.mdをお読みください。


マクロを書き出してテストしている時点でバグを発見したりするとスクリプトだけ修正したい時があると思います。
スクリプトを修正するためだけに再度マクロを書き出すのは非常に効率が悪いです。
ひたすらチェックボックスにチェックを入れる作業を再度しなくてはなりませんし、せっかく順番を入れ替えたりラベルコントロールなどを挿入した物もまた1からやり直すのは骨が折れてしまいます。

そういう時はマクロの作成から書き出すのではなくsettingファイルとして別名保存すると便利です。

ノードエディタ上にあるマクロ化したノードの上で右クリックからの設定→別名で保存を選択すると現在の状態で新たにsettingファイルとして保存できるので煩わしいチェックボックスをチェックする作業はしなくて済みます。

補助的なスクリプト

ですが、その場合でも文字列リテラルの格納方法は同様に1行で出力されます。上記のスクリプトで整形してあっても元の状態に戻ります。
もう一度上記のスクリプトを適用すれば良いのですが、軽微な変更ならsettingファイルを直接編集した方が速い場合もあります。

そこで、スクリプトの記述を上記のフォーマットの文字列リテラルに変換するスクリプトを作ってもらいました。
https://github.com/2ndillness/DR_settingfile_formatter/blob/main/clip_tools/scpt2str_clip.py

使い方

  1. DaVinci Resolveで該当するスクリプトのテキストボックス内のテキストをを全選択してコピー
    或いは別ファイルとして保存してあるスクリプトをコピー
  2. クリップボードにコピーしたテキストが格納された状態でPythonスクリプトを実行
python scpt2str_clip.py
  1. 上記フォーマットの文字列リテラルに変換されたデータがクリップボードに格納されるのでsettingファイルの挿入したい場所に貼り付け
  2. インデント等は手動で調整

感想

DaVinci Resolveのマクロを書き出すのはチェックボックスを大量にチェックしなければいけないので大変です。
それ故に一度書き出したらできる事なら書き出し直しはしたくない物です。

マクロを書き出してからテキストエディタで再編集したい内容も多いので、できるだけsettingファイルも見やすい状態にして快適に編集したいという思いがあります。

ですが、ひょっとしたらsettingファイルの見易さを気にしているのは少数派なのかも知れません。
なので整形用スクリプトはニッチだとは思いますが、個人用に作ってもらいました。

AIに作ってもらうに当たり私はPythonを触った事が無かったので少しだけ勉強しました。AIは非常に強力なツールですが、無料プランで使用できるモデルはそこまで賢くないのと、自身の知識が無いので的確な指示を出す事ができずに本当に苦労しました。結果的には自分もPythonの勉強を少しだけできたので良かったと思います。

GitHubで編集を提案

Discussion