From 0aa11a8442d947dbe984807575125f69b9d8a381 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 15 Oct 2019 18:58:20 +0200 Subject: [PATCH 1/8] preview button is shown for image sequences too --- pype/standalonepublish/widgets/widget_drop_frame.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pype/standalonepublish/widgets/widget_drop_frame.py b/pype/standalonepublish/widgets/widget_drop_frame.py index a5a686bae1..ba8ab44cf8 100644 --- a/pype/standalonepublish/widgets/widget_drop_frame.py +++ b/pype/standalonepublish/widgets/widget_drop_frame.py @@ -297,18 +297,23 @@ class DropDataFrame(QtWidgets.QFrame): if ext in exts: icon = ico break + + new_is_seq = data['is_sequence'] # Add 's' to icon_name if is sequence (image -> images) - if data['is_sequence']: + if new_is_seq: icon += 's' data['icon'] = icon data['thumb'] = ( ext in self.presets['extensions']['image_file'] or ext in self.presets['extensions']['video_file'] ) - data['prev'] = ext in self.presets['extensions']['video_file'] + data['prev'] = ( + ext in self.presets['extensions']['video_file'] or + (new_is_seq and ext in self.presets['extensions']['image_file']) + ) actions = [] - new_is_seq = data['is_sequence'] + found = False for item in self.components_list.widgets(): From c0af349a9f35635a862b6e7668c34c9f207c69be Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 11:27:59 +0200 Subject: [PATCH 2/8] add standalone publisher to hosts of extract review --- pype/plugins/global/publish/extract_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 7e67ef7bab..903f69c000 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -20,7 +20,7 @@ class ExtractReview(pyblish.api.InstancePlugin): label = "Extract Review" order = pyblish.api.ExtractorOrder + 0.02 families = ["review"] - hosts = ["nuke", "maya", "shell"] + hosts = ["nuke", "maya", "shell", "standalonepublisher"] def process(self, instance): # adding plugin attributes from presets From 361eb3564e378bc8c40974f00e5e44a8fd76451a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 11:28:47 +0200 Subject: [PATCH 3/8] added fix when extension has dot --- pype/plugins/global/publish/extract_review.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 903f69c000..1fdf6af811 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -40,7 +40,9 @@ class ExtractReview(pyblish.api.InstancePlugin): # filter out mov and img sequences representations_new = representations[:] for repre in representations: - if repre['ext'] in plugin_attrs["ext_filter"]: + # remove dot if extension has + repre_ext = repre['ext'].replace(".", "") + if repre_ext not in plugin_attrs["ext_filter"]: tags = repre.get("tags", []) self.log.info("Try repre: {}".format(repre)) From 9e69f4f52bc17ff0c3042767ddc6a21defad4965 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 11:30:33 +0200 Subject: [PATCH 4/8] added ability to specify profiles to be processed if necessary --- pype/plugins/global/publish/extract_review.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 1fdf6af811..49e71e535b 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -37,6 +37,9 @@ class ExtractReview(pyblish.api.InstancePlugin): # get representation and loop them representations = instance.data["representations"] + # get specific profile if was defined + specific_profiles = instance.data.get("repreProfiles") + # filter out mov and img sequences representations_new = representations[:] for repre in representations: @@ -52,6 +55,10 @@ class ExtractReview(pyblish.api.InstancePlugin): for name, profile in output_profiles.items(): self.log.debug("Profile name: {}".format(name)) + # filter profiles if were set specific profiles + if specific_profile and name not in specific_profiles: + continue + ext = profile.get("ext", None) if not ext: ext = "mov" From de4bc42ec7076645b2287b498ef1f314d80c4ff3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 11:31:25 +0200 Subject: [PATCH 5/8] collect context prepare data for preview rendering through extract_review --- pype/plugins/global/publish/collect_context.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pype/plugins/global/publish/collect_context.py b/pype/plugins/global/publish/collect_context.py index 5f443ac5fb..36ab7e419d 100644 --- a/pype/plugins/global/publish/collect_context.py +++ b/pype/plugins/global/publish/collect_context.py @@ -106,6 +106,12 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): instance.data["frameEnd"] = int(component["frameEnd"]) instance.data['fps'] = int(component['fps']) + if component["preview"]: + instance.data["families"].append("review") + instance.data["repreProfiles"] = ["h264_clean"] + component["tags"] = ["review", "delete"] + self.log.debug("Adding review family") + instance.data["representations"].append(component) self.log.info(in_data) From d9780d8caaec22377d98fcacc20b54561073dc0a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 13:52:40 +0200 Subject: [PATCH 6/8] changes in extract_review were changed back since it's nuke break change --- pype/plugins/global/publish/extract_review.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 49e71e535b..7e67ef7bab 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -20,7 +20,7 @@ class ExtractReview(pyblish.api.InstancePlugin): label = "Extract Review" order = pyblish.api.ExtractorOrder + 0.02 families = ["review"] - hosts = ["nuke", "maya", "shell", "standalonepublisher"] + hosts = ["nuke", "maya", "shell"] def process(self, instance): # adding plugin attributes from presets @@ -37,15 +37,10 @@ class ExtractReview(pyblish.api.InstancePlugin): # get representation and loop them representations = instance.data["representations"] - # get specific profile if was defined - specific_profiles = instance.data.get("repreProfiles") - # filter out mov and img sequences representations_new = representations[:] for repre in representations: - # remove dot if extension has - repre_ext = repre['ext'].replace(".", "") - if repre_ext not in plugin_attrs["ext_filter"]: + if repre['ext'] in plugin_attrs["ext_filter"]: tags = repre.get("tags", []) self.log.info("Try repre: {}".format(repre)) @@ -55,10 +50,6 @@ class ExtractReview(pyblish.api.InstancePlugin): for name, profile in output_profiles.items(): self.log.debug("Profile name: {}".format(name)) - # filter profiles if were set specific profiles - if specific_profile and name not in specific_profiles: - continue - ext = profile.get("ext", None) if not ext: ext = "mov" From 156029ef0bc26cb39541b05a337d076baf67aafc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 13:53:42 +0200 Subject: [PATCH 7/8] created modified extract review for standalone publisher --- .../plugins/global/publish/collect_context.py | 2 +- .../global/publish/extract_review_sa.py | 186 ++++++++++++++++++ 2 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 pype/plugins/global/publish/extract_review_sa.py diff --git a/pype/plugins/global/publish/collect_context.py b/pype/plugins/global/publish/collect_context.py index 36ab7e419d..0a41962748 100644 --- a/pype/plugins/global/publish/collect_context.py +++ b/pype/plugins/global/publish/collect_context.py @@ -108,7 +108,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): if component["preview"]: instance.data["families"].append("review") - instance.data["repreProfiles"] = ["h264_clean"] + instance.data["repreProfiles"] = ["h264"] component["tags"] = ["review", "delete"] self.log.debug("Adding review family") diff --git a/pype/plugins/global/publish/extract_review_sa.py b/pype/plugins/global/publish/extract_review_sa.py new file mode 100644 index 0000000000..a77af8dc6d --- /dev/null +++ b/pype/plugins/global/publish/extract_review_sa.py @@ -0,0 +1,186 @@ +import os + +import pyblish.api +from pype.vendor import clique +import pype.api + + +class ExtractReviewSaP(pyblish.api.InstancePlugin): + """Extracting Review mov file for Ftrack + + Compulsory attribute of representation is tags list with "review", + otherwise the representation is ignored. + + 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 SaP" + order = pyblish.api.ExtractorOrder + 0.02 + families = ["review"] + hosts = ["standalonepublisher"] + + def process(self, instance): + # adding plugin attributes from presets + presets = instance.context.data["presets"] + publish_presets = presets["plugins"]["global"]["publish"] + try: + plugin_attrs = publish_presets[self.__class__.__name__] + except KeyError: + raise KeyError("Preset for plugin \"{}\" are not set".format( + self.__class__.__name__ + )) + + output_profiles = plugin_attrs.get("outputs", {}) + + fps = instance.data.get("fps") + start_frame = instance.data.get("frameStart") + + self.log.debug("Families In: `{}`".format(instance.data["families"])) + + # get specific profile if was defined + specific_profiles = instance.data.get("repreProfiles") + + new_repres = [] + # filter out mov and img sequences + for repre in instance.data["representations"]: + tags = repre.get("tags", []) + if "review" not in tags: + continue + + staging_dir = repre["stagingDir"] + for name in specific_profiles: + profile = output_profiles.get(name) + if not profile: + self.log.warning( + "Profile \"{}\" was not found in presets".format(name) + ) + continue + + self.log.debug("Processing profile: {}".format(name)) + + ext = profile.get("ext", None) + if not ext: + ext = "mov" + self.log.debug(( + "`ext` attribute not in output profile \"{}\"." + " Setting to default ext: `mov`" + ).format(name)) + + if isinstance(repre["files"], list): + 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] + + repr_file = filename + "_{0}.{1}".format(name, ext) + + full_output_path = os.path.join(staging_dir, repr_file) + + self.log.info("input {}".format(full_input_path)) + self.log.info("output {}".format(full_output_path)) + + repre_new = repre.copy() + + new_tags = [x for x in tags if x != "delete"] + p_tags = profile.get("tags", []) + self.log.info("p_tags: `{}`".format(p_tags)) + + for _tag in p_tags: + if _tag not in new_tags: + new_tags.append(_tag) + + self.log.info("new_tags: `{}`".format(new_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 isinstance(repre["files"], list): + input_args.append("-start_number {0} -framerate {1}".format( + start_frame, fps)) + + input_args.append("-i {}".format(full_input_path)) + + output_args = [] + # preset's output data + output_args.extend(profile.get("output", [])) + + # letter_box + # TODO: add to documentation + lb_string = ( + "-filter:v " + "drawbox=0:0:iw:round((ih-(iw*(1/{0})))/2):t=fill:c=black," + "drawbox=0:ih-round((ih-(iw*(1/{0})))/2):iw:" + "round((ih-(iw*(1/{0})))/2):t=fill:c=black" + ) + letter_box = profile.get("letter_box", None) + if letter_box: + output_args.append(lb_string.format(letter_box)) + + # In case audio is longer than video. + output_args.append("-shortest") + + # output filename + output_args.append(full_output_path) + + ffmpeg_path = os.getenv("FFMPEG_PATH", "") + if ffmpeg_path: + ffmpeg_path += "/ffmpeg" + else: + ffmpeg_path = "ffmpeg" + + mov_args = [ + ffmpeg_path, + " ".join(input_args), + " ".join(output_args) + ] + subprcs_cmd = " ".join(mov_args) + + # run subprocess + self.log.debug("Executing: {}".format(subprcs_cmd)) + output = pype.api.subprocess(subprcs_cmd) + self.log.debug("Output: {}".format(output)) + + # create representation data + repre_new.update({ + "name": name, + "ext": ext, + "files": repr_file, + "tags": new_tags, + "outputName": name + }) + if repre_new.get("preview"): + repre_new.pop("preview") + if repre_new.get("thumbnail"): + repre_new.pop("thumbnail") + + # adding representation + self.log.debug("Adding: {}".format(repre_new)) + new_repres.append(repre_new) + + for repre in instance.data["representations"]: + if "delete" in repre.get("tags", []): + instance.data["representations"].remove(repre) + + for repre in new_repres: + self.log.debug("Adding repre: \"{}\"".format( + repre + )) + instance.data["representations"].append(repre) From 7b3e25e06cc1a2d974b0e7955ac566e0d85745f5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 16 Oct 2019 14:11:26 +0200 Subject: [PATCH 8/8] changed ffmpeg args to render only frame range from representation --- pype/plugins/global/publish/extract_review_sa.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pype/plugins/global/publish/extract_review_sa.py b/pype/plugins/global/publish/extract_review_sa.py index a77af8dc6d..541a717964 100644 --- a/pype/plugins/global/publish/extract_review_sa.py +++ b/pype/plugins/global/publish/extract_review_sa.py @@ -75,7 +75,6 @@ class ExtractReviewSaP(pyblish.api.InstancePlugin): staging_dir, collections[0].format("{head}{padding}{tail}") ) - filename = collections[0].format('{head}') if filename.endswith("."): filename = filename[:-1] @@ -113,17 +112,21 @@ class ExtractReviewSaP(pyblish.api.InstancePlugin): # necessary input data # adds start arg only if image sequence if isinstance(repre["files"], list): - input_args.append("-start_number {0} -framerate {1}".format( - start_frame, fps)) + input_args.extend([ + "-start_number {}".format(start_frame), + "-framerate {}".format(fps) + ]) input_args.append("-i {}".format(full_input_path)) output_args = [] # preset's output data output_args.extend(profile.get("output", [])) + + # set length of video by len of inserted files + output_args.append("-frames {}".format(len(repre["files"]))) # letter_box - # TODO: add to documentation lb_string = ( "-filter:v " "drawbox=0:0:iw:round((ih-(iw*(1/{0})))/2):t=fill:c=black," @@ -134,9 +137,6 @@ class ExtractReviewSaP(pyblish.api.InstancePlugin): if letter_box: output_args.append(lb_string.format(letter_box)) - # In case audio is longer than video. - output_args.append("-shortest") - # output filename output_args.append(full_output_path)