mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
OP-3723 - resize saved images in PS for ffmpeg
Ffmpeg cannot handle pictures higher than 16384x16384. Uses PIL to resize to max size(with aspect ratio). In the future this plugin should be refactored (to use general ExtractThumbnail and ExtractReview).
This commit is contained in:
parent
e93558f961
commit
c9f3340f3c
1 changed files with 49 additions and 6 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import os
|
||||
import shutil
|
||||
from PIL import Image
|
||||
|
||||
import openpype.api
|
||||
import openpype.lib
|
||||
|
|
@ -8,10 +9,17 @@ from openpype.hosts.photoshop import api as photoshop
|
|||
|
||||
class ExtractReview(openpype.api.Extractor):
|
||||
"""
|
||||
Produce a flattened or sequence image file from all 'image' instances.
|
||||
Produce a flattened or sequence image files from all 'image' instances.
|
||||
|
||||
If no 'image' instance is created, it produces flattened image from
|
||||
all visible layers.
|
||||
|
||||
It creates review, thumbnail and mov representations.
|
||||
|
||||
'review' family could be used in other steps as a reference, as it
|
||||
contains flattened image by default. (Eg. artist could load this
|
||||
review as a single item and see full image. In most cases 'image'
|
||||
family is separated by layers to better usage in animation or comp.)
|
||||
"""
|
||||
|
||||
label = "Extract Review"
|
||||
|
|
@ -49,7 +57,7 @@ class ExtractReview(openpype.api.Extractor):
|
|||
"stagingDir": staging_dir,
|
||||
"tags": self.jpg_options['tags'],
|
||||
})
|
||||
|
||||
processed_img_names = img_list
|
||||
else:
|
||||
self.log.info("Extract layers to flatten image.")
|
||||
img_list = self._saves_flattened_layers(staging_dir, layers)
|
||||
|
|
@ -57,26 +65,33 @@ class ExtractReview(openpype.api.Extractor):
|
|||
instance.data["representations"].append({
|
||||
"name": "jpg",
|
||||
"ext": "jpg",
|
||||
"files": img_list,
|
||||
"files": img_list, # cannot be [] for single frame
|
||||
"stagingDir": staging_dir,
|
||||
"tags": self.jpg_options['tags']
|
||||
})
|
||||
processed_img_names = [img_list]
|
||||
|
||||
ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")
|
||||
|
||||
instance.data["stagingDir"] = staging_dir
|
||||
|
||||
# Generate thumbnail.
|
||||
source_files_pattern = os.path.join(staging_dir,
|
||||
self.output_seq_filename)
|
||||
source_files_pattern = self._check_and_resize(processed_img_names,
|
||||
source_files_pattern,
|
||||
staging_dir)
|
||||
# Generate thumbnail
|
||||
thumbnail_path = os.path.join(staging_dir, "thumbnail.jpg")
|
||||
self.log.info(f"Generate thumbnail {thumbnail_path}")
|
||||
args = [
|
||||
ffmpeg_path,
|
||||
"-y",
|
||||
"-i", os.path.join(staging_dir, self.output_seq_filename),
|
||||
"-i", source_files_pattern,
|
||||
"-vf", "scale=300:-1",
|
||||
"-vframes", "1",
|
||||
thumbnail_path
|
||||
]
|
||||
self.log.debug("thumbnail args:: {}".format(args))
|
||||
output = openpype.lib.run_subprocess(args)
|
||||
|
||||
instance.data["representations"].append({
|
||||
|
|
@ -94,11 +109,12 @@ class ExtractReview(openpype.api.Extractor):
|
|||
args = [
|
||||
ffmpeg_path,
|
||||
"-y",
|
||||
"-i", os.path.join(staging_dir, self.output_seq_filename),
|
||||
"-i", source_files_pattern,
|
||||
"-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2",
|
||||
"-vframes", str(img_number),
|
||||
mov_path
|
||||
]
|
||||
self.log.debug("mov args:: {}".format(args))
|
||||
output = openpype.lib.run_subprocess(args)
|
||||
self.log.debug(output)
|
||||
instance.data["representations"].append({
|
||||
|
|
@ -120,6 +136,33 @@ class ExtractReview(openpype.api.Extractor):
|
|||
|
||||
self.log.info(f"Extracted {instance} to {staging_dir}")
|
||||
|
||||
def _check_and_resize(self, processed_img_names, source_files_pattern,
|
||||
staging_dir):
|
||||
"""Check if saved image could be used in ffmpeg.
|
||||
|
||||
Ffmpeg has max size 16384x16384. Saved image(s) must be resized to be
|
||||
used as a source for thumbnail or review mov.
|
||||
"""
|
||||
max_ffmpeg_size = 16384
|
||||
first_url = os.path.join(staging_dir, processed_img_names[0])
|
||||
with Image.open(first_url) as im:
|
||||
width, height = im.size
|
||||
|
||||
if width > max_ffmpeg_size or height > max_ffmpeg_size:
|
||||
resized_dir = os.path.join(staging_dir, "resized")
|
||||
os.mkdir(resized_dir)
|
||||
source_files_pattern = os.path.join(resized_dir,
|
||||
self.output_seq_filename)
|
||||
for file_name in processed_img_names:
|
||||
source_url = os.path.join(staging_dir, file_name)
|
||||
with Image.open(source_url) as res_img:
|
||||
# 'thumbnail' automatically keeps aspect ratio
|
||||
res_img.thumbnail((max_ffmpeg_size, max_ffmpeg_size),
|
||||
Image.ANTIALIAS)
|
||||
res_img.save(os.path.join(resized_dir, file_name))
|
||||
|
||||
return source_files_pattern
|
||||
|
||||
def _get_image_path_from_instances(self, instance):
|
||||
img_list = []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue