Source code for cgl.plugins.otio.tools.extract_shots
import re
from collections import OrderedDict
import opentimelineio as otio
from cgl.plugins.otio.tools.fcp import fcp_extract_shots
from cgl.plugins.otio.tools.aaf import aaf_extract_shots
SEQUENCE_NAME_FMT = r"(?P<sequence>[0-9]{1,3}[a-zA-Z]{0,3})"
SHOT_NUMBER_FMT = r"(?P<shot>[0-9]{4})"
SHOT_NAME_FMT = SEQUENCE_NAME_FMT + "_" + SHOT_NUMBER_FMT
HANDLES = 0
[docs]
def clean_seq_name(name):
name = name.split(":")[0]
FMT = r"(?P<number>[0-9]{1,3})(?P<letters>[a-zA-Z]{0,3})"
m = re.fullmatch(FMT, name)
d = m.groupdict()
clean_name = "%02d" % int(d["number"])
clean_name += d.get("letters", "")
return clean_name
[docs]
def parse_shot_name(name):
# print(name)
name = name.split(":")[0]
m = re.fullmatch(SHOT_NAME_FMT, name)
if m:
return clean_seq_name(m.group("sequence")), m.group("shot")
m = re.fullmatch(SHOT_NUMBER_FMT, name)
if m:
return None, m.group("shot")
m = re.fullmatch(SEQUENCE_NAME_FMT, name)
if m:
return clean_seq_name(m.group("sequence")), None
return None, None
[docs]
def parse_sequence_name(name):
m = re.search(SEQUENCE_NAME_FMT, name)
if m:
return clean_seq_name(m.group("sequence"))
return None
[docs]
def clean_name(name):
sequence, shot = parse_shot_name(name)
if sequence and shot:
return f"{sequence}_{shot}"
else:
return None
[docs]
def get_target_url(clip):
if not isinstance(clip, otio.schema.Clip):
return None
media_ref = clip.media_reference
if media_ref and isinstance(media_ref, otio.schema.ExternalReference):
return media_ref.target_url
[docs]
def is_aaf(path):
if path.lower().endswith(".aaf"):
return True
return False
[docs]
def simplify_timeline(source_path):
if is_aaf(source_path):
timeline, shot_dict = aaf_extract_shots.simplify_timeline(source_path)
print(1, shot_dict)
result = {}
for shot_name, item in shot_dict.items():
if shot_name:
clean_name = shot_name.split(":")[0]
result[clean_name] = aaf_extract_shots.get_item_timings(item)
return timeline, result
else:
# working with fcp from premiere
print(source_path)
return fcp_extract_shots.simplify_timeline(source_path)
[docs]
def generate_simplified_otio(source_path, otio_path):
print(source_path)
timeline, shot_dict = simplify_timeline(source_path)
if not shot_dict:
raise ValueError(
f"Unable to find shots in timeline.\n"
+ f"Nested sequence labels color might not be set to: SHOT_LABEL_COLOR\n"
+ f"Shots might not be following naming convention"
)
print(f"{timeline.name}")
for shot_name, source_media in shot_dict.items():
print(f" {shot_name}")
for target_url, start_frame, abs_frame, duration in source_media:
print(f" {target_url} {start_frame} {abs_frame} {duration}")
otio.adapters.write_to_file(timeline, otio_path)
return shot_dict
if __name__ == '__main__':
source_path = r"Z:\Alchemy\jhcs\ttas\VERSIONS\0\000\source\shots\103\s01\SEQ\edt\default\tmakota\000.000\high\MDC_103_MonsterOpposites_RC_251021.xml"
dict_ = extract_shot_edit_dict(source_path)
print(dict_.keys())
if __name__ == "__main__":
xml_path = r"E:\Alchemy\jhcs\ttas\VERSIONS\0\000\render\shots\103\s01\SEQ\edt\default\tom\000.000\high\mdc_103.xml"
print(extract_shot_edit_dict(xml_path))