From 68db3d9c117df46aaf883a344aef61d26752aa22 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:48:19 +0100 Subject: [PATCH 1/9] Add logic to extract colorspace from metadata if available. - Extract colorspace from media metadata for review clips. - Update instance data with the extracted colorspace information. --- .../plugins/publish/collect_otio_review.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/client/ayon_core/plugins/publish/collect_otio_review.py b/client/ayon_core/plugins/publish/collect_otio_review.py index 69cf9199e7..04422391c5 100644 --- a/client/ayon_core/plugins/publish/collect_otio_review.py +++ b/client/ayon_core/plugins/publish/collect_otio_review.py @@ -95,9 +95,46 @@ class CollectOtioReview(pyblish.api.InstancePlugin): instance.data["label"] = label + " (review)" instance.data["families"] += ["review", "ftrack"] instance.data["otioReviewClips"] = otio_review_clips + self.log.info( "Creating review track: {}".format(otio_review_clips)) + # get colorspace from metadata if available + if len(otio_review_clips) >= 1 and any( + # lets make sure any clip with media reference is found + ( + clip + for clip in otio_review_clips + if isinstance(clip, otio.schema.Clip) + and clip.media_reference + ) + ): + # get metadata from first clip + # get colorspace from metadata if available + # check if resolution is the same as source + r_otio_cl = next( + ( + clip + for clip in otio_review_clips + if isinstance(clip, otio.schema.Clip) + and clip.media_reference + ), + None, + ) + + # get metadata from first clip with media reference + media_ref = r_otio_cl.media_reference + media_metadata = media_ref.metadata + + # TODO: we might need some alternative method since + # native OTIO exports do not support ayon metadata + if review_colorspace := media_metadata.get( + "ayon.source.colorspace" + ): + instance.data["reviewColorspace"] = review_colorspace + self.log.info( + "Review colorspace: {}".format(review_colorspace)) + self.log.debug( "_ instance.data: {}".format(pformat(instance.data))) self.log.debug( From 83f28bf184bfa514294133f01787a47758ca610d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:48:30 +0100 Subject: [PATCH 2/9] Refactor plugin to include Colormanaged mixin The code changes refactor the plugin to include a Colormanaged mixin for managing colorspace data in representations. The mixin is added to the existing plugin class. --- .../plugins/publish/collect_otio_subset_resources.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py index 37a5e87a7a..c142036b83 100644 --- a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py +++ b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py @@ -10,12 +10,16 @@ import os import clique import pyblish.api +from ayon_core.pipeline import publish from ayon_core.pipeline.publish import ( get_publish_template_name ) -class CollectOtioSubsetResources(pyblish.api.InstancePlugin): +class CollectOtioSubsetResources( + pyblish.api.InstancePlugin, + publish.ColormanagedPyblishPluginMixin +): """Get Resources for a product version""" label = "Collect OTIO Subset Resources" @@ -190,9 +194,13 @@ class CollectOtioSubsetResources(pyblish.api.InstancePlugin): instance.data["originalDirname"] = self.staging_dir if repre: + colorspace = instance.data.get("colorspace") + # add colorspace data to representation + self.set_representation_colorspace( + repre, instance.context, colorspace) + # add representation to instance data instance.data["representations"].append(repre) - self.log.debug(">>>>>>>> {}".format(repre)) self.log.debug(instance.data) From 6a635b9d5e0852a77bd2bfaaa28b3ec6d1e8b4d0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:49:03 +0100 Subject: [PATCH 3/9] Update color transcoding process with debug log messages. - Add debug logs for files to convert, transcoded file, and input path. --- client/ayon_core/plugins/publish/extract_color_transcode.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index 3e54d324e3..e7e0c982eb 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -5,7 +5,6 @@ import pyblish.api from ayon_core.pipeline import publish from ayon_core.lib import ( - is_oiio_supported, ) @@ -154,12 +153,15 @@ class ExtractOIIOTranscode(publish.Extractor): files_to_convert = self._translate_to_sequence( files_to_convert) + self.log.debug("Files to convert: {}".format(files_to_convert)) for file_name in files_to_convert: + self.log.debug("Transcoding file: `{}`".format(file_name)) input_path = os.path.join(original_staging_dir, file_name) output_path = self._get_output_file_path(input_path, new_staging_dir, output_extension) + self.log.debug("Ynput path: `{}`".format(input_path)) convert_colorspace( input_path, output_path, From 3a71bbca295d8d2b9d7ab452ac1b3b8f3f26037c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:49:13 +0100 Subject: [PATCH 4/9] Add colorspace data extraction to representation loop Extracts colorspace data from instance data and sets it in the representation loop for processing. --- client/ayon_core/plugins/publish/extract_colorspace_data.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_colorspace_data.py b/client/ayon_core/plugins/publish/extract_colorspace_data.py index 7da4890748..d68ad4d80d 100644 --- a/client/ayon_core/plugins/publish/extract_colorspace_data.py +++ b/client/ayon_core/plugins/publish/extract_colorspace_data.py @@ -37,6 +37,9 @@ class ExtractColorspaceData(publish.Extractor, # get colorspace settings context = instance.context + # colorspace name could be kept in instance.data + colorspace = instance.data.get("colorspace") + # loop representations for representation in representations: # skip if colorspaceData is already at representation @@ -44,5 +47,5 @@ class ExtractColorspaceData(publish.Extractor, continue self.set_representation_colorspace( - representation, context + representation, context, colorspace) ) From 0ff9ae65d8843afa0179277c2c3342fab465cec9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:50:38 +0100 Subject: [PATCH 5/9] Refactor ExtractOTIOReview class inheritance and add colorspace handling - Refactored class inheritance for ExtractOTIOReview - Added handling for colorspace data in representation creation --- .../plugins/publish/extract_otio_review.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/client/ayon_core/plugins/publish/extract_otio_review.py b/client/ayon_core/plugins/publish/extract_otio_review.py index faba9fd36d..2c6472f8a4 100644 --- a/client/ayon_core/plugins/publish/extract_otio_review.py +++ b/client/ayon_core/plugins/publish/extract_otio_review.py @@ -26,7 +26,10 @@ from ayon_core.lib import ( from ayon_core.pipeline import publish -class ExtractOTIOReview(publish.Extractor): +class ExtractOTIOReview( + publish.Extractor, + publish.ColormanagedPyblishPluginMixin +): """ Extract OTIO timeline into one concuted image sequence file. @@ -78,7 +81,9 @@ class ExtractOTIOReview(publish.Extractor): self.used_frames = [] self.workfile_start = int(instance.data.get( "workfileFrameStart", 1001)) - handle_start - self.padding = len(str(self.workfile_start)) + # NOTE: padding has to be converted from + # end frame since start could be lower then 1000 + self.padding = len(str(instance.data.get("frameEnd", 1001))) self.used_frames.append(self.workfile_start) self.to_width = instance.data.get( "resolutionWidth") or self.to_width @@ -86,8 +91,10 @@ class ExtractOTIOReview(publish.Extractor): "resolutionHeight") or self.to_height # skip instance if no reviewable data available - if (not isinstance(otio_review_clips[0], otio.schema.Clip)) \ - and (len(otio_review_clips) == 1): + if ( + not isinstance(otio_review_clips[0], otio.schema.Clip) + and len(otio_review_clips) == 1 + ): self.log.warning( "Instance `{}` has nothing to process".format(instance)) return @@ -168,7 +175,7 @@ class ExtractOTIOReview(publish.Extractor): start -= clip_handle_start duration += clip_handle_start elif len(otio_review_clips) > 1 \ - and (index == len(otio_review_clips) - 1): + and (index == len(otio_review_clips) - 1): # more clips | last clip reframing with handle duration += clip_handle_end elif len(otio_review_clips) == 1: @@ -263,6 +270,13 @@ class ExtractOTIOReview(publish.Extractor): # creating and registering representation representation = self._create_representation(start, duration) + + # add colorspace data to representation + if colorspace := instance.data.get("reviewColorspace"): + self.set_representation_colorspace( + representation, instance.context, colorspace + ) + instance.data["representations"].append(representation) self.log.info("Adding representation: {}".format(representation)) From e0e541b24a01110846ff57b359a66ed8b60af81c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 6 Nov 2024 15:57:24 +0100 Subject: [PATCH 6/9] Refactor colorspace extraction logic - Removed unnecessary closing parenthesis in colorspace extraction method. --- client/ayon_core/plugins/publish/extract_colorspace_data.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_colorspace_data.py b/client/ayon_core/plugins/publish/extract_colorspace_data.py index d68ad4d80d..0ffa0f3035 100644 --- a/client/ayon_core/plugins/publish/extract_colorspace_data.py +++ b/client/ayon_core/plugins/publish/extract_colorspace_data.py @@ -48,4 +48,3 @@ class ExtractColorspaceData(publish.Extractor, self.set_representation_colorspace( representation, context, colorspace) - ) From 46c6511c500804c6d690aaab02ac6c02bdf22b5d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 7 Nov 2024 09:25:22 +0100 Subject: [PATCH 7/9] Refactor debug log in color transcoding function Removed unnecessary debug log statement from color transcoding function. --- client/ayon_core/plugins/publish/extract_color_transcode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_color_transcode.py b/client/ayon_core/plugins/publish/extract_color_transcode.py index e7e0c982eb..56d5d33ea4 100644 --- a/client/ayon_core/plugins/publish/extract_color_transcode.py +++ b/client/ayon_core/plugins/publish/extract_color_transcode.py @@ -161,7 +161,7 @@ class ExtractOIIOTranscode(publish.Extractor): output_path = self._get_output_file_path(input_path, new_staging_dir, output_extension) - self.log.debug("Ynput path: `{}`".format(input_path)) + convert_colorspace( input_path, output_path, From a7908a46e94cf22ca7b42fa5f2dab2657a3e8f13 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 11 Nov 2024 12:50:05 +0100 Subject: [PATCH 8/9] Update handling of missing otioReviewClips data - Handle case where otioReviewClips is missing by logging a message. --- client/ayon_core/plugins/publish/extract_otio_review.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/ayon_core/plugins/publish/extract_otio_review.py b/client/ayon_core/plugins/publish/extract_otio_review.py index 2c6472f8a4..b222c6efc3 100644 --- a/client/ayon_core/plugins/publish/extract_otio_review.py +++ b/client/ayon_core/plugins/publish/extract_otio_review.py @@ -74,7 +74,10 @@ class ExtractOTIOReview( # TODO: what if handles are different in `versionData`? handle_start = instance.data["handleStart"] handle_end = instance.data["handleEnd"] - otio_review_clips = instance.data["otioReviewClips"] + otio_review_clips = instance.data.get("otioReviewClips") + + if otio_review_clips is None: + self.log.info(f"Instance `{instance}` has no otioReviewClips") # add plugin wide attributes self.representation_files = [] From 235949b867aff1f5caf5139e60ec4ca136ae2d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Tue, 12 Nov 2024 15:58:08 +0100 Subject: [PATCH 9/9] Update client/ayon_core/plugins/publish/collect_otio_review.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../plugins/publish/collect_otio_review.py | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/client/ayon_core/plugins/publish/collect_otio_review.py b/client/ayon_core/plugins/publish/collect_otio_review.py index 04422391c5..4708b0a97c 100644 --- a/client/ayon_core/plugins/publish/collect_otio_review.py +++ b/client/ayon_core/plugins/publish/collect_otio_review.py @@ -100,37 +100,33 @@ class CollectOtioReview(pyblish.api.InstancePlugin): "Creating review track: {}".format(otio_review_clips)) # get colorspace from metadata if available - if len(otio_review_clips) >= 1 and any( - # lets make sure any clip with media reference is found + # get metadata from first clip with media reference + r_otio_cl = next( ( clip for clip in otio_review_clips - if isinstance(clip, otio.schema.Clip) - and clip.media_reference - ) - ): - # get metadata from first clip - # get colorspace from metadata if available - # check if resolution is the same as source - r_otio_cl = next( - ( - clip - for clip in otio_review_clips - if isinstance(clip, otio.schema.Clip) + if ( + isinstance(clip, otio.schema.Clip) and clip.media_reference - ), - None, - ) - - # get metadata from first clip with media reference + ) + ), + None + ) + if r_otio_cl is not None: media_ref = r_otio_cl.media_reference media_metadata = media_ref.metadata # TODO: we might need some alternative method since # native OTIO exports do not support ayon metadata - if review_colorspace := media_metadata.get( + review_colorspace = media_metadata.get( "ayon.source.colorspace" - ): + ) + if review_colorspace is None: + # Backwards compatibility for older scenes + review_colorspace = media_metadata.get( + "openpype.source.colourtransform" + ) + if review_colorspace: instance.data["reviewColorspace"] = review_colorspace self.log.info( "Review colorspace: {}".format(review_colorspace))