Flame 2027.2から.otioファイルの書き出しに対応したため、DaVinci Resolveから書き出した.otioファイルとの内部構造を比較しました。
その過程で、FlameのConformにおけるName Strict / File Name Strictの照合について、2027.1と2027.2で挙動が異なることを確認しました。
今回はDaVinci ResolveとAdobe Premiere Proから同じ編集内容の.otioファイルを書き出し、.movファイルと.exrイメージシーケンスを使用して検証しています。
Clip.2.nameとName Strict
DaVinci ResolveやPremiere Proから書き出した.otioファイルでは、Clip.2.nameにファイルの拡張子が含まれています。
.movの場合:
"name": "A002C001_2206227A.mov"
.exrイメージシーケンスの場合:
"name": "A002C001_2206227A[141603-141626].exr"
これらの名前はFlameのセグメントネームに反映されます。


一方、Flameに読み込んだメディアのクリップネームには、拡張子やフレーム範囲が含まれていないため、そのままではName Strictで一致しません。
そこで、Clip.2.nameを次のように修正しました。
"name": "A002C001_2206227A"
この変更だけで、Premiere Proの.mov、DaVinci Resolveの.movと.exrイメージシーケンスのいずれも、Name Strictによるリンクに成功しました。


File Name Strictのバージョンによる違い
.exrイメージシーケンスでは、Flame 2027.1と2027.2で異なる結果になりました。
| 検証内容 | 2027.1 | 2027.2 |
|---|---|---|
| Clip.2.nameのみ修正:Name Strict | 成功 | 成功 |
| Clip.2.nameのみ修正:File Name Strict | 失敗 | 成功 |
| Clip.2.nameとname_prefixを修正:File Name Strict | 成功 | 追加修正不要 |
Flame 2027.1では、以前の記事で紹介したように、ImageSequenceReference.1.name_prefixも修正する必要がありました。
しかし、Flame 2027.2ではname_prefixを変更しなくても、File Name Strictで正常にリンクできることを確認しました。
このため、2027.2では.otioファイルの修正処理を簡略化できます。
Pythonスクリプトの整理
今回の検証に合わせて、Premiere Pro / DaVinci Resolve共通のPythonスクリプトotio_prepare_for_flame.pyを作成しました。
このスクリプトでは、Clip.2.nameのみを修正します。
- .mov:ファイルの拡張子を削除
- .exr:フレーム範囲と拡張子を削除
- Media Reference、メディアパス、タイミング情報は変更しない
otio_prepare_for_flame.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Prepare Premiere Pro / DaVinci Resolve OTIO for Flame Name Strict conform.
Only Clip.2.name is modified. Media references, paths, timing and metadata
are preserved. Tested structurally against sample Premiere/Resolve OTIO files;
confirm relinking in Flame for each workflow.
"""
import argparse
import json
import re
from pathlib import Path
# Only recognized media extensions are removed. Extend this list as needed.
MEDIA_EXT = re.compile(
r"\.(?:exr|dpx|tif|tiff|jpg|jpeg|png|mov|mxf|mp4|m4v|avi|mkv|r3d|ari|braw)$",
re.IGNORECASE,
)
FRAME_RANGE = re.compile(r"\[\s*-?\d+\s*-\s*-?\d+\s*\]$")
def clean_clip_name(name: str) -> str:
"""Strip a known media extension and an optional trailing frame range."""
without_ext = MEDIA_EXT.sub("", name)
if without_ext == name:
return name # Do not alter arbitrary clip names.
without_range = FRAME_RANGE.sub("", without_ext)
if without_range != without_ext:
return without_range.rstrip(".") # Handles 'B004C0023.[1001-1024].exr'.
return without_ext
def prepare(data):
changes = []
def walk(value):
if isinstance(value, dict):
if value.get("OTIO_SCHEMA") == "Clip.2" and isinstance(value.get("name"), str):
old = value["name"]
new = clean_clip_name(old)
if old != new:
value["name"] = new
changes.append((old, new))
for child in value.values():
walk(child)
elif isinstance(value, list):
for child in value:
walk(child)
walk(data)
return changes
def main():
parser = argparse.ArgumentParser(
description="Strip file extensions and EXR/DPX frame ranges from Clip.2.name only."
)
parser.add_argument("input_otio", type=Path, help="Original Premiere/Resolve .otio")
parser.add_argument("output_otio", type=Path, help="New .otio (original is not overwritten)")
args = parser.parse_args()
if args.input_otio.resolve() == args.output_otio.resolve():
parser.error("Input and output must be different files.")
if not args.input_otio.is_file():
parser.error(f"Input file not found: {args.input_otio}")
data = json.loads(args.input_otio.read_text(encoding="utf-8-sig"))
changes = prepare(data)
args.output_otio.write_text(
json.dumps(data, ensure_ascii=False, indent=4) + "\n", encoding="utf-8"
)
for old, new in changes:
print(f" {old} -> {new}")
print(f"Changed Clip.2.name: {len(changes)}")
print(f"Output: {args.output_otio}")
print("Media references, paths and timing: unchanged")
if __name__ == "__main__":
main()Flame 2027.2では、このスクリプトによる修正だけでName Strict / File Name Strictの両方に対応できます。
一方、Flame 2027.1で.exrイメージシーケンスをFile Name Strictで照合する場合は、従来のresolve_otio_prepare_for_flame_strict.pyを使用します。
resolve_otio_prepare_for_flame_strict.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import json
import re
def strip_clip_name(name):
name = re.sub(r"\[\d+-\d+\]", "", name)
name = re.sub(r"\.[^.]+$", "", name)
return name.rstrip("._- ")
def process(obj):
changed_clip_name = 0
changed_name_prefix = 0
def walk(item):
nonlocal changed_clip_name, changed_name_prefix
if isinstance(item, dict):
schema = item.get("OTIO_SCHEMA")
# File Name Strict用:
# ImageSequenceReference.name を name_prefix にコピー
if schema == "ImageSequenceReference.1":
name = item.get("name")
prefix = item.get("name_prefix")
if isinstance(name, str) and name != prefix:
item["name_prefix"] = name
changed_name_prefix += 1
# Name Strict用:
# Clip.2.name だけ短くする
if schema == "Clip.2":
name = item.get("name")
if isinstance(name, str):
new_name = strip_clip_name(name)
if new_name != name:
item["name"] = new_name
changed_clip_name += 1
for value in item.values():
walk(value)
elif isinstance(item, list):
for value in item:
walk(value)
walk(obj)
return changed_clip_name, changed_name_prefix
def main():
parser = argparse.ArgumentParser(
description="Prepare Resolve OTIO for Flame Name and File Name Strict matching."
)
parser.add_argument("input_otio")
parser.add_argument("output_otio")
args = parser.parse_args()
with open(args.input_otio, "r", encoding="utf-8") as f:
data = json.load(f)
changed_clip_name, changed_name_prefix = process(data)
with open(args.output_otio, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
print(f"Changed Clip.2 names : {changed_clip_name}")
print(f"Changed name_prefix fields : {changed_name_prefix}")
print(f"Input : {args.input_otio}")
print(f"Output : {args.output_otio}")
if __name__ == "__main__":
main()
まとめ
今回の検証で、Flame 2027.2ではDaVinci Resolveの.exrイメージシーケンスに対するFile Name Strictの照合が、2027.1とは異なることが確認できました。
また、Name Strictについては、.otioファイルのClip.2.nameがFlameのセグメントネームに反映されるため、拡張子やフレーム範囲を削除することで正しく照合できることも確認しています。
なお、今回の結果はFlame 2027.1 / 2027.2で使用したテスト素材と.otioファイルによる検証結果です。