Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

General: Extract review single frame output #4064

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 45 additions & 14 deletions openpype/plugins/publish/extract_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
import copy
import json
import shutil

from abc import ABCMeta, abstractmethod
import six

import six
import clique

import speedcopy
import pyblish.api

from openpype.lib import (
get_ffmpeg_tool_path,
get_ffprobe_streams,

path_to_subprocess_arg,
run_subprocess,

)
from openpype.lib.transcoding import (
IMAGE_EXTENSIONS,
get_ffprobe_streams,
should_convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
get_transcode_temp_directory
get_transcode_temp_directory,
)
import speedcopy


class ExtractReview(pyblish.api.InstancePlugin):
Expand Down Expand Up @@ -175,6 +175,26 @@ def _get_outputs_per_representations(self, instance, profile_outputs):
outputs_per_representations.append((repre, outputs))
return outputs_per_representations

def _single_frame_filter(self, input_filepaths, output_defs):
single_frame_image = False
if len(input_filepaths) == 1:
ext = os.path.splitext(input_filepaths[0])[-1]
single_frame_image = ext in IMAGE_EXTENSIONS

filtered_defs = []
for output_def in output_defs:
output_filters = output_def.get("filter") or {}
frame_filter = output_filters.get("single_frame_filter")
if (
(not single_frame_image and frame_filter == "single_frame")
or (single_frame_image and frame_filter == "multi_frame")
):
continue

filtered_defs.append(output_def)

return filtered_defs

@staticmethod
def get_instance_label(instance):
return (
Expand All @@ -195,7 +215,7 @@ def main_process(self, instance):
outputs_per_repres = self._get_outputs_per_representations(
instance, profile_outputs
)
for repre, outpu_defs in outputs_per_repres:
for repre, output_defs in outputs_per_repres:
# Check if input should be preconverted before processing
# Store original staging dir (it's value may change)
src_repre_staging_dir = repre["stagingDir"]
Expand All @@ -216,6 +236,16 @@ def main_process(self, instance):
if first_input_path is None:
first_input_path = filepath

filtered_output_defs = self._single_frame_filter(
input_filepaths, output_defs
)
if not filtered_output_defs:
self.log.debug((
"Repre: {} - All output definitions were filtered"
" out by single frame filter. Skipping"
).format(repre["name"]))
continue

# Skip if file is not set
if first_input_path is None:
self.log.warning((
Expand Down Expand Up @@ -249,7 +279,10 @@ def main_process(self, instance):

try:
self._render_output_definitions(
instance, repre, src_repre_staging_dir, outpu_defs
instance,
repre,
src_repre_staging_dir,
filtered_output_defs
)

finally:
Expand All @@ -263,10 +296,10 @@ def main_process(self, instance):
shutil.rmtree(new_staging_dir)

def _render_output_definitions(
self, instance, repre, src_repre_staging_dir, outpu_defs
self, instance, repre, src_repre_staging_dir, output_defs
):
fill_data = copy.deepcopy(instance.data["anatomyData"])
for _output_def in outpu_defs:
for _output_def in output_defs:
output_def = copy.deepcopy(_output_def)
# Make sure output definition has "tags" key
if "tags" not in output_def:
Expand Down Expand Up @@ -1659,9 +1692,7 @@ def families_filter_validation(self, families, output_families_filter):
return True
return False

def filter_output_defs(
self, profile, subset_name, families
):
def filter_output_defs(self, profile, subset_name, families):
"""Return outputs matching input instance families.

Output definitions without families filter are marked as valid.
Expand Down
59 changes: 58 additions & 1 deletion openpype/settings/defaults/project_settings/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,62 @@
"families": [],
"hosts": [],
"outputs": {
"png": {
"ext": "png",
"tags": [
"ftrackreview"
],
"burnins": [],
"ffmpeg_args": {
"video_filters": [],
"audio_filters": [],
"input": [],
"output": []
},
"filter": {
"families": [
"render",
"review",
"ftrack"
],
"subsets": [],
"custom_tags": [],
"single_frame_filter": "single_frame"
},
"overscan_crop": "",
"overscan_color": [
0,
0,
0,
255
],
"width": 1920,
"height": 1080,
"scale_pixel_aspect": true,
"bg_color": [
0,
0,
0,
0
],
"letter_box": {
"enabled": false,
"ratio": 0.0,
"fill_color": [
0,
0,
0,
255
],
"line_thickness": 0,
"line_color": [
255,
0,
0,
255
]
}
},
"h264": {
"ext": "mp4",
"tags": [
Expand All @@ -79,7 +135,8 @@
"ftrack"
],
"subsets": [],
"custom_tags": []
"custom_tags": [],
"single_frame_filter": "multi_frame"
},
"overscan_crop": "",
"overscan_color": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,20 @@
"label": "Custom Tags",
"type": "list",
"object_type": "text"
},
{
"type": "label",
"label": "Use output <b>always</b> / only if input <b>is 1 frame</b> image / only if has <b>2+ frames</b> or <b>is video</b>"
},
{
"type": "enum",
"key": "single_frame_filter",
"default": "everytime",
"enum_items": [
{"everytime": "Always"},
{"single_frame": "Only if input has 1 image frame"},
{"multi_frame": "Only if input is video or sequence of frames"}
]
}
]
},
Expand Down
6 changes: 6 additions & 0 deletions website/docs/project_settings/settings_project_global.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ Profile may generate multiple outputs from a single input. Each output must defi
- set alpha to `0` to not use this option at all (in most of cases background stays black)
- other than `0` alpha will draw color as background

- **`Additional filtering`**
- Profile filtering defines which group of output definitions is used but output definitions may require more specific filters on their own.
- They may filter by subset name (regex can be used) or publish families. Publish families are more complex as are based on knowing code base.
- Filtering by custom tags -> this is used for targeting to output definitions from other extractors using settings (at this moment only Nuke bake extractor can target using custom tags).
- Nuke extractor settings path: `project_settings/nuke/publish/ExtractReviewDataMov/outputs/baking/add_custom_tags`
- Filtering by input length. Input may be video, sequence or single image. It is possible that `.mp4` should be created only when input is video or sequence and to create review `.png` when input is single frame. In some cases the output should be created even if it's single frame or multi frame input.

### IntegrateAssetNew

Expand Down