From 20878ec3cb469e51d263c6162be5c4d905f2e42d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 12 Jul 2019 10:48:49 +0200 Subject: [PATCH 1/3] feat(pype, nuke): publishing with new review to ftrack with ffmpeg, wip --- .../ftrack/publish/collect_ftrack_api.py | 3 + .../global/_publish_unused/extract_review.py | 92 ------------ pype/plugins/global/publish/extract_review.py | 141 ++++++++++++++++++ .../_publish_unused/collect_render_target.py | 46 ++++++ .../extract_script.py | 4 +- .../plugins/nuke/publish/collect_instances.py | 2 +- pype/plugins/nuke/publish/collect_writes.py | 3 +- .../nuke/publish/extract_render_local.py | 1 - ...tract_review.py => extract_review_data.py} | 85 +++-------- 9 files changed, 213 insertions(+), 164 deletions(-) delete mode 100644 pype/plugins/global/_publish_unused/extract_review.py create mode 100644 pype/plugins/global/publish/extract_review.py create mode 100644 pype/plugins/nuke/_publish_unused/collect_render_target.py rename pype/plugins/nuke/{publish => _publish_unused}/extract_script.py (94%) rename pype/plugins/nuke/publish/{extract_review.py => extract_review_data.py} (69%) diff --git a/pype/plugins/ftrack/publish/collect_ftrack_api.py b/pype/plugins/ftrack/publish/collect_ftrack_api.py index e4923cac98..d09baec676 100644 --- a/pype/plugins/ftrack/publish/collect_ftrack_api.py +++ b/pype/plugins/ftrack/publish/collect_ftrack_api.py @@ -18,6 +18,9 @@ class CollectFtrackApi(pyblish.api.ContextPlugin): ftrack_log = logging.getLogger('ftrack_api') ftrack_log.setLevel(logging.WARNING) + ftrack_log = logging.getLogger('ftrack_api_old') + ftrack_log.setLevel(logging.WARNING) + # Collect session session = ftrack_api.Session() context.data["ftrackSession"] = session diff --git a/pype/plugins/global/_publish_unused/extract_review.py b/pype/plugins/global/_publish_unused/extract_review.py deleted file mode 100644 index 885db1cfc9..0000000000 --- a/pype/plugins/global/_publish_unused/extract_review.py +++ /dev/null @@ -1,92 +0,0 @@ -# import os -# import pyblish.api -# import subprocess -# from pype.vendor import clique -# from pypeapp import config -# -# -# class ExtractReview(pyblish.api.InstancePlugin): -# """Resolve any dependency issies -# -# This plug-in resolves any paths which, if not updated might break -# the published file. -# -# The order of families is important, when working with lookdev you want to -# first publish the texture, update the texture paths in the nodes and then -# publish the shading network. Same goes for file dependent assets. -# """ -# -# label = "Extract Review" -# order = pyblish.api.ExtractorOrder -# # families = ["imagesequence", "render", "write", "source"] -# # hosts = ["shell"] -# -# def process(self, instance): -# # adding plugin attributes from presets -# publish_presets = config.get_presets()["plugins"]["global"]["publish"] -# plugin_attrs = publish_presets[self.__class__.__name__] -# -# -# fps = instance.data.get("fps") -# start = instance.data.get("startFrame") -# stagingdir = os.path.normpath(instance.data.get("stagingDir")) -# -# collected_frames = os.listdir(stagingdir) -# collections, remainder = clique.assemble(collected_frames) -# -# full_input_path = os.path.join( -# stagingdir, collections[0].format('{head}{padding}{tail}') -# ) -# self.log.info("input {}".format(full_input_path)) -# -# filename = collections[0].format('{head}') -# if not filename.endswith('.'): -# filename += "." -# movFile = filename + "mov" -# full_output_path = os.path.join(stagingdir, movFile) -# -# self.log.info("output {}".format(full_output_path)) -# -# config_data = instance.context.data['output_repre_config'] -# -# proj_name = os.environ.get('AVALON_PROJECT', '__default__') -# profile = config_data.get(proj_name, config_data['__default__']) -# -# input_args = [] -# # overrides output file -# input_args.append("-y") -# # preset's input data -# input_args.extend(profile.get('input', [])) -# # necessary input data -# input_args.append("-start_number {}".format(start)) -# input_args.append("-i {}".format(full_input_path)) -# input_args.append("-framerate {}".format(fps)) -# -# output_args = [] -# # preset's output data -# output_args.extend(profile.get('output', [])) -# # output filename -# output_args.append(full_output_path) -# mov_args = [ -# "ffmpeg", -# " ".join(input_args), -# " ".join(output_args) -# ] -# subprocess_mov = " ".join(mov_args) -# sub_proc = subprocess.Popen(subprocess_mov) -# sub_proc.wait() -# -# if not os.path.isfile(full_output_path): -# raise("Quicktime wasn't created succesfully") -# -# if "representations" not in instance.data: -# instance.data["representations"] = [] -# -# representation = { -# 'name': 'mov', -# 'ext': 'mov', -# 'files': movFile, -# "stagingDir": stagingdir, -# "preview": True -# } -# instance.data["representations"].append(representation) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py new file mode 100644 index 0000000000..8c570d0c73 --- /dev/null +++ b/pype/plugins/global/publish/extract_review.py @@ -0,0 +1,141 @@ +import os +import pyblish.api +import subprocess +from pype.vendor import clique +from pypeapp import config + + +class ExtractReview(pyblish.api.InstancePlugin): + """Resolve any dependency issies + + This plug-in resolves any paths which, if not updated might break + the published file. + + The order of families is important, when working with lookdev you want to + first publish the texture, update the texture paths in the nodes and then + publish the shading network. Same goes for file dependent assets. + """ + + label = "Extract Review" + order = pyblish.api.ExtractorOrder + 0.02 + families = ["review"] + + def process(self, instance): + # adding plugin attributes from presets + publish_presets = config.get_presets()["plugins"]["global"]["publish"] + plugin_attrs = publish_presets[self.__class__.__name__] + output_profiles = plugin_attrs.get("outputs", {}) + + inst_data = instance.data + fps = inst_data.get("fps") + start_frame = inst_data.get("startFrame") + + # get representation and loop them + representations = instance.data["representations"] + + # filter out mov and img sequences + representations_new = list() + for repre in representations: + if repre['ext'] in plugin_attrs["ext_filter"]: + tags = repre.get("tags", []) + + self.log.info("Try repre: {}".format(repre)) + + if "review" in tags: + + repre_new = repre.copy() + del(repre) + + staging_dir = repre_new["stagingDir"] + + if "mov" not in repre_new['ext']: + # get output presets and loop them + collected_frames = os.listdir(staging_dir) + collections, remainder = clique.assemble( + collected_frames) + + full_input_path = os.path.join( + staging_dir, collections[0].format( + '{head}{padding}{tail}') + ) + + filename = collections[0].format('{head}') + if not filename.endswith('.'): + filename += "." + mov_file = filename + "mov" + + else: + full_input_path = os.path.join( + staging_dir, repre_new["files"]) + + filename = repre_new["files"].split(".")[0] + mov_file = filename + ".mov" + # test if the file is not the input file + if not os.path.isfile(os.path.join( + staging_dir, mov_file)): + mov_file = filename + "_.mov" + + full_output_path = os.path.join(staging_dir, mov_file) + + self.log.info("input {}".format(full_input_path)) + self.log.info("output {}".format(full_output_path)) + + for name, profile in output_profiles.items(): + self.log.debug("Profile name: {}".format(name)) + new_tags = tags + profile.get('tags', []) + input_args = [] + + # overrides output file + input_args.append("-y") + + # preset's input data + input_args.extend(profile.get('input', [])) + + # necessary input data + # adds start arg only if image sequence + if "mov" not in repre_new['ext']: + input_args.append("-start_number {}".format( + start_frame)) + + input_args.append("-i {}".format(full_input_path)) + input_args.append("-framerate {}".format(fps)) + + output_args = [] + # preset's output data + output_args.extend(profile.get('output', [])) + + # output filename + output_args.append(full_output_path) + mov_args = [ + "ffmpeg", + " ".join(input_args), + " ".join(output_args) + ] + subprocess_mov = " ".join(mov_args) + + # run subprocess + sub_proc = subprocess.Popen(subprocess_mov) + sub_proc.wait() + + if not os.path.isfile(full_output_path): + self.log.error( + "Quicktime wasn't created succesfully") + + # create representation data + repre_new.update({ + 'name': name, + 'ext': 'mov', + 'files': mov_file, + "thumbnail": False, + "preview": True, + "tags": new_tags + }) + + # adding representation + representations_new.append(repre_new) + else: + representations_new.append(repre) + + self.log.debug( + "new representations: {}".format(representations_new)) + instance.data["representations"] = representations_new diff --git a/pype/plugins/nuke/_publish_unused/collect_render_target.py b/pype/plugins/nuke/_publish_unused/collect_render_target.py new file mode 100644 index 0000000000..6c04414f69 --- /dev/null +++ b/pype/plugins/nuke/_publish_unused/collect_render_target.py @@ -0,0 +1,46 @@ +import pyblish.api + + +@pyblish.api.log +class CollectRenderTarget(pyblish.api.InstancePlugin): + """Collect families for all instances""" + + order = pyblish.api.CollectorOrder + 0.2 + label = "Collect Render Target" + hosts = ["nuke", "nukeassist"] + families = ['write'] + + def process(self, instance): + + node = instance[0] + + self.log.info('processing {}'.format(node)) + + families = [] + if instance.data.get('families'): + families += instance.data['families'] + + # set for ftrack to accept + # instance.data["families"] = ["ftrack"] + + if node["render"].value(): + # dealing with local/farm rendering + if node["render_farm"].value(): + families.append("render.farm") + else: + families.append("render.local") + else: + families.append("render.frames") + # to ignore staging dir op in integrate + instance.data['transfer'] = False + + families.append('ftrack') + + instance.data["families"] = families + + # Sort/grouped by family (preserving local index) + instance.context[:] = sorted(instance.context, key=self.sort_by_family) + + def sort_by_family(self, instance): + """Sort by family""" + return instance.data.get("families", instance.data.get("family")) diff --git a/pype/plugins/nuke/publish/extract_script.py b/pype/plugins/nuke/_publish_unused/extract_script.py similarity index 94% rename from pype/plugins/nuke/publish/extract_script.py rename to pype/plugins/nuke/_publish_unused/extract_script.py index d0be98b93e..7d55ea0da4 100644 --- a/pype/plugins/nuke/publish/extract_script.py +++ b/pype/plugins/nuke/_publish_unused/extract_script.py @@ -27,8 +27,8 @@ class ExtractScript(pype.api.Extractor): shutil.copy(current_script, path) if "representations" not in instance.data: - instance.data["representations"] = [] - + instance.data["representations"] = list() + representation = { 'name': 'nk', 'ext': '.nk', diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 7f119f9a1e..35673c5ff3 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -68,7 +68,7 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): "avalonKnob": avalon_knob_data, "publish": node.knob('publish').value(), "step": 1, - "fps": int(nuke.root()['fps'].value()) + "fps": nuke.root()['fps'].value() }) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 2dae39a1fc..216160616b 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -11,7 +11,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.1 label = "Collect Writes" hosts = ["nuke", "nukeassist"] - families = ["render.local", "render", "render.farm"] + families = ["render", "render.local", "render.farm"] def process(self, instance): @@ -96,5 +96,4 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "colorspace": node["colorspace"].value(), }) - self.log.debug("instance.data: {}".format(instance.data)) diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index f424bf1200..1d6550024f 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -21,7 +21,6 @@ class NukeRenderLocal(pype.api.Extractor): def process(self, instance): node = instance[0] - context = instance.context self.log.debug("instance collected: {}".format(instance.data)) diff --git a/pype/plugins/nuke/publish/extract_review.py b/pype/plugins/nuke/publish/extract_review_data.py similarity index 69% rename from pype/plugins/nuke/publish/extract_review.py rename to pype/plugins/nuke/publish/extract_review_data.py index bdbd3d17a6..552aa0cdb0 100644 --- a/pype/plugins/nuke/publish/extract_review.py +++ b/pype/plugins/nuke/publish/extract_review_data.py @@ -2,10 +2,9 @@ import os import nuke import pyblish.api import pype -from pype.vendor import ffmpeg -class ExtractDataForReview(pype.api.Extractor): +class ExtractReviewData(pype.api.Extractor): """Extracts movie and thumbnail with baked in luts must be run after extract_render_local.py @@ -13,8 +12,7 @@ class ExtractDataForReview(pype.api.Extractor): """ order = pyblish.api.ExtractorOrder + 0.01 - label = "Extract Review" - optional = True + label = "Extract Review Data" families = ["review"] hosts = ["nuke"] @@ -35,63 +33,15 @@ class ExtractDataForReview(pype.api.Extractor): if "still" not in instance.data["families"]: self.render_review_representation(instance, representation="mov") - self.log.debug("review mov:") - self.transcode_mov(instance) - self.log.debug("instance.data: {}".format(instance.data)) self.render_review_representation(instance, representation="jpeg") else: - self.log.debug("instance: {}".format(instance)) self.render_review_representation(instance, representation="jpeg") # Restore selection [i["selected"].setValue(False) for i in nuke.allNodes()] [i["selected"].setValue(True) for i in selection] - def transcode_mov(self, instance): - collection = instance.data["collection"] - stagingDir = instance.data["stagingDir"].replace("\\", "/") - file_name = collection.format("{head}mov") - - review_mov = os.path.join(stagingDir, file_name).replace("\\", "/") - - self.log.info("transcoding review mov: {0}".format(review_mov)) - if instance.data.get("baked_colorspace_movie"): - input_movie = instance.data["baked_colorspace_movie"] - out, err = ( - ffmpeg - .input(input_movie) - .output( - review_mov, - pix_fmt='yuv420p', - crf=18, - timecode="00:00:00:01" - ) - .overwrite_output() - .run() - ) - - self.log.debug("Removing `{0}`...".format( - instance.data["baked_colorspace_movie"])) - os.remove(instance.data["baked_colorspace_movie"]) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - 'name': 'review', - 'ext': 'mov', - 'files': file_name, - "stagingDir": stagingDir, - "anatomy_template": "render", - "thumbnail": False, - "preview": True, - 'startFrameReview': instance.data['startFrame'], - 'endFrameReview': instance.data['endFrame'], - 'frameRate': instance.context.data["framerate"] - } - instance.data["representations"].append(representation) - def render_review_representation(self, instance, representation="mov"): @@ -172,6 +122,7 @@ class ExtractDataForReview(pype.api.Extractor): temporary_nodes.append(write_node) thumbnail = False preview = True + tags = ["review"] elif representation in "jpeg": file = fhead + "jpeg" @@ -184,29 +135,31 @@ class ExtractDataForReview(pype.api.Extractor): temporary_nodes.append(write_node) thumbnail = True preview = False + tags = ["thumbnail"] # retime for first_frame = int(last_frame) / 2 last_frame = int(last_frame) / 2 - # add into files for integration as representation - if "representations" not in instance.data: - instance.data["representations"] = [] - - repre = { - 'name': representation, - 'ext': representation, - 'files': file, - "stagingDir": stagingDir, - "anatomy_template": "render", - "thumbnail": thumbnail, - "preview": preview - } - instance.data["representations"].append(repre) + repre = { + 'name': representation, + 'ext': representation, + 'files': file, + "stagingDir": stagingDir, + "startFrame": first_frame, + "endFrame": last_frame, + "anatomy_template": "render", + "thumbnail": thumbnail, + "preview": preview, + "tags": tags + } + instance.data["representations"].append(repre) # Render frames nuke.execute(write_node.name(), int(first_frame), int(last_frame)) + self.log.debug("representations: {}".format(instance.data["representations"])) + # Clean up for node in temporary_nodes: nuke.delete(node) From f45986a1ce5395c000c0a047194ae01b3d7d58a9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 12 Jul 2019 16:30:13 +0200 Subject: [PATCH 2/3] feat(pype): adding burnin plugin to function with reviews --- .../publish/integrate_ftrack_instances.py | 9 +- pype/plugins/global/publish/extract_burnin.py | 41 +++++-- pype/plugins/global/publish/extract_review.py | 103 ++++++++++-------- 3 files changed, 91 insertions(+), 62 deletions(-) diff --git a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py index a79e1f8ce5..9d8bd653d7 100644 --- a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py +++ b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py @@ -49,14 +49,14 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): for comp in instance.data['representations']: self.log.debug('component {}'.format(comp)) - if comp.get('thumbnail'): + if comp.get('thumbnail') or ("thumbnail" in comp.get('tags', [])): location = self.get_ftrack_location( 'ftrack.server', ft_session ) component_data = { "name": "thumbnail" # Default component name is "main". } - elif comp.get('preview'): + elif comp.get('preview') or ("preview" in comp.get('tags', [])): ''' Ftrack bug requirement: - Start frame must be 0 @@ -120,7 +120,9 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): componentList.append(component_item) # Create copy with ftrack.unmanaged location if thumb or prev - if comp.get('thumbnail') or comp.get('preview'): + if comp.get('thumbnail') or comp.get('preview') \ + or ("preview" in comp.get('tags', [])) \ + or ("thumbnail" in comp.get('tags', [])): unmanaged_loc = self.get_ftrack_location( 'ftrack.unmanaged', ft_session ) @@ -148,7 +150,6 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): componentList.append(component_item_src) - self.log.debug('componentsList: {}'.format(str(componentList))) instance.data["ftrackComponentsList"] = componentList diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 34ee33f602..b2956e330e 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -2,6 +2,7 @@ import os import subprocess import pype.api import json +import pyblish class ExtractBurnin(pype.api.Extractor): @@ -14,7 +15,8 @@ class ExtractBurnin(pype.api.Extractor): """ label = "Quicktime with burnins" - families = ["burnin"] + order = pyblish.api.ExtractorOrder + 0.03 + families = ["review", "burnin"] optional = True def process(self, instance): @@ -29,25 +31,30 @@ class ExtractBurnin(pype.api.Extractor): "start_frame": int(instance.data['startFrame']), "version": "v" + str(instance.context.data['version']) } + self.log.debug("__ burnin_data1: {}".format(burnin_data)) + for i, repre in enumerate(instance.data["representations"]): + self.log.debug("__ i: `{}`, repre: `{}`".format(i, repre)) - for repre in instance.data["representations"]: - if (not repre.get("burnin", False) or - "burnin" not in repre.get("tags", [])): + if "burnin" not in repre.get("tags", []): continue - stagingdir = self.staging_dir(instance) + stagingdir = repre["stagingDir"] filename = "{0}".format(repre["files"]) - movieFileBurnin = filename + "Burn" + ".mov" + name = "_burnin" + movieFileBurnin = filename.replace(".mov", "") + name + ".mov" full_movie_path = os.path.join(stagingdir, repre["files"]) full_burnin_path = os.path.join(stagingdir, movieFileBurnin) + self.log.debug("__ full_burnin_path: {}".format(full_burnin_path)) burnin_data = { "input": full_movie_path.replace("\\", "/"), "output": full_burnin_path.replace("\\", "/"), "burnin_data": burnin_data - } + } + + self.log.debug("__ burnin_data2: {}".format(burnin_data)) json_data = json.dumps(burnin_data) scriptpath = os.path.join(os.environ['PYPE_MODULE_ROOT'], @@ -55,9 +62,19 @@ class ExtractBurnin(pype.api.Extractor): "scripts", "otio_burnin.py") - p = subprocess.Popen( - ['python', scriptpath, json_data] - ) - p.wait() + self.log.debug("__ scriptpath: {}".format(scriptpath)) - repre['files']: movieFileBurnin + try: + p = subprocess.Popen( + [os.getenv("PYPE_PYTHON_EXE"), scriptpath, json_data] + ) + p.wait() + except Exception as e: + raise RuntimeError("Burnin script didn't work: `{}`".format(e)) + + if os.path.exists(full_burnin_path): + repre_update = { + "files": movieFileBurnin, + "name": repre["name"] + name + } + instance.data["representations"][i].update(repre_update) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 8c570d0c73..af6d59d798 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -6,14 +6,14 @@ from pypeapp import config class ExtractReview(pyblish.api.InstancePlugin): - """Resolve any dependency issies + """Extracting Review mov file for Ftrack - This plug-in resolves any paths which, if not updated might break - the published file. + Compulsory attribute of representation is tags list with "review", + otherwise the representation is ignored. - The order of families is important, when working with lookdev you want to - first publish the texture, update the texture paths in the nodes and then - publish the shading network. Same goes for file dependent assets. + All new represetnations are created and encoded by ffmpeg following + presets found in `pype-config/presets/plugins/global/publish.json:ExtractReview:outputs`. To change the file extension + filter values use preset's attributes `ext_filter` """ label = "Extract Review" @@ -30,6 +30,8 @@ class ExtractReview(pyblish.api.InstancePlugin): fps = inst_data.get("fps") start_frame = inst_data.get("startFrame") + self.log.debug("Families In: `{}`".format(instance.data["families"])) + # get representation and loop them representations = instance.data["representations"] @@ -43,46 +45,50 @@ class ExtractReview(pyblish.api.InstancePlugin): if "review" in tags: - repre_new = repre.copy() - del(repre) - - staging_dir = repre_new["stagingDir"] - - if "mov" not in repre_new['ext']: - # get output presets and loop them - collected_frames = os.listdir(staging_dir) - collections, remainder = clique.assemble( - collected_frames) - - full_input_path = os.path.join( - staging_dir, collections[0].format( - '{head}{padding}{tail}') - ) - - filename = collections[0].format('{head}') - if not filename.endswith('.'): - filename += "." - mov_file = filename + "mov" - - else: - full_input_path = os.path.join( - staging_dir, repre_new["files"]) - - filename = repre_new["files"].split(".")[0] - mov_file = filename + ".mov" - # test if the file is not the input file - if not os.path.isfile(os.path.join( - staging_dir, mov_file)): - mov_file = filename + "_.mov" - - full_output_path = os.path.join(staging_dir, mov_file) - - self.log.info("input {}".format(full_input_path)) - self.log.info("output {}".format(full_output_path)) + staging_dir = repre["stagingDir"] for name, profile in output_profiles.items(): + if "mov" not in repre['ext']: + # get output presets and loop them + collections, remainder = clique.assemble( + repre["files"]) + + full_input_path = os.path.join( + staging_dir, collections[0].format( + '{head}{padding}{tail}') + ) + + filename = collections[0].format('{head}') + if filename.endswith('.'): + filename = filename[:-1] + else: + full_input_path = os.path.join( + staging_dir, repre["files"]) + filename = repre["files"].split(".")[0] + + mov_file = filename + "_{0}.{1}".format(name, "mov") + + full_output_path = os.path.join(staging_dir, mov_file) + + self.log.info("input {}".format(full_input_path)) + self.log.info("output {}".format(full_output_path)) + + repre_new = repre.copy() + self.log.debug("Profile name: {}".format(name)) - new_tags = tags + profile.get('tags', []) + + new_tags = tags[:] + p_tags = profile.get('tags', []) + self.log.info("p_tags: `{}`".format(p_tags)) + # add families + [instance.data["families"].append(t) for t in p_tags + if t not in instance.data["families"]] + # add to + [new_tags.append(t) for t in p_tags + if t not in new_tags] + + self.log.info("new_tags: `{}`".format(new_tags)) + input_args = [] # overrides output file @@ -126,16 +132,21 @@ class ExtractReview(pyblish.api.InstancePlugin): 'name': name, 'ext': 'mov', 'files': mov_file, - "thumbnail": False, - "preview": True, - "tags": new_tags + "tags": new_tags, + "outputName": name }) + repre_new.pop("preview") + repre_new.pop("thumbnail") # adding representation representations_new.append(repre_new) else: representations_new.append(repre) + else: + representations_new.append(repre) self.log.debug( "new representations: {}".format(representations_new)) instance.data["representations"] = representations_new + + self.log.debug("Families Out: `{}`".format(instance.data["families"])) From 37fd304026de383b399fab8a55afa9785e748cd1 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 12 Jul 2019 16:30:50 +0200 Subject: [PATCH 3/3] feat(pype): addig additional path element for representation preset names --- pype/plugins/global/publish/integrate_new.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index e70657eef9..c03e66c670 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -342,6 +342,9 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): template_data["representation"] = repre['ext'] + if repre.get("outputName"): + template_data["output"] = repre['outputName'] + src = os.path.join(stagingdir, fname) anatomy_filled = anatomy.format(template_data) dst = os.path.normpath(