diff --git a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py index b8489de758..5db89a0ab9 100644 --- a/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py +++ b/openpype/hosts/flame/plugins/publish/collect_timeline_instances.py @@ -3,7 +3,10 @@ from types import NoneType import pyblish import openpype.hosts.flame.api as opfapi from openpype.hosts.flame.otio import flame_export -import openpype.lib as oplib +from openpype.pipeline.editorial import ( + is_overlapping_otio_ranges, + get_media_range_with_retimes +) # # developer reload modules from pprint import pformat @@ -279,7 +282,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): # HACK: it is here to serve for versions bellow 2021.1 if not any([head, tail]): - retimed_attributes = oplib.get_media_range_with_retimes( + retimed_attributes = get_media_range_with_retimes( otio_clip, handle_start, handle_end) self.log.debug( ">> retimed_attributes: {}".format(retimed_attributes)) @@ -378,7 +381,7 @@ class CollectTimelineInstances(pyblish.api.ContextPlugin): continue if otio_clip.name not in segment.name.get_value(): continue - if oplib.is_overlapping_otio_ranges( + if is_overlapping_otio_ranges( parent_range, timeline_range, strict=True): # add pypedata marker to otio_clip metadata diff --git a/openpype/hosts/hiero/plugins/publish/precollect_instances.py b/openpype/hosts/hiero/plugins/publish/precollect_instances.py index b891a37d9d..2d0ec6fc99 100644 --- a/openpype/hosts/hiero/plugins/publish/precollect_instances.py +++ b/openpype/hosts/hiero/plugins/publish/precollect_instances.py @@ -1,5 +1,5 @@ import pyblish -import openpype +from openpype.pipeline.editorial import is_overlapping_otio_ranges from openpype.hosts.hiero import api as phiero from openpype.hosts.hiero.api.otio import hiero_export import hiero @@ -275,7 +275,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): parent_range = otio_audio.range_in_parent() # if any overaling clip found then return True - if openpype.lib.is_overlapping_otio_ranges( + if is_overlapping_otio_ranges( parent_range, timeline_range, strict=False): return True @@ -304,7 +304,7 @@ class PrecollectInstances(pyblish.api.ContextPlugin): continue self.log.debug("__ parent_range: {}".format(parent_range)) self.log.debug("__ timeline_range: {}".format(timeline_range)) - if openpype.lib.is_overlapping_otio_ranges( + if is_overlapping_otio_ranges( parent_range, timeline_range, strict=True): # add pypedata marker to otio_clip metadata diff --git a/openpype/hosts/resolve/api/lib.py b/openpype/hosts/resolve/api/lib.py index 22f83c6eed..c4717bd370 100644 --- a/openpype/hosts/resolve/api/lib.py +++ b/openpype/hosts/resolve/api/lib.py @@ -4,7 +4,7 @@ import re import os import contextlib from opentimelineio import opentime -import openpype +from openpype.pipeline.editorial import is_overlapping_otio_ranges from ..otio import davinci_export as otio_export @@ -824,7 +824,7 @@ def get_otio_clip_instance_data(otio_timeline, timeline_item_data): continue if otio_clip.name not in timeline_item.GetName(): continue - if openpype.lib.is_overlapping_otio_ranges( + if is_overlapping_otio_ranges( parent_range, timeline_range, strict=True): # add pypedata marker to otio_clip metadata diff --git a/openpype/lib/editorial.py b/openpype/lib/editorial.py index 32d6dc3688..49220b4f15 100644 --- a/openpype/lib/editorial.py +++ b/openpype/lib/editorial.py @@ -1,289 +1,102 @@ -import os -import re -import clique -from .import_utils import discover_host_vendor_module +"""Code related to editorial utility functions was moved +to 'openpype.pipeline.editorial' please change your imports as soon as +possible. File will be probably removed in OpenPype 3.14.* +""" -try: - import opentimelineio as otio - from opentimelineio import opentime as _ot -except ImportError: - if not os.environ.get("AVALON_APP"): - raise - otio = discover_host_vendor_module("opentimelineio") - _ot = discover_host_vendor_module("opentimelineio.opentime") +import warnings +import functools -def otio_range_to_frame_range(otio_range): - start = _ot.to_frames( - otio_range.start_time, otio_range.start_time.rate) - end = start + _ot.to_frames( - otio_range.duration, otio_range.duration.rate) - return start, end +class EditorialDeprecatedWarning(DeprecationWarning): + pass -def otio_range_with_handles(otio_range, instance): - handle_start = instance.data["handleStart"] - handle_end = instance.data["handleEnd"] - handles_duration = handle_start + handle_end - fps = float(otio_range.start_time.rate) - start = _ot.to_frames(otio_range.start_time, fps) - duration = _ot.to_frames(otio_range.duration, fps) +def editorial_deprecated(func): + """Mark functions as deprecated. - return _ot.TimeRange( - start_time=_ot.RationalTime((start - handle_start), fps), - duration=_ot.RationalTime((duration + handles_duration), fps) - ) - - -def is_overlapping_otio_ranges(test_otio_range, main_otio_range, strict=False): - test_start, test_end = otio_range_to_frame_range(test_otio_range) - main_start, main_end = otio_range_to_frame_range(main_otio_range) - covering_exp = bool( - (test_start <= main_start) and (test_end >= main_end) - ) - inside_exp = bool( - (test_start >= main_start) and (test_end <= main_end) - ) - overlaying_right_exp = bool( - (test_start <= main_end) and (test_end >= main_end) - ) - overlaying_left_exp = bool( - (test_end >= main_start) and (test_start <= main_start) - ) - - if not strict: - return any(( - covering_exp, - inside_exp, - overlaying_right_exp, - overlaying_left_exp - )) - else: - return covering_exp - - -def convert_to_padded_path(path, padding): + It will result in a warning being emitted when the function is used. """ - Return correct padding in sequence string - Args: - path (str): path url or simple file name - padding (int): number of padding - - Returns: - type: string with reformated path - - Example: - convert_to_padded_path("plate.%d.exr") > plate.%04d.exr - - """ - if "%d" in path: - path = re.sub("%d", "%0{padding}d".format(padding=padding), path) - return path + @functools.wraps(func) + def new_func(*args, **kwargs): + warnings.simplefilter("always", EditorialDeprecatedWarning) + warnings.warn( + ( + "Call to deprecated function '{}'." + " Function was moved to 'openpype.pipeline.editorial'." + ).format(func.__name__), + category=EditorialDeprecatedWarning, + stacklevel=2 + ) + return func(*args, **kwargs) + return new_func -def trim_media_range(media_range, source_range): - """ - Trim input media range with clip source range. +@editorial_deprecated +def otio_range_to_frame_range(*args, **kwargs): + from openpype.pipeline.editorial import otio_range_to_frame_range - Args: - media_range (otio._ot._ot.TimeRange): available range of media - source_range (otio._ot._ot.TimeRange): clip required range - - Returns: - otio._ot._ot.TimeRange: trimmed media range - - """ - rw_media_start = _ot.RationalTime( - media_range.start_time.value + source_range.start_time.value, - media_range.start_time.rate - ) - rw_media_duration = _ot.RationalTime( - source_range.duration.value, - media_range.duration.rate - ) - return _ot.TimeRange( - rw_media_start, rw_media_duration) + return otio_range_to_frame_range(*args, **kwargs) -def range_from_frames(start, duration, fps): - """ - Returns otio time range. +@editorial_deprecated +def otio_range_with_handles(*args, **kwargs): + from openpype.pipeline.editorial import otio_range_with_handles - Args: - start (int): frame start - duration (int): frame duration - fps (float): frame range - - Returns: - otio._ot._ot.TimeRange: created range - - """ - return _ot.TimeRange( - _ot.RationalTime(start, fps), - _ot.RationalTime(duration, fps) - ) + return otio_range_with_handles(*args, **kwargs) -def frames_to_secons(frames, framerate): - """ - Returning secons. +@editorial_deprecated +def is_overlapping_otio_ranges(*args, **kwargs): + from openpype.pipeline.editorial import is_overlapping_otio_ranges - Args: - frames (int): frame - framerate (float): frame rate - - Returns: - float: second value - - """ - rt = _ot.from_frames(frames, framerate) - return _ot.to_seconds(rt) + return is_overlapping_otio_ranges(*args, **kwargs) -def frames_to_timecode(frames, framerate): - rt = _ot.from_frames(frames, framerate) - return _ot.to_timecode(rt) +@editorial_deprecated +def convert_to_padded_path(*args, **kwargs): + from openpype.pipeline.editorial import convert_to_padded_path + + return convert_to_padded_path(*args, **kwargs) -def make_sequence_collection(path, otio_range, metadata): - """ - Make collection from path otio range and otio metadata. +@editorial_deprecated +def trim_media_range(*args, **kwargs): + from openpype.pipeline.editorial import trim_media_range - Args: - path (str): path to image sequence with `%d` - otio_range (otio._ot._ot.TimeRange): range to be used - metadata (dict): data where padding value can be found - - Returns: - list: dir_path (str): path to sequence, collection object - - """ - if "%" not in path: - return None - file_name = os.path.basename(path) - dir_path = os.path.dirname(path) - head = file_name.split("%")[0] - tail = os.path.splitext(file_name)[-1] - first, last = otio_range_to_frame_range(otio_range) - collection = clique.Collection( - head=head, tail=tail, padding=metadata["padding"]) - collection.indexes.update([i for i in range(first, last)]) - return dir_path, collection + return trim_media_range(*args, **kwargs) -def _sequence_resize(source, length): - step = float(len(source) - 1) / (length - 1) - for i in range(length): - low, ratio = divmod(i * step, 1) - high = low + 1 if ratio > 0 else low - yield (1 - ratio) * source[int(low)] + ratio * source[int(high)] +@editorial_deprecated +def range_from_frames(*args, **kwargs): + from openpype.pipeline.editorial import range_from_frames + + return range_from_frames(*args, **kwargs) -def get_media_range_with_retimes(otio_clip, handle_start, handle_end): - source_range = otio_clip.source_range - available_range = otio_clip.available_range() - media_in = available_range.start_time.value - media_out = available_range.end_time_inclusive().value +@editorial_deprecated +def frames_to_secons(*args, **kwargs): + from openpype.pipeline.editorial import frames_to_seconds - # modifiers - time_scalar = 1. - offset_in = 0 - offset_out = 0 - time_warp_nodes = [] + return frames_to_seconds(*args, **kwargs) - # Check for speed effects and adjust playback speed accordingly - for effect in otio_clip.effects: - if isinstance(effect, otio.schema.LinearTimeWarp): - time_scalar = effect.time_scalar - elif isinstance(effect, otio.schema.FreezeFrame): - # For freeze frame, playback speed must be set after range - time_scalar = 0. +@editorial_deprecated +def frames_to_timecode(*args, **kwargs): + from openpype.pipeline.editorial import frames_to_timecode - elif isinstance(effect, otio.schema.TimeEffect): - # For freeze frame, playback speed must be set after range - name = effect.name - effect_name = effect.effect_name - if "TimeWarp" not in effect_name: - continue - metadata = effect.metadata - lookup = metadata.get("lookup") - if not lookup: - continue + return frames_to_timecode(*args, **kwargs) - # time warp node - tw_node = { - "Class": "TimeWarp", - "name": name - } - tw_node.update(metadata) - tw_node["lookup"] = list(lookup) - # get first and last frame offsets - offset_in += lookup[0] - offset_out += lookup[-1] +@editorial_deprecated +def make_sequence_collection(*args, **kwargs): + from openpype.pipeline.editorial import make_sequence_collection - # add to timewarp nodes - time_warp_nodes.append(tw_node) + return make_sequence_collection(*args, **kwargs) - # multiply by time scalar - offset_in *= time_scalar - offset_out *= time_scalar - # filip offset if reversed speed - if time_scalar < 0: - _offset_in = offset_out - _offset_out = offset_in - offset_in = _offset_in - offset_out = _offset_out +@editorial_deprecated +def get_media_range_with_retimes(*args, **kwargs): + from openpype.pipeline.editorial import get_media_range_with_retimes - # scale handles - handle_start *= abs(time_scalar) - handle_end *= abs(time_scalar) - - # filip handles if reversed speed - if time_scalar < 0: - _handle_start = handle_end - _handle_end = handle_start - handle_start = _handle_start - handle_end = _handle_end - - source_in = source_range.start_time.value - - media_in_trimmed = ( - media_in + source_in + offset_in) - media_out_trimmed = ( - media_in + source_in + ( - ((source_range.duration.value - 1) * abs( - time_scalar)) + offset_out)) - - # calculate available handles - if (media_in_trimmed - media_in) < handle_start: - handle_start = (media_in_trimmed - media_in) - if (media_out - media_out_trimmed) < handle_end: - handle_end = (media_out - media_out_trimmed) - - # create version data - version_data = { - "versionData": { - "retime": True, - "speed": time_scalar, - "timewarps": time_warp_nodes, - "handleStart": round(handle_start), - "handleEnd": round(handle_end) - } - } - - returning_dict = { - "mediaIn": media_in_trimmed, - "mediaOut": media_out_trimmed, - "handleStart": round(handle_start), - "handleEnd": round(handle_end) - } - - # add version data only if retime - if time_warp_nodes or time_scalar != 1.: - returning_dict.update(version_data) - - return returning_dict + return get_media_range_with_retimes(*args, **kwargs) diff --git a/openpype/lib/import_utils.py b/openpype/lib/import_utils.py deleted file mode 100644 index e88c07fca6..0000000000 --- a/openpype/lib/import_utils.py +++ /dev/null @@ -1,25 +0,0 @@ -import os -import sys -import importlib -from .log import PypeLogger as Logger - -log = Logger().get_logger(__name__) - - -def discover_host_vendor_module(module_name): - host = os.environ["AVALON_APP"] - pype_root = os.environ["OPENPYPE_REPOS_ROOT"] - main_module = module_name.split(".")[0] - module_path = os.path.join( - pype_root, "hosts", host, "vendor", main_module) - - log.debug( - "Importing module from host vendor path: `{}`".format(module_path)) - - if not os.path.exists(module_path): - log.warning( - "Path not existing: `{}`".format(module_path)) - return None - - sys.path.insert(1, module_path) - return importlib.import_module(module_name) diff --git a/openpype/pipeline/editorial.py b/openpype/pipeline/editorial.py new file mode 100644 index 0000000000..f62a1842e0 --- /dev/null +++ b/openpype/pipeline/editorial.py @@ -0,0 +1,282 @@ +import os +import re +import clique + +import opentimelineio as otio +from opentimelineio import opentime as _ot + + +def otio_range_to_frame_range(otio_range): + start = _ot.to_frames( + otio_range.start_time, otio_range.start_time.rate) + end = start + _ot.to_frames( + otio_range.duration, otio_range.duration.rate) + return start, end + + +def otio_range_with_handles(otio_range, instance): + handle_start = instance.data["handleStart"] + handle_end = instance.data["handleEnd"] + handles_duration = handle_start + handle_end + fps = float(otio_range.start_time.rate) + start = _ot.to_frames(otio_range.start_time, fps) + duration = _ot.to_frames(otio_range.duration, fps) + + return _ot.TimeRange( + start_time=_ot.RationalTime((start - handle_start), fps), + duration=_ot.RationalTime((duration + handles_duration), fps) + ) + + +def is_overlapping_otio_ranges(test_otio_range, main_otio_range, strict=False): + test_start, test_end = otio_range_to_frame_range(test_otio_range) + main_start, main_end = otio_range_to_frame_range(main_otio_range) + covering_exp = bool( + (test_start <= main_start) and (test_end >= main_end) + ) + inside_exp = bool( + (test_start >= main_start) and (test_end <= main_end) + ) + overlaying_right_exp = bool( + (test_start <= main_end) and (test_end >= main_end) + ) + overlaying_left_exp = bool( + (test_end >= main_start) and (test_start <= main_start) + ) + + if not strict: + return any(( + covering_exp, + inside_exp, + overlaying_right_exp, + overlaying_left_exp + )) + else: + return covering_exp + + +def convert_to_padded_path(path, padding): + """ + Return correct padding in sequence string + + Args: + path (str): path url or simple file name + padding (int): number of padding + + Returns: + type: string with reformated path + + Example: + convert_to_padded_path("plate.%d.exr") > plate.%04d.exr + + """ + if "%d" in path: + path = re.sub("%d", "%0{padding}d".format(padding=padding), path) + return path + + +def trim_media_range(media_range, source_range): + """ + Trim input media range with clip source range. + + Args: + media_range (otio._ot._ot.TimeRange): available range of media + source_range (otio._ot._ot.TimeRange): clip required range + + Returns: + otio._ot._ot.TimeRange: trimmed media range + + """ + rw_media_start = _ot.RationalTime( + media_range.start_time.value + source_range.start_time.value, + media_range.start_time.rate + ) + rw_media_duration = _ot.RationalTime( + source_range.duration.value, + media_range.duration.rate + ) + return _ot.TimeRange( + rw_media_start, rw_media_duration) + + +def range_from_frames(start, duration, fps): + """ + Returns otio time range. + + Args: + start (int): frame start + duration (int): frame duration + fps (float): frame range + + Returns: + otio._ot._ot.TimeRange: created range + + """ + return _ot.TimeRange( + _ot.RationalTime(start, fps), + _ot.RationalTime(duration, fps) + ) + + +def frames_to_seconds(frames, framerate): + """ + Returning seconds. + + Args: + frames (int): frame + framerate (float): frame rate + + Returns: + float: second value + """ + + rt = _ot.from_frames(frames, framerate) + return _ot.to_seconds(rt) + + +def frames_to_timecode(frames, framerate): + rt = _ot.from_frames(frames, framerate) + return _ot.to_timecode(rt) + + +def make_sequence_collection(path, otio_range, metadata): + """ + Make collection from path otio range and otio metadata. + + Args: + path (str): path to image sequence with `%d` + otio_range (otio._ot._ot.TimeRange): range to be used + metadata (dict): data where padding value can be found + + Returns: + list: dir_path (str): path to sequence, collection object + + """ + if "%" not in path: + return None + file_name = os.path.basename(path) + dir_path = os.path.dirname(path) + head = file_name.split("%")[0] + tail = os.path.splitext(file_name)[-1] + first, last = otio_range_to_frame_range(otio_range) + collection = clique.Collection( + head=head, tail=tail, padding=metadata["padding"]) + collection.indexes.update([i for i in range(first, last)]) + return dir_path, collection + + +def _sequence_resize(source, length): + step = float(len(source) - 1) / (length - 1) + for i in range(length): + low, ratio = divmod(i * step, 1) + high = low + 1 if ratio > 0 else low + yield (1 - ratio) * source[int(low)] + ratio * source[int(high)] + + +def get_media_range_with_retimes(otio_clip, handle_start, handle_end): + source_range = otio_clip.source_range + available_range = otio_clip.available_range() + media_in = available_range.start_time.value + media_out = available_range.end_time_inclusive().value + + # modifiers + time_scalar = 1. + offset_in = 0 + offset_out = 0 + time_warp_nodes = [] + + # Check for speed effects and adjust playback speed accordingly + for effect in otio_clip.effects: + if isinstance(effect, otio.schema.LinearTimeWarp): + time_scalar = effect.time_scalar + + elif isinstance(effect, otio.schema.FreezeFrame): + # For freeze frame, playback speed must be set after range + time_scalar = 0. + + elif isinstance(effect, otio.schema.TimeEffect): + # For freeze frame, playback speed must be set after range + name = effect.name + effect_name = effect.effect_name + if "TimeWarp" not in effect_name: + continue + metadata = effect.metadata + lookup = metadata.get("lookup") + if not lookup: + continue + + # time warp node + tw_node = { + "Class": "TimeWarp", + "name": name + } + tw_node.update(metadata) + tw_node["lookup"] = list(lookup) + + # get first and last frame offsets + offset_in += lookup[0] + offset_out += lookup[-1] + + # add to timewarp nodes + time_warp_nodes.append(tw_node) + + # multiply by time scalar + offset_in *= time_scalar + offset_out *= time_scalar + + # filip offset if reversed speed + if time_scalar < 0: + _offset_in = offset_out + _offset_out = offset_in + offset_in = _offset_in + offset_out = _offset_out + + # scale handles + handle_start *= abs(time_scalar) + handle_end *= abs(time_scalar) + + # filip handles if reversed speed + if time_scalar < 0: + _handle_start = handle_end + _handle_end = handle_start + handle_start = _handle_start + handle_end = _handle_end + + source_in = source_range.start_time.value + + media_in_trimmed = ( + media_in + source_in + offset_in) + media_out_trimmed = ( + media_in + source_in + ( + ((source_range.duration.value - 1) * abs( + time_scalar)) + offset_out)) + + # calculate available handles + if (media_in_trimmed - media_in) < handle_start: + handle_start = (media_in_trimmed - media_in) + if (media_out - media_out_trimmed) < handle_end: + handle_end = (media_out - media_out_trimmed) + + # create version data + version_data = { + "versionData": { + "retime": True, + "speed": time_scalar, + "timewarps": time_warp_nodes, + "handleStart": round(handle_start), + "handleEnd": round(handle_end) + } + } + + returning_dict = { + "mediaIn": media_in_trimmed, + "mediaOut": media_out_trimmed, + "handleStart": round(handle_start), + "handleEnd": round(handle_end) + } + + # add version data only if retime + if time_warp_nodes or time_scalar != 1.: + returning_dict.update(version_data) + + return returning_dict diff --git a/openpype/plugins/publish/collect_otio_frame_ranges.py b/openpype/plugins/publish/collect_otio_frame_ranges.py index 8eaf9d6f29..c86e777850 100644 --- a/openpype/plugins/publish/collect_otio_frame_ranges.py +++ b/openpype/plugins/publish/collect_otio_frame_ranges.py @@ -8,8 +8,11 @@ Requires: # import os import opentimelineio as otio import pyblish.api -import openpype.lib from pprint import pformat +from openpype.pipeline.editorial import ( + otio_range_to_frame_range, + otio_range_with_handles +) class CollectOtioFrameRanges(pyblish.api.InstancePlugin): @@ -31,9 +34,9 @@ class CollectOtioFrameRanges(pyblish.api.InstancePlugin): otio_tl_range = otio_clip.range_in_parent() otio_src_range = otio_clip.source_range otio_avalable_range = otio_clip.available_range() - otio_tl_range_handles = openpype.lib.otio_range_with_handles( + otio_tl_range_handles = otio_range_with_handles( otio_tl_range, instance) - otio_src_range_handles = openpype.lib.otio_range_with_handles( + otio_src_range_handles = otio_range_with_handles( otio_src_range, instance) # get source avalable start frame @@ -42,7 +45,7 @@ class CollectOtioFrameRanges(pyblish.api.InstancePlugin): otio_avalable_range.start_time.rate) # convert to frames - range_convert = openpype.lib.otio_range_to_frame_range + range_convert = otio_range_to_frame_range tl_start, tl_end = range_convert(otio_tl_range) tl_start_h, tl_end_h = range_convert(otio_tl_range_handles) src_start, src_end = range_convert(otio_src_range) diff --git a/openpype/plugins/publish/collect_otio_subset_resources.py b/openpype/plugins/publish/collect_otio_subset_resources.py index 40d4f35bdc..fc6a9b50f2 100644 --- a/openpype/plugins/publish/collect_otio_subset_resources.py +++ b/openpype/plugins/publish/collect_otio_subset_resources.py @@ -10,7 +10,11 @@ import os import clique import opentimelineio as otio import pyblish.api -import openpype.lib as oplib +from openpype.pipeline.editorial import ( + get_media_range_with_retimes, + range_from_frames, + make_sequence_collection +) class CollectOtioSubsetResources(pyblish.api.InstancePlugin): @@ -42,7 +46,7 @@ class CollectOtioSubsetResources(pyblish.api.InstancePlugin): available_duration = otio_avalable_range.duration.value # get available range trimmed with processed retimes - retimed_attributes = oplib.get_media_range_with_retimes( + retimed_attributes = get_media_range_with_retimes( otio_clip, handle_start, handle_end) self.log.debug( ">> retimed_attributes: {}".format(retimed_attributes)) @@ -64,7 +68,7 @@ class CollectOtioSubsetResources(pyblish.api.InstancePlugin): a_frame_end_h = media_out + handle_end # create trimmed otio time range - trimmed_media_range_h = oplib.range_from_frames( + trimmed_media_range_h = range_from_frames( a_frame_start_h, (a_frame_end_h - a_frame_start_h) + 1, media_fps ) @@ -144,7 +148,7 @@ class CollectOtioSubsetResources(pyblish.api.InstancePlugin): # in case it is file sequence but not new OTIO schema # `ImageSequenceReference` path = media_ref.target_url - collection_data = oplib.make_sequence_collection( + collection_data = make_sequence_collection( path, trimmed_media_range_h, metadata) self.staging_dir, collection = collection_data diff --git a/openpype/plugins/publish/extract_otio_review.py b/openpype/plugins/publish/extract_otio_review.py index 35adc97442..2ce5323468 100644 --- a/openpype/plugins/publish/extract_otio_review.py +++ b/openpype/plugins/publish/extract_otio_review.py @@ -19,6 +19,13 @@ import clique import opentimelineio as otio from pyblish import api import openpype +from openpype.pipeline.editorial import ( + otio_range_to_frame_range, + trim_media_range, + range_from_frames, + frames_to_seconds, + make_sequence_collection +) class ExtractOTIOReview(openpype.api.Extractor): @@ -161,7 +168,7 @@ class ExtractOTIOReview(openpype.api.Extractor): dirname = media_ref.target_url_base head = media_ref.name_prefix tail = media_ref.name_suffix - first, last = openpype.lib.otio_range_to_frame_range( + first, last = otio_range_to_frame_range( available_range) collection = clique.Collection( head=head, @@ -180,7 +187,7 @@ class ExtractOTIOReview(openpype.api.Extractor): # in case it is file sequence but not new OTIO schema # `ImageSequenceReference` path = media_ref.target_url - collection_data = openpype.lib.make_sequence_collection( + collection_data = make_sequence_collection( path, available_range, metadata) dir_path, collection = collection_data @@ -305,8 +312,8 @@ class ExtractOTIOReview(openpype.api.Extractor): duration = avl_durtation # return correct trimmed range - return openpype.lib.trim_media_range( - avl_range, openpype.lib.range_from_frames(start, duration, fps) + return trim_media_range( + avl_range, range_from_frames(start, duration, fps) ) def _render_seqment(self, sequence=None, @@ -357,8 +364,8 @@ class ExtractOTIOReview(openpype.api.Extractor): frame_start = otio_range.start_time.value input_fps = otio_range.start_time.rate frame_duration = otio_range.duration.value - sec_start = openpype.lib.frames_to_secons(frame_start, input_fps) - sec_duration = openpype.lib.frames_to_secons( + sec_start = frames_to_seconds(frame_start, input_fps) + sec_duration = frames_to_seconds( frame_duration, input_fps ) @@ -370,8 +377,7 @@ class ExtractOTIOReview(openpype.api.Extractor): ]) elif gap: - sec_duration = openpype.lib.frames_to_secons( - gap, self.actual_fps) + sec_duration = frames_to_seconds(gap, self.actual_fps) # form command for rendering gap files command.extend([ diff --git a/openpype/plugins/publish/extract_otio_trimming_video.py b/openpype/plugins/publish/extract_otio_trimming_video.py index e8e2994f36..19625fa568 100644 --- a/openpype/plugins/publish/extract_otio_trimming_video.py +++ b/openpype/plugins/publish/extract_otio_trimming_video.py @@ -9,6 +9,7 @@ import os from pyblish import api import openpype from copy import deepcopy +from openpype.pipeline.editorial import frames_to_seconds class ExtractOTIOTrimmingVideo(openpype.api.Extractor): @@ -81,8 +82,8 @@ class ExtractOTIOTrimmingVideo(openpype.api.Extractor): frame_start = otio_range.start_time.value input_fps = otio_range.start_time.rate frame_duration = otio_range.duration.value - 1 - sec_start = openpype.lib.frames_to_secons(frame_start, input_fps) - sec_duration = openpype.lib.frames_to_secons(frame_duration, input_fps) + sec_start = frames_to_seconds(frame_start, input_fps) + sec_duration = frames_to_seconds(frame_duration, input_fps) # form command for rendering gap files command.extend([