Merge pull request #1901 from pypeclub/feature/AE_local_render

Feature AE local render
This commit is contained in:
Petr Kalis 2021-08-06 18:23:47 +02:00 committed by GitHub
commit cdda7c19e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 296 additions and 129 deletions

View file

@ -0,0 +1,17 @@
from openpype.hosts.aftereffects.plugins.create import create_render
import logging
log = logging.getLogger(__name__)
class CreateLocalRender(create_render.CreateRender):
""" Creator to render locally.
Created only after default render on farm. So family 'render.local' is
used for backward compatibility.
"""
name = "renderDefault"
label = "Render Locally"
family = "renderLocal"

View file

@ -1,10 +1,14 @@
from openpype.lib import abstract_collect_render
from openpype.lib.abstract_collect_render import RenderInstance
import pyblish.api
import attr
import os
import re
import attr
import tempfile
from avalon import aftereffects
import pyblish.api
from openpype.settings import get_project_settings
from openpype.lib import abstract_collect_render
from openpype.lib.abstract_collect_render import RenderInstance
@attr.s
@ -13,6 +17,8 @@ class AERenderInstance(RenderInstance):
comp_name = attr.ib(default=None)
comp_id = attr.ib(default=None)
fps = attr.ib(default=None)
projectEntity = attr.ib(default=None)
stagingDir = attr.ib(default=None)
class CollectAERender(abstract_collect_render.AbstractCollectRender):
@ -21,6 +27,11 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
label = "Collect After Effects Render Layers"
hosts = ["aftereffects"]
# internal
family_remapping = {
"render": ("render.farm", "farm"), # (family, label)
"renderLocal": ("render", "local")
}
padding_width = 6
rendered_extension = 'png'
@ -62,14 +73,16 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
fps = work_area_info.frameRate
# TODO add resolution when supported by extension
if inst["family"] == "render" and inst["active"]:
if inst["family"] in self.family_remapping.keys() \
and inst["active"]:
remapped_family = self.family_remapping[inst["family"]]
instance = AERenderInstance(
family="render.farm", # other way integrate would catch it
families=["render.farm"],
family=remapped_family[0],
families=[remapped_family[0]],
version=version,
time="",
source=current_file,
label="{} - farm".format(inst["subset"]),
label="{} - {}".format(inst["subset"], remapped_family[1]),
subset=inst["subset"],
asset=context.data["assetEntity"]["name"],
attachTo=False,
@ -105,6 +118,30 @@ class CollectAERender(abstract_collect_render.AbstractCollectRender):
instance.outputDir = self._get_output_dir(instance)
settings = get_project_settings(os.getenv("AVALON_PROJECT"))
reviewable_subset_filter = \
(settings["deadline"]
["publish"]
["ProcessSubmittedJobOnFarm"]
["aov_filter"])
if inst["family"] == "renderLocal":
# for local renders
instance.anatomyData["version"] = instance.version
instance.anatomyData["subset"] = instance.subset
instance.stagingDir = tempfile.mkdtemp()
instance.projectEntity = project_entity
if self.hosts[0] in reviewable_subset_filter.keys():
for aov_pattern in \
reviewable_subset_filter[self.hosts[0]]:
if re.match(aov_pattern, instance.subset):
instance.families.append("review")
instance.review = True
break
self.log.info("New instance:: {}".format(instance))
instances.append(instance)
return instances

View file

@ -0,0 +1,82 @@
import os
import six
import sys
import openpype.api
from avalon import aftereffects
class ExtractLocalRender(openpype.api.Extractor):
"""Render RenderQueue locally."""
order = openpype.api.Extractor.order - 0.47
label = "Extract Local Render"
hosts = ["aftereffects"]
families = ["render"]
def process(self, instance):
stub = aftereffects.stub()
staging_dir = instance.data["stagingDir"]
self.log.info("staging_dir::{}".format(staging_dir))
stub.render(staging_dir)
# pull file name from Render Queue Output module
render_q = stub.get_render_info()
if not render_q:
raise ValueError("No file extension set in Render Queue")
_, ext = os.path.splitext(os.path.basename(render_q.file_name))
ext = ext[1:]
first_file_path = None
files = []
self.log.info("files::{}".format(os.listdir(staging_dir)))
for file_name in os.listdir(staging_dir):
files.append(file_name)
if first_file_path is None:
first_file_path = os.path.join(staging_dir,
file_name)
resulting_files = files
if len(files) == 1:
resulting_files = files[0]
repre_data = {
"frameStart": instance.data["frameStart"],
"frameEnd": instance.data["frameEnd"],
"name": ext,
"ext": ext,
"files": resulting_files,
"stagingDir": staging_dir
}
if instance.data["review"]:
repre_data["tags"] = ["review"]
instance.data["representations"] = [repre_data]
ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")
# Generate thumbnail.
thumbnail_path = os.path.join(staging_dir,
"thumbnail.jpg")
args = [
ffmpeg_path, "-y",
"-i", first_file_path,
"-vf", "scale=300:-1",
"-vframes", "1",
thumbnail_path
]
self.log.debug("Thumbnail args:: {}".format(args))
try:
output = openpype.lib.run_subprocess(args)
except TypeError:
self.log.warning("Error in creating thumbnail")
six.reraise(*sys.exc_info())
instance.data["representations"].append({
"name": "thumbnail",
"ext": "jpg",
"files": os.path.basename(thumbnail_path),
"stagingDir": staging_dir,
"tags": ["thumbnail"]
})

View file

@ -53,7 +53,7 @@ class ValidateSceneSettings(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = "Validate Scene Settings"
families = ["render.farm"]
families = ["render.farm", "render"]
hosts = ["aftereffects"]
optional = True

View file

@ -44,7 +44,8 @@ class ExtractBurnin(openpype.api.Extractor):
"harmony",
"fusion",
"aftereffects",
"tvpaint"
"tvpaint",
"aftereffects"
# "resolve"
]
optional = True

View file

@ -44,7 +44,8 @@ class ExtractReview(pyblish.api.InstancePlugin):
"standalonepublisher",
"fusion",
"tvpaint",
"resolve"
"resolve",
"aftereffects"
]
# Supported extensions

View file

@ -11,6 +11,30 @@
"deadline"
]
},
"ProcessSubmittedJobOnFarm": {
"enabled": true,
"deadline_department": "",
"deadline_pool": "",
"deadline_group": "",
"deadline_chunk_size": 1,
"deadline_priority": 50,
"publishing_script": "",
"skip_integration_repre_list": [],
"aov_filter": {
"maya": [
".+(?:\\.|_)([Bb]eauty)(?:\\.|_).*"
],
"nuke": [
".*"
],
"aftereffects": [
".*"
],
"celaction": [
".*"
]
}
},
"MayaSubmitDeadline": {
"enabled": true,
"optional": false,

View file

@ -298,6 +298,17 @@
"add_ftrack_family": true
}
]
},
{
"hosts": [
"aftereffects"
],
"families": [
"render"
],
"tasks": [],
"add_ftrack_family": true,
"advanced_filtering": []
}
]
},

View file

@ -173,28 +173,6 @@
}
]
},
"ProcessSubmittedJobOnFarm": {
"enabled": true,
"deadline_department": "",
"deadline_pool": "",
"deadline_group": "",
"deadline_chunk_size": 1,
"deadline_priority": 50,
"publishing_script": "",
"skip_integration_repre_list": [],
"aov_filter": {
"maya": [
".+(?:\\.|_)([Bb]eauty)(?:\\.|_).*"
],
"nuke": [],
"aftereffects": [
".*"
],
"celaction": [
".*"
]
}
},
"CleanUp": {
"paterns": [],
"remove_temp_renders": false
@ -257,6 +235,16 @@
],
"tasks": [],
"template": "{family}{Task}"
},
{
"families": [
"renderLocal"
],
"hosts": [
"aftereffects"
],
"tasks": [],
"template": "render{Task}{Variant}"
}
]
},

View file

@ -52,6 +52,101 @@
}
]
},
{
"type": "dict",
"collapsible": true,
"key": "ProcessSubmittedJobOnFarm",
"label": "ProcessSubmittedJobOnFarm",
"checkbox_key": "enabled",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "text",
"key": "deadline_department",
"label": "Deadline department"
},
{
"type": "text",
"key": "deadline_pool",
"label": "Deadline Pool"
},
{
"type": "text",
"key": "deadline_group",
"label": "Deadline Group"
},
{
"type": "number",
"key": "deadline_chunk_size",
"label": "Deadline Chunk Size"
},
{
"type": "number",
"key": "deadline_priority",
"label": "Deadline Priotity"
},
{
"type": "splitter"
},
{
"type": "text",
"key": "publishing_script",
"label": "Publishing script path"
},
{
"type": "list",
"key": "skip_integration_repre_list",
"label": "Skip integration of representation with ext",
"object_type": {
"type": "text"
}
},
{
"type": "dict",
"key": "aov_filter",
"label": "Reviewable subsets filter",
"children": [
{
"type": "list",
"key": "maya",
"label": "Maya",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "nuke",
"label": "Nuke",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "aftereffects",
"label": "After Effects",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "celaction",
"label": "Celaction",
"object_type": {
"type": "text"
}
}
]
}
]
},
{
"type": "dict",
"collapsible": true,

View file

@ -556,101 +556,6 @@
}
]
},
{
"type": "dict",
"collapsible": true,
"key": "ProcessSubmittedJobOnFarm",
"label": "ProcessSubmittedJobOnFarm",
"checkbox_key": "enabled",
"is_group": true,
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "text",
"key": "deadline_department",
"label": "Deadline department"
},
{
"type": "text",
"key": "deadline_pool",
"label": "Deadline Pool"
},
{
"type": "text",
"key": "deadline_group",
"label": "Deadline Group"
},
{
"type": "number",
"key": "deadline_chunk_size",
"label": "Deadline Chunk Size"
},
{
"type": "number",
"key": "deadline_priority",
"label": "Deadline Priotity"
},
{
"type": "splitter"
},
{
"type": "text",
"key": "publishing_script",
"label": "Publishing script path"
},
{
"type": "list",
"key": "skip_integration_repre_list",
"label": "Skip integration of representation with ext",
"object_type": {
"type": "text"
}
},
{
"type": "dict",
"key": "aov_filter",
"label": "Reviewable subsets filter",
"children": [
{
"type": "list",
"key": "maya",
"label": "Maya",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "nuke",
"label": "Nuke",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "aftereffects",
"label": "After Effects",
"object_type": {
"type": "text"
}
},
{
"type": "list",
"key": "celaction",
"label": "Celaction",
"object_type": {
"type": "text"
}
}
]
}
]
},
{
"type": "dict",
"collapsible": true,