diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index e1508b9131..dedfd98979 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -224,7 +224,7 @@ class ExtractBurnin(pype.api.Extractor): self.log.debug("Executing: {}".format(args)) # Run burnin script - output = pype.api.subprocess(args) + output = pype.api.subprocess(args, shell=True) self.log.debug("Output: {}".format(output)) for filepath in temp_data["full_input_paths"]: @@ -964,7 +964,7 @@ class ExtractBurnin(pype.api.Extractor): args = [executable, scriptpath, json_data] self.log.debug("Executing: {}".format(args)) - output = pype.api.subprocess(args) + output = pype.api.subprocess(args, shell=True) self.log.debug("Output: {}".format(output)) repre_update = { diff --git a/pype/plugins/global/publish/extract_jpeg.py b/pype/plugins/global/publish/extract_jpeg.py index 9b775f8b6f..97af9a3751 100644 --- a/pype/plugins/global/publish/extract_jpeg.py +++ b/pype/plugins/global/publish/extract_jpeg.py @@ -83,7 +83,7 @@ class ExtractJpegEXR(pyblish.api.InstancePlugin): # run subprocess self.log.debug("{}".format(subprocess_jpeg)) - pype.api.subprocess(subprocess_jpeg) + pype.api.subprocess(subprocess_jpeg, shell=True) if "representations" not in instance.data: instance.data["representations"] = [] diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index e1a0d7043a..ac8766f5a7 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -175,7 +175,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # run subprocess self.log.debug("Executing: {}".format(subprcs_cmd)) - output = pype.api.subprocess(subprcs_cmd) + output = pype.api.subprocess(subprcs_cmd, shell=True) self.log.debug("Output: {}".format(output)) output_name = output_def["filename_suffix"] @@ -342,6 +342,12 @@ class ExtractReview(pyblish.api.InstancePlugin): "-i \"{}\"".format(temp_data["full_input_path"]) ) + if temp_data["output_is_sequence"]: + # Set start frame + ffmpeg_input_args.append( + "-start_number {}".format(temp_data["output_frame_start"]) + ) + # Add audio arguments if there are any. Skipped when output are images. if not temp_data["output_ext_is_image"]: audio_in_args, audio_filters, audio_out_args = self.audio_args( @@ -1482,7 +1488,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # run subprocess self.log.debug("Executing: {}".format(subprcs_cmd)) - output = pype.api.subprocess(subprcs_cmd) + output = pype.api.subprocess(subprcs_cmd, shell=True) self.log.debug("Output: {}".format(output)) # create representation data diff --git a/pype/plugins/global/publish/extract_review_slate.py b/pype/plugins/global/publish/extract_review_slate.py index f2ea6c0875..2e1fc25ae5 100644 --- a/pype/plugins/global/publish/extract_review_slate.py +++ b/pype/plugins/global/publish/extract_review_slate.py @@ -186,7 +186,7 @@ class ExtractReviewSlate(pype.api.Extractor): # run slate generation subprocess self.log.debug("Slate Executing: {}".format(slate_subprcs_cmd)) - slate_output = pype.api.subprocess(slate_subprcs_cmd) + slate_output = pype.api.subprocess(slate_subprcs_cmd, shell=True) self.log.debug("Slate Output: {}".format(slate_output)) # create ffmpeg concat text file path @@ -221,7 +221,7 @@ class ExtractReviewSlate(pype.api.Extractor): # ffmpeg concat subprocess self.log.debug("Executing concat: {}".format(concat_subprcs_cmd)) - concat_output = pype.api.subprocess(concat_subprcs_cmd) + concat_output = pype.api.subprocess(concat_subprcs_cmd, shell=True) self.log.debug("Output concat: {}".format(concat_output)) self.log.debug("__ repre[tags]: {}".format(repre["tags"])) diff --git a/pype/plugins/standalonepublisher/publish/extract_review.py b/pype/plugins/standalonepublisher/publish/extract_review.py deleted file mode 100644 index 0f845afcb1..0000000000 --- a/pype/plugins/standalonepublisher/publish/extract_review.py +++ /dev/null @@ -1,199 +0,0 @@ -import os -import tempfile - -import pyblish.api -import clique -import pype.api -import pype.lib - - -class ExtractReviewSP(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 SP" - order = pyblish.api.ExtractorOrder + 0.02 - families = ["review"] - hosts = ["standalonepublisher"] - - def process(self, instance): - # adding plugin attributes from presets - presets = instance.context.data["presets"] - try: - publish_presets = presets["plugins"]["standalonepublisher"]["publish"] - 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] - - # prepare output file - repr_file = filename + "_{0}.{1}".format(name, ext) - out_stagigng_dir = tempfile.mkdtemp(prefix="extract_review_") - full_output_path = os.path.join(out_stagigng_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.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", [])) - - if isinstance(repre["files"], list): - # set length of video by len of inserted files - video_len = len(repre["files"]) - else: - video_len = repre["frameEnd"] - repre["frameStart"] + 1 - output_args.append( - "-frames {}".format(video_len) - ) - - # letter_box - 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)) - - # output filename - output_args.append(full_output_path) - - ffmpeg_path = pype.lib.get_ffmpeg_tool_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, - "stagingDir": out_stagigng_dir, - "tags": new_tags, - "outputName": name, - "frameStartFtrack": 1, - "frameEndFtrack": video_len - }) - # cleanup thumbnail from new repre - if repre_new.get("thumbnail"): - repre_new.pop("thumbnail") - if "thumbnail" in repre_new["tags"]: - repre_new["tags"].remove("thumbnail") - - # adding representation - self.log.debug("Adding: {}".format(repre_new)) - # cleanup repre from preview - if "preview" in repre: - repre.pop("preview") - if "preview" in repre["tags"]: - repre["tags"].remove("preview") - 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) diff --git a/pype/plugins/standalonepublisher/publish/extract_thumbnail.py b/pype/plugins/standalonepublisher/publish/extract_thumbnail.py deleted file mode 100644 index cddc9c3a82..0000000000 --- a/pype/plugins/standalonepublisher/publish/extract_thumbnail.py +++ /dev/null @@ -1,122 +0,0 @@ -import os -import tempfile -import subprocess -import pyblish.api -import pype.api -import pype.lib - - -class ExtractThumbnailSP(pyblish.api.InstancePlugin): - """Extract jpeg thumbnail from component input from standalone publisher - - Uses jpeg file from component if possible (when single or multiple jpegs - are loaded to component selected as thumbnail) otherwise extracts from - input file/s single jpeg to temp. - """ - - label = "Extract Thumbnail SP" - hosts = ["standalonepublisher"] - order = pyblish.api.ExtractorOrder - - # Presetable attribute - ffmpeg_args = None - - def process(self, instance): - repres = instance.data.get('representations') - if not repres: - return - - thumbnail_repre = None - for repre in repres: - if repre.get("thumbnail"): - thumbnail_repre = repre - break - - if not thumbnail_repre: - return - - files = thumbnail_repre.get("files") - if not files: - return - - if isinstance(files, list): - files_len = len(files) - file = str(files[0]) - else: - files_len = 1 - file = files - - is_jpeg = False - if file.endswith(".jpeg") or file.endswith(".jpg"): - is_jpeg = True - - if is_jpeg and files_len == 1: - # skip if already is single jpeg file - return - - elif is_jpeg: - # use first frame as thumbnail if is sequence of jpegs - full_thumbnail_path = file - self.log.info( - "For thumbnail is used file: {}".format(full_thumbnail_path) - ) - - else: - # Convert to jpeg if not yet - full_input_path = os.path.join(thumbnail_repre["stagingDir"], file) - self.log.info("input {}".format(full_input_path)) - - full_thumbnail_path = tempfile.mkstemp(suffix=".jpg")[1] - self.log.info("output {}".format(full_thumbnail_path)) - - ffmpeg_path = pype.lib.get_ffmpeg_tool_path("ffmpeg") - - ffmpeg_args = self.ffmpeg_args or {} - - jpeg_items = [] - jpeg_items.append(ffmpeg_path) - # override file if already exists - jpeg_items.append("-y") - # add input filters from peresets - jpeg_items.extend(ffmpeg_args.get("input") or []) - # input file - jpeg_items.append("-i {}".format(full_input_path)) - # extract only single file - jpeg_items.append("-vframes 1") - - jpeg_items.extend(ffmpeg_args.get("output") or []) - - # output file - jpeg_items.append(full_thumbnail_path) - - subprocess_jpeg = " ".join(jpeg_items) - - # run subprocess - self.log.debug("Executing: {}".format(subprocess_jpeg)) - subprocess.Popen( - subprocess_jpeg, - stdout=subprocess.PIPE, - shell=True - ) - - # remove thumbnail key from origin repre - thumbnail_repre.pop("thumbnail") - - filename = os.path.basename(full_thumbnail_path) - staging_dir = os.path.dirname(full_thumbnail_path) - - # create new thumbnail representation - representation = { - 'name': 'jpg', - 'ext': 'jpg', - 'files': filename, - "stagingDir": staging_dir, - "thumbnail": True, - "tags": [] - } - - # # add Delete tag when temp file was rendered - # if not is_jpeg: - # representation["tags"].append("delete") - - instance.data["representations"].append(representation)