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

General: Extract review sequence is not converted with same names #3075

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
run_subprocess,

get_transcode_temp_directory,
convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
should_convert_for_ffmpeg
)

Expand Down Expand Up @@ -59,11 +59,9 @@ def process(self, instance):
if do_convert:
convert_dir = get_transcode_temp_directory()
filename = os.path.basename(full_input_path)
convert_for_ffmpeg(
full_input_path,
convert_input_paths_for_ffmpeg(
[full_input_path],
convert_dir,
None,
None,
self.log
)
full_input_path = os.path.join(convert_dir, filename)
Expand Down
2 changes: 2 additions & 0 deletions openpype/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
get_transcode_temp_directory,
should_convert_for_ffmpeg,
convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
get_ffprobe_data,
get_ffprobe_streams,
get_ffmpeg_codec_args,
Expand Down Expand Up @@ -276,6 +277,7 @@
"get_transcode_temp_directory",
"should_convert_for_ffmpeg",
"convert_for_ffmpeg",
"convert_input_paths_for_ffmpeg",
"get_ffprobe_data",
"get_ffprobe_streams",
"get_ffmpeg_codec_args",
Expand Down
135 changes: 135 additions & 0 deletions openpype/lib/transcoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,11 @@ def should_convert_for_ffmpeg(src_filepath):
return False


# Deprecated since 2022 4 20
# - Reason - Doesn't convert sequences right way: Can't handle gaps, reuse
# first frame for all frames and changes filenames when input
# is sequence.
# - use 'convert_input_paths_for_ffmpeg' instead
def convert_for_ffmpeg(
first_input_path,
output_dir,
Expand Down Expand Up @@ -409,6 +414,12 @@ def convert_for_ffmpeg(
if logger is None:
logger = logging.getLogger(__name__)

logger.warning((
"DEPRECATED: 'openpype.lib.transcoding.convert_for_ffmpeg' is"
" deprecated function of conversion for FFMpeg. Please replace usage"
" with 'openpype.lib.transcoding.convert_input_paths_for_ffmpeg'"
))

ext = os.path.splitext(first_input_path)[1].lower()
if ext != ".exr":
raise ValueError((
Expand Down Expand Up @@ -516,6 +527,130 @@ def convert_for_ffmpeg(
run_subprocess(oiio_cmd, logger=logger)


def convert_input_paths_for_ffmpeg(
input_paths,
output_dir,
logger=None
):
"""Contert 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
file.

Filenames of input files are kept so make sure that output directory
is not the same directory as input files have.
- This way it can handle gaps and can keep input filenames without handling
frame template

Args:
input_paths (str): Paths that should be converted. It is expected that
contains single file or image sequence of samy type.
output_dir (str): Path to directory where output will be rendered.
Must not be same as input's directory.
logger (logging.Logger): Logger used for logging.

Raises:
ValueError: If input filepath has extension not supported by function.
Currently is supported only ".exr" extension.
"""
if logger is None:
logger = logging.getLogger(__name__)

first_input_path = input_paths[0]
ext = os.path.splitext(first_input_path)[1].lower()
if ext != ".exr":
raise ValueError((
"Function 'convert_for_ffmpeg' currently support only"
" \".exr\" extension. Got \"{}\"."
).format(ext))

input_info = get_oiio_info_for_input(first_input_path)

# Change compression only if source compression is "dwaa" or "dwab"
# - they're not supported in ffmpeg
compression = input_info["attribs"].get("compression")
if compression in ("dwaa", "dwab"):
compression = "none"

# Collect channels to export
channel_names = input_info["channelnames"]
review_channels = get_convert_rgb_channels(channel_names)
if review_channels is None:
raise ValueError(
"Couldn't find channels that can be used for conversion."
)

red, green, blue, alpha = review_channels
input_channels = [red, green, blue]
channels_arg = "R={},G={},B={}".format(red, green, blue)
if alpha is not None:
channels_arg += ",A={}".format(alpha)
input_channels.append(alpha)
input_channels_str = ",".join(input_channels)

for input_path in input_paths:
# Prepare subprocess arguments
oiio_cmd = [
get_oiio_tools_path(),

# Don't add any additional attributes
"--nosoftwareattrib",
]
# Add input compression if available
if compression:
oiio_cmd.extend(["--compression", compression])

oiio_cmd.extend([
# Tell oiiotool which channels should be loaded
# - other channels are not loaded to memory so helps to
# avoid memory leak issues
"-i:ch={}".format(input_channels_str), input_path,
# Tell oiiotool which channels should be put to top stack
# (and output)
"--ch", channels_arg
])

for attr_name, attr_value in input_info["attribs"].items():
if not isinstance(attr_value, str):
continue

# Remove attributes that have string value longer than allowed
# length for ffmpeg or when containt unallowed symbols
erase_reason = "Missing reason"
erase_attribute = False
if len(attr_value) > MAX_FFMPEG_STRING_LEN:
erase_reason = "has too long value ({} chars).".format(
len(attr_value)
)

if erase_attribute:
for char in NOT_ALLOWED_FFMPEG_CHARS:
if char in attr_value:
erase_attribute = True
erase_reason = (
"contains unsupported character \"{}\"."
).format(char)
break

if erase_attribute:
# Set attribute to empty string
logger.info((
"Removed attribute \"{}\" from metadata because {}."
).format(attr_name, erase_reason))
oiio_cmd.extend(["--eraseattrib", attr_name])

# Add last argument - path to output
base_filename = os.path.basename(first_input_path)
output_path = os.path.join(output_dir, base_filename)
oiio_cmd.extend([
"-o", output_path
])

logger.debug("Conversion command: {}".format(" ".join(oiio_cmd)))
run_subprocess(oiio_cmd, logger=logger)


# FFMPEG functions
def get_ffprobe_data(path_to_file, logger=None):
"""Load data about entered filepath via ffprobe.
Expand Down
13 changes: 8 additions & 5 deletions openpype/plugins/publish/extract_burnin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
run_openpype_process,

get_transcode_temp_directory,
convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
should_convert_for_ffmpeg,

CREATE_NO_WINDOW
Expand Down Expand Up @@ -187,8 +187,13 @@ def main_process(self, instance):
repre_files = repre["files"]
if isinstance(repre_files, (tuple, list)):
filename = repre_files[0]
src_filepaths = [
os.path.join(src_repre_staging_dir, filename)
for filename in repre_files
]
else:
filename = repre_files
src_filepaths = [os.path.join(src_repre_staging_dir, filename)]

first_input_path = os.path.join(src_repre_staging_dir, filename)
# Determine if representation requires pre conversion for ffmpeg
Expand All @@ -209,11 +214,9 @@ def main_process(self, instance):
new_staging_dir = get_transcode_temp_directory()
repre["stagingDir"] = new_staging_dir

convert_for_ffmpeg(
first_input_path,
convert_input_paths_for_ffmpeg(
src_filepaths,
new_staging_dir,
_temp_data["frameStart"],
_temp_data["frameEnd"],
self.log
)

Expand Down
8 changes: 3 additions & 5 deletions openpype/plugins/publish/extract_jpeg_exr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
path_to_subprocess_arg,

get_transcode_temp_directory,
convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
should_convert_for_ffmpeg
)

Expand Down Expand Up @@ -79,11 +79,9 @@ def process(self, instance):
if do_convert:
convert_dir = get_transcode_temp_directory()
filename = os.path.basename(full_input_path)
convert_for_ffmpeg(
full_input_path,
convert_input_paths_for_ffmpeg(
[full_input_path],
convert_dir,
None,
None,
self.log
)
full_input_path = os.path.join(convert_dir, filename)
Expand Down
18 changes: 9 additions & 9 deletions openpype/plugins/publish/extract_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
path_to_subprocess_arg,

should_convert_for_ffmpeg,
convert_for_ffmpeg,
convert_input_paths_for_ffmpeg,
get_transcode_temp_directory
)
import speedcopy
Expand Down Expand Up @@ -194,16 +194,20 @@ def main_process(self, instance):
src_repre_staging_dir = repre["stagingDir"]
# Receive filepath to first file in representation
first_input_path = None
input_filepaths = []
if not self.input_is_sequence(repre):
first_input_path = os.path.join(
src_repre_staging_dir, repre["files"]
)
input_filepaths.append(first_input_path)
else:
for filename in repre["files"]:
first_input_path = os.path.join(
filepath = os.path.join(
src_repre_staging_dir, filename
)
break
input_filepaths.append(filepath)
if first_input_path is None:
first_input_path = filepath

# Skip if file is not set
if first_input_path is None:
Expand All @@ -230,13 +234,9 @@ def main_process(self, instance):
new_staging_dir = get_transcode_temp_directory()
repre["stagingDir"] = new_staging_dir

frame_start = instance.data["frameStart"]
frame_end = instance.data["frameEnd"]
convert_for_ffmpeg(
first_input_path,
convert_input_paths_for_ffmpeg(
input_filepaths,
new_staging_dir,
frame_start,
frame_end,
self.log
)

Expand Down