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

Enhancement: More control over thumbnail processing. #3259

Merged
merged 39 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d636a41
Replace plugin name with more descriptive one.
May 17, 2022
78c7081
Change label name.
May 17, 2022
8f7428d
Add OIIO
May 18, 2022
8453f97
Add profiles handling in schema aand for extractor
May 25, 2022
0040f02
Style fix
May 25, 2022
8e0b015
Fix comment typo
May 25, 2022
043ba41
Remove whitespace
May 25, 2022
c50cab5
initial refactoring
May 25, 2022
d992935
name probesize and duration to max_int
May 25, 2022
cc4efe7
style fix
May 26, 2022
70c5366
Additional oiiotool conversion refactoring, some style fixes
May 26, 2022
2b4d650
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
May 27, 2022
20b7b5d
Style fixes, remove unused imports
May 27, 2022
9afdf50
initial conversion refactor
May 30, 2022
eef1e09
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
May 30, 2022
b6e6b7a
refactor cleanup
May 31, 2022
ca9c06d
continue refactor
Jun 1, 2022
ebfef2a
Cleanup
Jun 1, 2022
b720d46
continue refactoring
Jun 1, 2022
84c073d
Further clean up and refactor.
Jun 1, 2022
3b26f78
Revert "Add profiles handling in schema aand for extractor"
Jun 1, 2022
c446866
remove unused variable
Jun 1, 2022
f8de7b3
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
Jun 1, 2022
9d851e8
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
Jun 1, 2022
3310c76
Merge branch 'OP-3172_More-control-over-thumbnail-processing' of http…
Jun 2, 2022
b3098a4
Fix path bug causing output path to equal input path.
Jun 6, 2022
a922b93
Fix path bug.
Jun 6, 2022
a1e95dd
Fix oiio subprocess arguments.
Jun 9, 2022
f79f934
Update openpype/plugins/publish/extract_jpeg_exr.py
Jun 9, 2022
012f21c
Fix error messages.
Jun 9, 2022
a97a293
Merge branch 'OP-3172_More-control-over-thumbnail-processing' of http…
Jun 9, 2022
5e817c5
Fix style warning.
Jun 9, 2022
5e0589d
Restore removed logging messaage.
Jun 9, 2022
3a7e329
Update openpype/plugins/publish/extract_jpeg_exr.py
Jun 10, 2022
28d0ea3
Update openpype/plugins/publish/extract_jpeg_exr.py
Jun 10, 2022
b19fc26
Handle muiltilayered flag
Jun 10, 2022
2ef659f
Merge branch 'OP-3172_More-control-over-thumbnail-processing' of http…
Jun 10, 2022
6d2548c
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
Jun 10, 2022
18caa8c
Merge branch 'develop' into OP-3172_More-control-over-thumbnail-proce…
jakubjezek001 Jun 15, 2022
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
2 changes: 1 addition & 1 deletion openpype/lib/transcoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ def convert_input_paths_for_ffmpeg(
output_dir,
logger=None
):
"""Contert source file to format supported in ffmpeg.
"""Convert source file to format supported in ffmpeg.

Currently can convert only exrs. The input filepaths should be files
with same type. Information about input is loaded only from first found
Expand Down
193 changes: 99 additions & 94 deletions openpype/plugins/publish/extract_jpeg_exr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_oiio_tools_path,
is_oiio_supported,

run_subprocess,
path_to_subprocess_arg,

get_transcode_temp_directory,
convert_input_paths_for_ffmpeg,
should_convert_for_ffmpeg
execute,
)

import shutil


class ExtractJpegEXR(pyblish.api.InstancePlugin):
class ExtractThumbnail(pyblish.api.InstancePlugin):
"""Create jpg thumbnail from sequence using ffmpeg"""

label = "Extract Jpeg EXR"
label = "Extract Thumbnail"
order = pyblish.api.ExtractorOrder
families = [
"imagesequence", "render", "render2d",
Expand Down Expand Up @@ -49,7 +47,6 @@ def process(self, instance):
return

filtered_repres = self._get_filtered_repres(instance)

for repre in filtered_repres:
repre_files = repre["files"]
if not isinstance(repre_files, (list, tuple)):
Expand All @@ -62,100 +59,50 @@ def process(self, instance):

full_input_path = os.path.join(stagingdir, input_file)
self.log.info("input {}".format(full_input_path))

do_convert = should_convert_for_ffmpeg(full_input_path)
# If result is None the requirement of conversion can't be
# determined
if do_convert is None:
self.log.info((
"Can't determine if representation requires conversion."
" Skipped."
))
continue

# Do conversion if needed
# - change staging dir of source representation
# - must be set back after output definitions processing
convert_dir = None
if do_convert:
convert_dir = get_transcode_temp_directory()
filename = os.path.basename(full_input_path)
convert_input_paths_for_ffmpeg(
[full_input_path],
convert_dir,
self.log
)
full_input_path = os.path.join(convert_dir, filename)

filename = os.path.splitext(input_file)[0]
if not filename.endswith('.'):
filename += "."
jpeg_file = filename + "jpg"
full_output_path = os.path.join(stagingdir, jpeg_file)

self.log.info("output {}".format(full_output_path))

ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_args = self.ffmpeg_args or {}

jpeg_items = []
jpeg_items.append(path_to_subprocess_arg(ffmpeg_path))
# override file if already exists
jpeg_items.append("-y")
# use same input args like with mov
jpeg_items.extend(ffmpeg_args.get("input") or [])
# input file
jpeg_items.append("-i {}".format(
path_to_subprocess_arg(full_input_path)
))
# output arguments from presets
jpeg_items.extend(ffmpeg_args.get("output") or [])

# If its a movie file, we just want one frame.
if repre["ext"] == "mov":
jpeg_items.append("-vframes 1")

# output file
jpeg_items.append(path_to_subprocess_arg(full_output_path))

subprocess_command = " ".join(jpeg_items)

# run subprocess
self.log.debug("{}".format(subprocess_command))
try: # temporary until oiiotool is supported cross platform
run_subprocess(
subprocess_command, shell=True, logger=self.log
)
except RuntimeError as exp:
if "Compression" in str(exp):
self.log.debug(
"Unsupported compression on input files. Skipping!!!"
)
return
self.log.warning("Conversion crashed", exc_info=True)
raise
thumbnail_created = False
# Try to use FFMPEG if OIIO is not supported (for cases when
# oiiotool isn't available)
if not is_oiio_supported():
thumbnail_created = self.create_thumbnail_ffmpeg(full_input_path, full_output_path) # noqa
else:
# Check if the file can be read by OIIO
oiio_tool_path = get_oiio_tools_path()
args = [
oiio_tool_path, "--info", "-i", full_output_path
]
returncode = execute(args, silent=True)
# If the input can read by OIIO then use OIIO method for
# conversion otherwise use ffmpeg
if returncode == 0:
self.log.info("Input can be read by OIIO, converting with oiiotool now.") # noqa
thumbnail_created = self.create_thumbnail_oiio(full_input_path, full_output_path) # noqa
else:
self.log.info("Converting with FFMPEG because input can't be read by OIIO.") # noqa
thumbnail_created = self.create_thumbnail_ffmpeg(full_input_path, full_output_path) # noqa

# Skip the rest of the process if the thumbnail wasn't created
if not thumbnail_created:
self.log.warning("Thumbanil has not been created.")
return

new_repre = {
"name": "thumbnail",
"ext": "jpg",
"files": jpeg_file,
"stagingDir": stagingdir,
"thumbnail": True,
"tags": ["thumbnail"]
}

# adding representation
self.log.debug("Adding: {}".format(new_repre))
instance.data["representations"].append(new_repre)

# Cleanup temp folder
if convert_dir is not None and os.path.exists(convert_dir):
shutil.rmtree(convert_dir)

# Create only one representation with name 'thumbnail'
# TODO maybe handle way how to decide from which representation
# will be thumbnail created
break
"name": "thumbnail",
This conversation was marked as resolved.
Show resolved Hide resolved
"ext": "jpg",
"files": jpeg_file,
"stagingDir": stagingdir,
"thumbnail": True,
"tags": ["thumbnail"]
}
This conversation was marked as resolved.
Show resolved Hide resolved

# adding representation
self.log.debug("Adding: {}".format(new_repre))
instance.data["representations"].append(new_repre)

def _get_filtered_repres(self, instance):
filtered_repres = []
Expand All @@ -175,3 +122,61 @@ def _get_filtered_repres(self, instance):

filtered_repres.append(repre)
return filtered_repres

def create_thumbnail_oiio(self, src_path, dst_path):
self.log.info("outputting {}".format(dst_path))
oiio_tool_path = get_oiio_tools_path()
oiio_cmd = [oiio_tool_path, "-a",
src_path, "-o",
dst_path
]
subprocess_exr = " ".join(oiio_cmd)
self.log.info(f"running: {subprocess_exr}")
try:
run_subprocess(oiio_cmd, logger=self.log)
return True
except Exception:
self.log.warning(
"Failed to create thubmnail using oiiotool",
exc_info=True
)
return False

def create_thumbnail_ffmpeg(self, src_path, dst_path):
self.log.info("outputting {}".format(dst_path))

ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_args = self.ffmpeg_args or {}

jpeg_items = []
jpeg_items.append(path_to_subprocess_arg(ffmpeg_path))
# override file if already exists
jpeg_items.append("-y")
# flag for large file sizes
max_int = 2147483647
jpeg_items.append("-analyzeduration {}".format(max_int))
jpeg_items.append("-probesize {}".format(max_int))
# use same input args like with mov
jpeg_items.extend(ffmpeg_args.get("input") or [])
# input file
jpeg_items.append("-i {}".format(
path_to_subprocess_arg(src_path)
))
# output arguments from presets
jpeg_items.extend(ffmpeg_args.get("output") or [])
# we just want one frame from movie files
jpeg_items.append("-vframes 1")
# output file
jpeg_items.append(path_to_subprocess_arg(dst_path))
subprocess_command = " ".join(jpeg_items)
try:
run_subprocess(
subprocess_command, shell=True, logger=self.log
)
return True
except Exception:
self.log.warning(
"Failed to create thubmnail using ffmpeg",
exc_info=True
)
return False
2 changes: 1 addition & 1 deletion openpype/settings/defaults/project_settings/deadline.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@
}
}
}
}
}
2 changes: 1 addition & 1 deletion openpype/settings/defaults/project_settings/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"enabled": false,
"profiles": []
},
"ExtractJpegEXR": {
"ExtractThumbnail": {
"enabled": true,
"ffmpeg_args": {
"input": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@
"type": "dict",
"collapsible": true,
"checkbox_key": "enabled",
"key": "ExtractJpegEXR",
"label": "ExtractJpegEXR",
"key": "ExtractThumbnail",
"label": "ExtractThumbnail",
"is_group": true,
"children": [
{
Expand Down