mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
feat(hiero): update otio export import
This commit is contained in:
parent
027f19f9f6
commit
7dfc6a56d8
2 changed files with 83 additions and 49 deletions
|
|
@ -49,6 +49,9 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
return str(type(self))
|
return str(type(self))
|
||||||
|
|
||||||
def get_rate(self, item):
|
def get_rate(self, item):
|
||||||
|
if not hasattr(item, 'framerate'):
|
||||||
|
item = item.sequence()
|
||||||
|
|
||||||
num, den = item.framerate().toRational()
|
num, den = item.framerate().toRational()
|
||||||
rate = float(num) / float(den)
|
rate = float(num) / float(den)
|
||||||
|
|
||||||
|
|
@ -58,12 +61,12 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
return round(rate, 2)
|
return round(rate, 2)
|
||||||
|
|
||||||
def get_clip_ranges(self, trackitem):
|
def get_clip_ranges(self, trackitem):
|
||||||
# Is clip an audio file? Use sequence frame rate
|
# Get rate from source or sequence
|
||||||
if not trackitem.source().mediaSource().hasVideo():
|
if trackitem.source().mediaSource().hasVideo():
|
||||||
rate_item = trackitem.sequence()
|
rate_item = trackitem.source()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
rate_item = trackitem.source()
|
rate_item = trackitem.sequence()
|
||||||
|
|
||||||
source_rate = self.get_rate(rate_item)
|
source_rate = self.get_rate(rate_item)
|
||||||
|
|
||||||
|
|
@ -88,9 +91,10 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
duration=source_duration
|
duration=source_duration
|
||||||
)
|
)
|
||||||
|
|
||||||
available_range = None
|
|
||||||
hiero_clip = trackitem.source()
|
hiero_clip = trackitem.source()
|
||||||
if not hiero_clip.mediaSource().isOffline():
|
|
||||||
|
available_range = None
|
||||||
|
if hiero_clip.mediaSource().isMediaPresent():
|
||||||
start_time = otio.opentime.RationalTime(
|
start_time = otio.opentime.RationalTime(
|
||||||
hiero_clip.mediaSource().startTime(),
|
hiero_clip.mediaSource().startTime(),
|
||||||
source_rate
|
source_rate
|
||||||
|
|
@ -123,7 +127,7 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
|
|
||||||
def get_marker_color(self, tag):
|
def get_marker_color(self, tag):
|
||||||
icon = tag.icon()
|
icon = tag.icon()
|
||||||
pat = 'icons:Tag(?P<color>\w+)\.\w+'
|
pat = r'icons:Tag(?P<color>\w+)\.\w+'
|
||||||
|
|
||||||
res = re.search(pat, icon)
|
res = re.search(pat, icon)
|
||||||
if res:
|
if res:
|
||||||
|
|
@ -155,13 +159,17 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
metadata = dict(
|
||||||
|
Hiero=tag.metadata().dict()
|
||||||
|
)
|
||||||
|
# Store the source item for future import assignment
|
||||||
|
metadata['Hiero']['source_type'] = hiero_item.__class__.__name__
|
||||||
|
|
||||||
marker = otio.schema.Marker(
|
marker = otio.schema.Marker(
|
||||||
name=tag.name(),
|
name=tag.name(),
|
||||||
color=self.get_marker_color(tag),
|
color=self.get_marker_color(tag),
|
||||||
marked_range=marked_range,
|
marked_range=marked_range,
|
||||||
metadata={
|
metadata=metadata
|
||||||
'Hiero': tag.metadata().dict()
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
otio_item.markers.append(marker)
|
otio_item.markers.append(marker)
|
||||||
|
|
@ -170,37 +178,44 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
hiero_clip = trackitem.source()
|
hiero_clip = trackitem.source()
|
||||||
|
|
||||||
# Add Gap if needed
|
# Add Gap if needed
|
||||||
prev_item = (
|
if itemindex == 0:
|
||||||
itemindex and trackitem.parent().items()[itemindex - 1] or
|
prev_item = trackitem
|
||||||
trackitem
|
|
||||||
)
|
|
||||||
|
|
||||||
if prev_item == trackitem and trackitem.timelineIn() > 0:
|
else:
|
||||||
|
prev_item = trackitem.parent().items()[itemindex - 1]
|
||||||
|
|
||||||
|
clip_diff = trackitem.timelineIn() - prev_item.timelineOut()
|
||||||
|
|
||||||
|
if itemindex == 0 and trackitem.timelineIn() > 0:
|
||||||
self.add_gap(trackitem, otio_track, 0)
|
self.add_gap(trackitem, otio_track, 0)
|
||||||
|
|
||||||
elif (
|
elif itemindex and clip_diff != 1:
|
||||||
prev_item != trackitem and
|
|
||||||
prev_item.timelineOut() != trackitem.timelineIn()
|
|
||||||
):
|
|
||||||
self.add_gap(trackitem, otio_track, prev_item.timelineOut())
|
self.add_gap(trackitem, otio_track, prev_item.timelineOut())
|
||||||
|
|
||||||
# Create Clip
|
# Create Clip
|
||||||
source_range, available_range = self.get_clip_ranges(trackitem)
|
source_range, available_range = self.get_clip_ranges(trackitem)
|
||||||
|
|
||||||
otio_clip = otio.schema.Clip()
|
otio_clip = otio.schema.Clip(
|
||||||
otio_clip.name = trackitem.name()
|
name=trackitem.name(),
|
||||||
otio_clip.source_range = source_range
|
source_range=source_range
|
||||||
|
)
|
||||||
|
|
||||||
# Add media reference
|
# Add media reference
|
||||||
media_reference = otio.schema.MissingReference()
|
media_reference = otio.schema.MissingReference()
|
||||||
if not hiero_clip.mediaSource().isOffline():
|
if hiero_clip.mediaSource().isMediaPresent():
|
||||||
source = hiero_clip.mediaSource()
|
source = hiero_clip.mediaSource()
|
||||||
media_reference = otio.schema.ExternalReference()
|
first_file = source.fileinfos()[0]
|
||||||
media_reference.available_range = available_range
|
path = first_file.filename()
|
||||||
|
|
||||||
path, name = os.path.split(source.fileinfos()[0].filename())
|
if "%" in path:
|
||||||
media_reference.target_url = os.path.join(path, name)
|
path = re.sub(r"%\d+d", "%d", path)
|
||||||
media_reference.name = name
|
if "#" in path:
|
||||||
|
path = re.sub(r"#+", "%d", path)
|
||||||
|
|
||||||
|
media_reference = otio.schema.ExternalReference(
|
||||||
|
target_url=u'{}'.format(path),
|
||||||
|
available_range=available_range
|
||||||
|
)
|
||||||
|
|
||||||
otio_clip.media_reference = media_reference
|
otio_clip.media_reference = media_reference
|
||||||
|
|
||||||
|
|
@ -218,6 +233,7 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
|
|
||||||
# Add tags as markers
|
# Add tags as markers
|
||||||
if self._preset.properties()["includeTags"]:
|
if self._preset.properties()["includeTags"]:
|
||||||
|
self.add_markers(trackitem, otio_clip)
|
||||||
self.add_markers(trackitem.source(), otio_clip)
|
self.add_markers(trackitem.source(), otio_clip)
|
||||||
|
|
||||||
otio_track.append(otio_clip)
|
otio_track.append(otio_clip)
|
||||||
|
|
@ -273,16 +289,16 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
name=alignment, # Consider placing Hiero name in metadata
|
name=alignment, # Consider placing Hiero name in metadata
|
||||||
transition_type=otio.schema.TransitionTypes.SMPTE_Dissolve,
|
transition_type=otio.schema.TransitionTypes.SMPTE_Dissolve,
|
||||||
in_offset=in_time,
|
in_offset=in_time,
|
||||||
out_offset=out_time,
|
out_offset=out_time
|
||||||
metadata={}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if alignment == 'kFadeIn':
|
if alignment == 'kFadeIn':
|
||||||
otio_track.insert(-2, otio_transition)
|
otio_track.insert(-1, otio_transition)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
otio_track.append(otio_transition)
|
otio_track.append(otio_transition)
|
||||||
|
|
||||||
|
|
||||||
def add_tracks(self):
|
def add_tracks(self):
|
||||||
for track in self._sequence.items():
|
for track in self._sequence.items():
|
||||||
if isinstance(track, hiero.core.AudioTrack):
|
if isinstance(track, hiero.core.AudioTrack):
|
||||||
|
|
@ -291,8 +307,7 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
else:
|
else:
|
||||||
kind = otio.schema.TrackKind.Video
|
kind = otio.schema.TrackKind.Video
|
||||||
|
|
||||||
otio_track = otio.schema.Track(kind=kind)
|
otio_track = otio.schema.Track(name=track.name(), kind=kind)
|
||||||
otio_track.name = track.name()
|
|
||||||
|
|
||||||
for itemindex, trackitem in enumerate(track):
|
for itemindex, trackitem in enumerate(track):
|
||||||
if isinstance(trackitem.source(), hiero.core.Clip):
|
if isinstance(trackitem.source(), hiero.core.Clip):
|
||||||
|
|
@ -306,6 +321,12 @@ class OTIOExportTask(hiero.core.TaskBase):
|
||||||
|
|
||||||
def create_OTIO(self):
|
def create_OTIO(self):
|
||||||
self.otio_timeline = otio.schema.Timeline()
|
self.otio_timeline = otio.schema.Timeline()
|
||||||
|
|
||||||
|
# Set global start time based on sequence
|
||||||
|
self.otio_timeline.global_start_time = otio.opentime.RationalTime(
|
||||||
|
self._sequence.timecodeStart(),
|
||||||
|
self._sequence.framerate().toFloat()
|
||||||
|
)
|
||||||
self.otio_timeline.name = self._sequence.name()
|
self.otio_timeline.name = self._sequence.name()
|
||||||
|
|
||||||
self.add_tracks()
|
self.add_tracks()
|
||||||
|
|
|
||||||
|
|
@ -356,19 +356,38 @@ def create_trackitem(playhead, track, otio_clip, clip, tagsbin):
|
||||||
return trackitem
|
return trackitem
|
||||||
|
|
||||||
|
|
||||||
def build_sequence(otio_timeline, project=None, track_kind=None):
|
def build_sequence(
|
||||||
|
otio_timeline, project=None, sequence=None, track_kind=None):
|
||||||
|
|
||||||
if project is None:
|
if project is None:
|
||||||
# TODO: Find a proper way for active project
|
if sequence:
|
||||||
project = hiero.core.projects(hiero.core.Project.kUserProjects)[-1]
|
project = sequence.project()
|
||||||
|
|
||||||
# Create a Sequence
|
else:
|
||||||
sequence = hiero.core.Sequence(otio_timeline.name or 'OTIOSequence')
|
# Per version 12.1v2 there is no way of getting active project
|
||||||
|
project = hiero.core.projects(hiero.core.Project.kUserProjects)[-1]
|
||||||
|
|
||||||
# Create a Bin to hold clips
|
|
||||||
projectbin = project.clipsBin()
|
projectbin = project.clipsBin()
|
||||||
projectbin.addItem(hiero.core.BinItem(sequence))
|
|
||||||
sequencebin = hiero.core.Bin(sequence.name())
|
if not sequence:
|
||||||
projectbin.addItem(sequencebin)
|
# Create a Sequence
|
||||||
|
sequence = hiero.core.Sequence(otio_timeline.name or 'OTIOSequence')
|
||||||
|
|
||||||
|
# Set sequence settings from otio timeline if available
|
||||||
|
if hasattr(otio_timeline, 'global_start_time'):
|
||||||
|
if otio_timeline.global_start_time:
|
||||||
|
start_time = otio_timeline.global_start_time
|
||||||
|
sequence.setFramerate(start_time.rate)
|
||||||
|
sequence.setTimecodeStart(start_time.value)
|
||||||
|
|
||||||
|
# Create a Bin to hold clips
|
||||||
|
projectbin.addItem(hiero.core.BinItem(sequence))
|
||||||
|
|
||||||
|
sequencebin = hiero.core.Bin(sequence.name())
|
||||||
|
projectbin.addItem(sequencebin)
|
||||||
|
|
||||||
|
else:
|
||||||
|
sequencebin = projectbin
|
||||||
|
|
||||||
# Get tagsBin
|
# Get tagsBin
|
||||||
tagsbin = hiero.core.project("Tag Presets").tagsBin()
|
tagsbin = hiero.core.project("Tag Presets").tagsBin()
|
||||||
|
|
@ -376,17 +395,11 @@ def build_sequence(otio_timeline, project=None, track_kind=None):
|
||||||
# Add timeline markers
|
# Add timeline markers
|
||||||
add_markers(otio_timeline, sequence, tagsbin)
|
add_markers(otio_timeline, sequence, tagsbin)
|
||||||
|
|
||||||
# add sequence attributes form otio timeline
|
|
||||||
if otio_timeline.global_start_time:
|
|
||||||
sequence.setFramerate(otio_timeline.global_start_time.rate)
|
|
||||||
sequence.setTimecodeStart(otio_timeline.global_start_time.value)
|
|
||||||
|
|
||||||
if isinstance(otio_timeline, otio.schema.Timeline):
|
if isinstance(otio_timeline, otio.schema.Timeline):
|
||||||
tracks = otio_timeline.tracks
|
tracks = otio_timeline.tracks
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# otio.schema.Stack
|
tracks = [otio_timeline]
|
||||||
tracks = otio_timeline
|
|
||||||
|
|
||||||
for tracknum, otio_track in enumerate(tracks):
|
for tracknum, otio_track in enumerate(tracks):
|
||||||
playhead = 0
|
playhead = 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue