コンテンツにスキップ

クリップの長さが正しくない場合

特定の条件下でAppendToTimelineを利用すると、タイムラインへ追加されたクリップが指定値と異なる長さになる現象を確認しました。

このページでは、この問題に関する調査結果について記載します。

DaVinci ResolveのScript APIにて公開されているメソッドで、メディアプール上にあるアイテムを、タイムラインへクリップとして追加する機能があります。

また、clipInfoを設定して渡すことで、追加クリップの位置や長さなどを指定することが可能です。

DunkAssistでは、このAppendToTimelineclipInfoを渡してクリップの投げ込みを行っているため、ここに不具合があれば影響を受けます。

どのような問題が発生するのか

Section titled “どのような問題が発生するのか”

タイムラインに追加されるクリップが、clipInfoで設定された値より長くなったり、短くなったりします。

これによりDunkAssistが投げ込むクリップの長さが、想定と異なるものになることがあります。

音声系アイテムと、Fusion系アイテムで検証を行いました。

言語はいずれもLuaになります。

以下のいずれかの条件を満たしている時に、AppendToTimelineを利用して音声をタイムラインへと追加すると、clipInfoで指定した値と異なる長さになることを確認しています。

  1. 「プロジェクト設定のタイムラインフレームレート」と「現在のタイムラインのフレームレート」が異なる。
  2. ある程度編集を行ってから既存のタイムラインを削除し、プロジェクト設定のタイムラインフレームレートを変更する。

タイムラインへと追加するクリップがFusion系アイテムだった場合、アイテム内で設定されているフレームレートの値が影響します。

例えばText+をメディアプールに保存する場合、一度タイムラインへと置いてから、メディアプールへと渡す必要があります。

この時のタイムラインのフレームレートの値がアイテムに設定され、AppendToTimeline実行時に影響します。

なお、Fusion系アイテムに関しては、現在のタイムラインへと手動で配置し、メディアプールに戻すことで、設定されているフレームレート値を更新することが可能です。

  • プロジェクト設定と同じフレームレートでタイムラインを作成する。
  • 一度編集を始めたら、プロジェクト設定のフレームレートを変更しない。
  • Fusion系アイテムの場合は、手動で現在のタイムラインに置いてから、メディアプールに戻す。
  • clipInfoでクリップの長さ(endFrame)を指定しない。
  • DaVinci Resolveの公式がこの問題に対応するのを待つ。

本検証は次の環境で行いました。

  • Windows 11 Pro 25H2
  • DaVinci Resolve Studio 21.0.4

また、検証に使用したスクリプトや、事前準備、実際の手順などについては下記を参照してください。

AppendToTimelineを実行するためのLuaスクリプトです。コンソールに入力して実行してください。

なお、CLIP_DURATIONの値を変更すると、タイムラインに追加するクリップの長さの設定値を変更することができます。

このスクリプトは音声ファイルの投げ込みのみ対応しています。

-- タイムラインに追加するクリップの長さ
local CLIP_DURATION = 30
-- オーディオクリップのタイプ
local AUDIO_TYPES = { "Audio", "オーディオ", "音频", "오디오", "Áudio", "Аудио", "ออดิโอ", "Âm thanh" }
-- contains関数
local function contains(array, value)
for _, item in ipairs(array) do
if item == value then
return true
end
end
return false
end
-- タイムコードをフレーム数に変換
local function timecodeToFrame(timecode, fps)
local h, m, s, f = timecode:match("(%d+):(%d+):(%d+)[:;](%d+)")
if not h then
return nil
end
h = tonumber(h)
m = tonumber(m)
s = tonumber(s)
f = tonumber(f)
local nominal_fps = math.floor(fps + 0.5)
return ((h * 3600) + (m * 60) + s) * nominal_fps + f
end
-- プロジェクトを取得
local project = resolve:GetProjectManager():GetCurrentProject()
-- プロジェクトのフレームレートを取得
local project_fps = tonumber(project:GetSetting("timelineFrameRate"))
print("プロジェクトfps: " .. project_fps)
-- 現在のタイムラインのフレームレートを取得
local timeline = project:GetCurrentTimeline()
local timeline_fps = tonumber(timeline:GetSetting("timelineFrameRate"))
print("タイムラインfps: " .. timeline_fps)
-- 現在の再生ヘッドの位置を取得
local current_timecode = timeline:GetCurrentTimecode()
local current_playhead = timecodeToFrame(current_timecode, timeline_fps)
-- メディアプールの直下に保存されているオーディオクリップを1つだけ取得
local media_pool = project:GetMediaPool()
local root_list = media_pool:GetRootFolder():GetClipList()
local audio_clip = nil
for _, clip in ipairs(root_list) do
local clip_type = clip:GetClipProperty("Type")
local is_audio = contains(AUDIO_TYPES, clip_type)
if is_audio then
audio_clip = clip
break
end
end
if audio_clip == nil then
print("オーディオクリップを取得できませんでした。")
return
end
-- 現在の再生ヘッドの位置に、オーディオクリップを設置
local audio_clip_info = {
mediaPoolItem = audio_clip,
mediaType = 2,
trackIndex = 1,
recordFrame = current_playhead,
startFrame = 0,
endFrame = CLIP_DURATION,
}
local placed_clip = media_pool:AppendToTimeline({ audio_clip_info })
if placed_clip == nil or placed_clip[1] == nil then
print("AppendToTimelineの実行に失敗しました。")
return
end
-- Output the results.
print("クリップの長さの設定値: " .. CLIP_DURATION)
print("実際に追加されたクリップの長さ: " .. placed_clip[1]:GetDuration())
local mismatch_duration = placed_clip[1]:GetDuration() - CLIP_DURATION
if mismatch_duration == 0 then
print("クリップは適切に追加されました。")
else
print("設定値と実際の長さの差: " .. mismatch_duration)
end

新規プロジェクトを開始し、メディアプールのマスターに任意の音声ファイルを保存してください。

事前準備が完了したら、次の手順を行ってください。

  1. メディアプール領域を右クリックし、「タイムライン」→「新規タイムラインを作成」を選択
  2. 左下の「プロジェクト設定を使用」のチェックを外します
  3. 「フォーマット」タブにて、「タイムラインフレームレート」をプロジェクト設定と異なる値に変更
  4. 上記の設定でタイムラインを作成
  5. 検証用スクリプトを実行

上記手順により、タイムラインへのクリップの追加と、コンソールへの情報の出力が行われます。

事前準備が完了したら、次の手順を行ってください。

  1. メディアプール領域を右クリックし、「タイムライン」→「新規タイムラインを作成」を選択
  2. 左下の「プロジェクト設定を使用」が有効である状態でタイムラインを作成
  3. 検証用スクリプトを実行し、タイムラインへと音声を追加(正常に追加されます)
  4. メディアプールからタイムラインを削除
  5. 右下の⚙から「プロジェクト設定」を開き→「マスター設定」タブを選択
  6. 「タイムラインフレームレート」を異なる値に変更して保存
  7. 再度タイムラインを「プロジェクト設定を使用」が有効な状態で作成
  8. 検証用スクリプトを実行

上記手順により、タイムラインへのクリップの追加と、コンソールへの情報の出力が行われます。

筆者の環境では、検証により以下の結果が得られました。

クリップの長さの設定値はlocal CLIP_DURATION = 30であることを前提とします。

発生条件1の検証

現在のタイムラインfps プロジェクト設定fps 追加クリップの長さ 設定値との差
24 30 24 -6
60 50 36 6

発生条件2の検証

現在のタイムラインfps 変更前のプロジェクト設定fps 追加クリップの長さ 設定値との差
24 30 24 -6
60 50 36 6

これらのデータから、AppendToTimeline実行時に次の計算式と同等の処理が行われているものと考えられます。

追加クリップの長さ = 設定した長さ * (現在のタイムラインfps / 影響を与えるfps)

また、この現象は、プロジェクトの保存とロードを行っても解消されないことを確認しております。

AppendToTimelineの問題はバグか仕様か

Section titled “AppendToTimelineの問題はバグか仕様か”

客観的に見てバグだと思います。

発生条件1によるズレだけであれば、プロジェクト設定と現在のタイムラインのフレームレート差を補正しているという見方もできます。

しかし発生条件2によるズレには合理的理由がありません。

また、対象のクリップのタイプによって条件が異なることから、この処理に整合性があるとは言えません。

Blackmagic Forumでも、この問題に関係するスレッドは作成されています。

BUG AppendToTimeline : cannot set still frames durations
Script AppendToTimeline framerate conversion

ただ、いずれも2024年のスレッドなので、公式がこの問題に対応する気があるのか、そもそもバグとして認識しているかは不明です。

また、筆者も公式サポート(Blackmagic Design様のテクニカルサポートとDeveloper Support)へと問い合わせを行いましたが、明確な回答をいただけていません。

ver0.1.3にて、次の対策を行いました。

  • DaVinci Resolveのfps差によるクリップの長さのずれを自動調整する設定を追加
  • 音声クリップの長さの調整が必要ない場合は、終了フレームを設定しないように変更