Merge pull request #3908 from pypeclub/feature/OP-3938_Ftrack-image-review-instead-of-single-frame-video

Photoshop: create single frame image in Ftrack as review
This commit is contained in:
Petr Kalis 2022-10-07 09:27:13 +02:00 committed by GitHub
commit 1c7827aab0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 231 additions and 157 deletions

View file

@ -9,6 +9,7 @@ from openpype.lib.transcoding import (
convert_ffprobe_fps_to_float,
)
from openpype.lib.profiles_filtering import filter_profiles
from openpype.lib.transcoding import VIDEO_EXTENSIONS
class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
@ -121,6 +122,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
review_representations = []
thumbnail_representations = []
other_representations = []
has_movie_review = False
for repre in instance_repres:
self.log.debug("Representation {}".format(repre))
repre_tags = repre.get("tags") or []
@ -129,6 +131,8 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
elif "ftrackreview" in repre_tags:
review_representations.append(repre)
if self._is_repre_video(repre):
has_movie_review = True
else:
other_representations.append(repre)
@ -146,65 +150,53 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
# TODO what if there is multiple thumbnails?
first_thumbnail_component = None
first_thumbnail_component_repre = None
for repre in thumbnail_representations:
repre_path = self._get_repre_path(instance, repre, False)
if not repre_path:
self.log.warning(
"Published path is not set and source was removed."
if has_movie_review:
for repre in thumbnail_representations:
repre_path = self._get_repre_path(instance, repre, False)
if not repre_path:
self.log.warning(
"Published path is not set and source was removed."
)
continue
# Create copy of base comp item and append it
thumbnail_item = copy.deepcopy(base_component_item)
thumbnail_item["component_path"] = repre_path
thumbnail_item["component_data"] = {
"name": "thumbnail"
}
thumbnail_item["thumbnail"] = True
# Create copy of item before setting location
if "delete" not in repre["tags"]:
src_components_to_add.append(copy.deepcopy(thumbnail_item))
# Create copy of first thumbnail
if first_thumbnail_component is None:
first_thumbnail_component_repre = repre
first_thumbnail_component = thumbnail_item
# Set location
thumbnail_item["component_location_name"] = (
ftrack_server_location_name
)
continue
# Create copy of base comp item and append it
thumbnail_item = copy.deepcopy(base_component_item)
thumbnail_item["component_path"] = repre_path
thumbnail_item["component_data"] = {
"name": "thumbnail"
}
thumbnail_item["thumbnail"] = True
# Create copy of item before setting location
src_components_to_add.append(copy.deepcopy(thumbnail_item))
# Create copy of first thumbnail
if first_thumbnail_component is None:
first_thumbnail_component_repre = repre
first_thumbnail_component = thumbnail_item
# Set location
thumbnail_item["component_location_name"] = (
ftrack_server_location_name
)
# Add item to component list
component_list.append(thumbnail_item)
# Add item to component list
component_list.append(thumbnail_item)
if first_thumbnail_component is not None:
width = first_thumbnail_component_repre.get("width")
height = first_thumbnail_component_repre.get("height")
if not width or not height:
component_path = first_thumbnail_component["component_path"]
streams = []
try:
streams = get_ffprobe_streams(component_path)
except Exception:
self.log.debug((
"Failed to retrieve information about intput {}"
).format(component_path))
metadata = self._prepare_image_component_metadata(
first_thumbnail_component_repre,
first_thumbnail_component["component_path"]
)
for stream in streams:
if "width" in stream and "height" in stream:
width = stream["width"]
height = stream["height"]
break
if width and height:
if metadata:
component_data = first_thumbnail_component["component_data"]
component_data["name"] = "ftrackreview-image"
component_data["metadata"] = {
"ftr_meta": json.dumps({
"width": width,
"height": height,
"format": "image"
})
}
component_data["metadata"] = metadata
if review_representations:
component_data["name"] = "thumbnail"
else:
component_data["name"] = "ftrackreview-image"
# Create review components
# Change asset name of each new component for review
@ -213,6 +205,11 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
extended_asset_name = ""
multiple_reviewable = len(review_representations) > 1
for repre in review_representations:
if not self._is_repre_video(repre) and has_movie_review:
self.log.debug("Movie repre has priority "
"from {}".format(repre))
continue
repre_path = self._get_repre_path(instance, repre, False)
if not repre_path:
self.log.warning(
@ -261,12 +258,23 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
# Change location
review_item["component_path"] = repre_path
# Change component data
review_item["component_data"] = {
# Default component name is "main".
"name": "ftrackreview-mp4",
"metadata": self._prepare_component_metadata(
if self._is_repre_video(repre):
component_name = "ftrackreview-mp4"
metadata = self._prepare_video_component_metadata(
instance, repre, repre_path, True
)
else:
component_name = "ftrackreview-image"
metadata = self._prepare_image_component_metadata(
repre, repre_path
)
review_item["thumbnail"] = True
review_item["component_data"] = {
# Default component name is "main".
"name": component_name,
"metadata": metadata
}
if is_first_review_repre:
@ -276,7 +284,8 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
not_first_components.append(review_item)
# Create copy of item before setting location
src_components_to_add.append(copy.deepcopy(review_item))
if "delete" not in repre["tags"]:
src_components_to_add.append(copy.deepcopy(review_item))
# Set location
review_item["component_location_name"] = (
@ -422,7 +431,18 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
return matching_profile["status"] or None
def _prepare_component_metadata(
self, instance, repre, component_path, is_review
self, instance, repre, component_path, is_review=None
):
if self._is_repre_video(repre):
return self._prepare_video_component_metadata(instance, repre,
component_path,
is_review)
else:
return self._prepare_image_component_metadata(repre,
component_path)
def _prepare_video_component_metadata(
self, instance, repre, component_path, is_review=None
):
metadata = {}
if "openpype_version" in self.additional_metadata_keys:
@ -434,9 +454,9 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
try:
streams = get_ffprobe_streams(component_path)
except Exception:
self.log.debug((
"Failed to retrieve information about intput {}"
).format(component_path))
self.log.debug(
"Failed to retrieve information about "
"input {}".format(component_path))
# Find video streams
video_streams = [
@ -480,9 +500,9 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
input_framerate
)
except ValueError:
self.log.warning((
"Could not convert ffprobe fps to float \"{}\""
).format(input_framerate))
self.log.warning(
"Could not convert ffprobe "
"fps to float \"{}\"".format(input_framerate))
continue
stream_width = tmp_width
@ -554,3 +574,37 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin):
"frameRate": float(fps)
})
return metadata
def _prepare_image_component_metadata(self, repre, component_path):
width = repre.get("width")
height = repre.get("height")
if not width or not height:
streams = []
try:
streams = get_ffprobe_streams(component_path)
except Exception:
self.log.debug(
"Failed to retrieve information "
"about input {}".format(component_path))
for stream in streams:
if "width" in stream and "height" in stream:
width = stream["width"]
height = stream["height"]
break
metadata = {}
if width and height:
metadata = {
"ftr_meta": json.dumps({
"width": width,
"height": height,
"format": "image"
})
}
return metadata
def _is_repre_video(self, repre):
repre_ext = ".{}".format(repre["ext"])
return repre_ext in VIDEO_EXTENSIONS