AYON: 3rd party addon usage (#5300)

* implemented helper functions to get ffmpeg and oiio tool arguments

* modified validation functions to be able to handle list of arguments

* path getters can return a path in AYON mode if one argument is returned

* removed test exception

* modified docstrings

* is_oiio_supported is using new functions to get launch arguments

* new functions are in lib public =

* use new functions all over the place

* renamed 'ffmpeg_path' to 'ffmpeg_args'

* raise 'ToolNotFoundError' if tool argument could not be found

* reraise 'KnownPublishError' in publish plugins

* fix comment

* simplify args start

* ffmpeg and oiio function require tool name and support additional arguments

* renamed 'get_oiio_tools_args' to 'get_oiio_tool_args'

* fix variable name
This commit is contained in:
Jakub Trllo 2023-07-27 10:54:45 +02:00 committed by GitHub
parent 7b5e716147
commit d63aa34a76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 302 additions and 198 deletions

View file

@ -94,15 +94,14 @@ class ExtractRender(pyblish.api.InstancePlugin):
# Generate thumbnail.
thumbnail_path = os.path.join(path, "thumbnail.png")
ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")
args = [
ffmpeg_path,
args = openpype.lib.get_ffmpeg_tool_args(
"ffmpeg",
"-y",
"-i", os.path.join(path, list(collections[0])[0]),
"-vf", "scale=300:-1",
"-vframes", "1",
thumbnail_path
]
)
process = subprocess.Popen(
args,
stdout=subprocess.PIPE,

View file

@ -2,7 +2,7 @@ import os
import pyblish.api
from openpype.lib import (
get_oiio_tools_path,
get_oiio_tool_args,
run_subprocess,
)
from openpype.pipeline import publish
@ -18,7 +18,7 @@ class ExtractFrames(publish.Extractor):
movie_extensions = ["mov", "mp4"]
def process(self, instance):
oiio_tool_path = get_oiio_tools_path()
oiio_tool_args = get_oiio_tool_args("oiiotool")
staging_dir = self.staging_dir(instance)
output_template = os.path.join(staging_dir, instance.data["name"])
sequence = instance.context.data["activeTimeline"]
@ -36,7 +36,7 @@ class ExtractFrames(publish.Extractor):
output_path = output_template
output_path += ".{:04d}.{}".format(int(frame), output_ext)
args = [oiio_tool_path]
args = list(oiio_tool_args)
ext = os.path.splitext(input_path)[1][1:]
if ext in self.movie_extensions:

View file

@ -15,8 +15,14 @@ import pyblish.api
from maya import cmds # noqa
from openpype.lib.vendor_bin_utils import find_executable
from openpype.lib import source_hash, run_subprocess, get_oiio_tools_path
from openpype.lib import (
find_executable,
source_hash,
run_subprocess,
get_oiio_tool_args,
ToolNotFoundError,
)
from openpype.pipeline import legacy_io, publish, KnownPublishError
from openpype.hosts.maya.api import lib
@ -267,12 +273,11 @@ class MakeTX(TextureProcessor):
"""
maketx_path = get_oiio_tools_path("maketx")
if not maketx_path:
raise AssertionError(
"OIIO 'maketx' tool not found. Result: {}".format(maketx_path)
)
try:
maketx_args = get_oiio_tool_args("maketx")
except ToolNotFoundError:
raise KnownPublishError(
"OpenImageIO is not available on the machine")
# Define .tx filepath in staging if source file is not .tx
fname, ext = os.path.splitext(os.path.basename(source))
@ -328,8 +333,7 @@ class MakeTX(TextureProcessor):
self.log.info("Generating .tx file for %s .." % source)
subprocess_args = [
maketx_path,
subprocess_args = maketx_args + [
"-v", # verbose
"-u", # update mode
# --checknan doesn't influence the output file but aborts the

View file

@ -1,10 +1,9 @@
import os
import shutil
from PIL import Image
from openpype.lib import (
run_subprocess,
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
)
from openpype.pipeline import publish
from openpype.hosts.photoshop import api as photoshop
@ -85,7 +84,7 @@ class ExtractReview(publish.Extractor):
instance.data["representations"].append(repre_skeleton)
processed_img_names = [img_list]
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_args = get_ffmpeg_tool_args("ffmpeg")
instance.data["stagingDir"] = staging_dir
@ -94,13 +93,21 @@ class ExtractReview(publish.Extractor):
source_files_pattern = self._check_and_resize(processed_img_names,
source_files_pattern,
staging_dir)
self._generate_thumbnail(ffmpeg_path, instance, source_files_pattern,
staging_dir)
self._generate_thumbnail(
list(ffmpeg_args),
instance,
source_files_pattern,
staging_dir)
no_of_frames = len(processed_img_names)
if no_of_frames > 1:
self._generate_mov(ffmpeg_path, instance, fps, no_of_frames,
source_files_pattern, staging_dir)
self._generate_mov(
list(ffmpeg_args),
instance,
fps,
no_of_frames,
source_files_pattern,
staging_dir)
self.log.info(f"Extracted {instance} to {staging_dir}")
@ -142,8 +149,9 @@ class ExtractReview(publish.Extractor):
"tags": self.mov_options['tags']
})
def _generate_thumbnail(self, ffmpeg_path, instance, source_files_pattern,
staging_dir):
def _generate_thumbnail(
self, ffmpeg_args, instance, source_files_pattern, staging_dir
):
"""Generates scaled down thumbnail and adds it as representation.
Args:
@ -157,8 +165,7 @@ class ExtractReview(publish.Extractor):
# Generate thumbnail
thumbnail_path = os.path.join(staging_dir, "thumbnail.jpg")
self.log.info(f"Generate thumbnail {thumbnail_path}")
args = [
ffmpeg_path,
args = ffmpeg_args + [
"-y",
"-i", source_files_pattern,
"-vf", "scale=300:-1",

View file

@ -1,8 +1,9 @@
import os
import subprocess
import tempfile
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
get_ffprobe_streams,
path_to_subprocess_arg,
run_subprocess,
@ -62,12 +63,12 @@ class ExtractThumbnailSP(pyblish.api.InstancePlugin):
instance.context.data["cleanupFullPaths"].append(full_thumbnail_path)
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_executable_args = get_ffmpeg_tool_args("ffmpeg")
ffmpeg_args = self.ffmpeg_args or {}
jpeg_items = [
path_to_subprocess_arg(ffmpeg_path),
subprocess.list2cmdline(ffmpeg_executable_args),
# override file if already exists
"-y"
]

View file

@ -9,7 +9,8 @@ import json
import pyblish.api
from openpype.lib import (
get_oiio_tools_path,
get_oiio_tool_args,
ToolNotFoundError,
run_subprocess,
)
from openpype.pipeline import KnownPublishError
@ -34,11 +35,12 @@ class ExtractConvertToEXR(pyblish.api.InstancePlugin):
if not repres:
return
oiio_path = get_oiio_tools_path()
# Raise an exception when oiiotool is not available
# - this can currently happen on MacOS machines
if not os.path.exists(oiio_path):
KnownPublishError(
try:
oiio_args = get_oiio_tool_args("oiiotool")
except ToolNotFoundError:
# Raise an exception when oiiotool is not available
# - this can currently happen on MacOS machines
raise KnownPublishError(
"OpenImageIO tool is not available on this machine."
)
@ -64,8 +66,8 @@ class ExtractConvertToEXR(pyblish.api.InstancePlugin):
src_filepaths.add(src_filepath)
args = [
oiio_path, src_filepath,
args = oiio_args + [
src_filepath,
"--compression", self.exr_compression,
# TODO how to define color conversion?
"--colorconvert", "sRGB", "linear",

View file

@ -22,11 +22,14 @@ from .events import (
)
from .vendor_bin_utils import (
ToolNotFoundError,
find_executable,
get_vendor_bin_path,
get_oiio_tools_path,
get_oiio_tool_args,
get_ffmpeg_tool_path,
is_oiio_supported
get_ffmpeg_tool_args,
is_oiio_supported,
)
from .attribute_definitions import (
@ -172,7 +175,6 @@ __all__ = [
"emit_event",
"register_event_callback",
"find_executable",
"get_openpype_execute_args",
"get_linux_launcher_args",
"execute",
@ -186,9 +188,13 @@ __all__ = [
"env_value_to_bool",
"get_paths_from_environ",
"ToolNotFoundError",
"find_executable",
"get_vendor_bin_path",
"get_oiio_tools_path",
"get_oiio_tool_args",
"get_ffmpeg_tool_path",
"get_ffmpeg_tool_args",
"is_oiio_supported",
"AbstractAttrDef",

View file

@ -11,8 +11,8 @@ import xml.etree.ElementTree
from .execute import run_subprocess
from .vendor_bin_utils import (
get_ffmpeg_tool_path,
get_oiio_tools_path,
get_ffmpeg_tool_args,
get_oiio_tool_args,
is_oiio_supported,
)
@ -83,11 +83,11 @@ def get_oiio_info_for_input(filepath, logger=None, subimages=False):
Stdout should contain xml format string.
"""
args = [
get_oiio_tools_path(),
args = get_oiio_tool_args(
"oiiotool",
"--info",
"-v"
]
)
if subimages:
args.append("-a")
@ -486,12 +486,11 @@ def convert_for_ffmpeg(
compression = "none"
# Prepare subprocess arguments
oiio_cmd = [
get_oiio_tools_path(),
oiio_cmd = get_oiio_tool_args(
"oiiotool",
# Don't add any additional attributes
"--nosoftwareattrib",
]
)
# Add input compression if available
if compression:
oiio_cmd.extend(["--compression", compression])
@ -656,12 +655,11 @@ def convert_input_paths_for_ffmpeg(
for input_path in input_paths:
# Prepare subprocess arguments
oiio_cmd = [
get_oiio_tools_path(),
oiio_cmd = get_oiio_tool_args(
"oiiotool",
# Don't add any additional attributes
"--nosoftwareattrib",
]
)
# Add input compression if available
if compression:
oiio_cmd.extend(["--compression", compression])
@ -729,8 +727,8 @@ def get_ffprobe_data(path_to_file, logger=None):
logger.info(
"Getting information about input \"{}\".".format(path_to_file)
)
args = [
get_ffmpeg_tool_path("ffprobe"),
ffprobe_args = get_ffmpeg_tool_args("ffprobe")
args = ffprobe_args + [
"-hide_banner",
"-loglevel", "fatal",
"-show_error",
@ -1084,13 +1082,13 @@ def convert_colorspace(
if logger is None:
logger = logging.getLogger(__name__)
oiio_cmd = [
get_oiio_tools_path(),
oiio_cmd = get_oiio_tool_args(
"oiiotool",
input_path,
# Don't add any additional attributes
"--nosoftwareattrib",
"--colorconfig", config_path
]
)
if all([target_colorspace, view, display]):
raise ValueError("Colorspace and both screen and display"

View file

@ -3,9 +3,15 @@ import logging
import platform
import subprocess
from openpype import AYON_SERVER_ENABLED
log = logging.getLogger("Vendor utils")
class ToolNotFoundError(Exception):
"""Raised when tool arguments are not found."""
class CachedToolPaths:
"""Cache already used and discovered tools and their executables.
@ -252,7 +258,7 @@ def _check_args_returncode(args):
return proc.returncode == 0
def _oiio_executable_validation(filepath):
def _oiio_executable_validation(args):
"""Validate oiio tool executable if can be executed.
Validation has 2 steps. First is using 'find_executable' to fill possible
@ -270,32 +276,63 @@ def _oiio_executable_validation(filepath):
should be used.
Args:
filepath (str): Path to executable.
args (Union[str, list[str]]): Arguments to launch tool or
path to tool executable.
Returns:
bool: Filepath is valid executable.
"""
filepath = find_executable(filepath)
if not filepath:
if not args:
return False
return _check_args_returncode([filepath, "--help"])
if not isinstance(args, list):
filepath = find_executable(args)
if not filepath:
return False
args = [filepath]
return _check_args_returncode(args + ["--help"])
def _get_ayon_oiio_tool_args(tool_name):
try:
# Use 'ayon-third-party' addon to get oiio arguments
from ayon_third_party import get_oiio_arguments
except Exception:
print("!!! Failed to import 'ayon_third_party' addon.")
return None
try:
return get_oiio_arguments(tool_name)
except Exception as exc:
print("!!! Failed to get OpenImageIO args. Reason: {}".format(exc))
return None
def get_oiio_tools_path(tool="oiiotool"):
"""Path to vendorized OpenImageIO tool executables.
"""Path to OpenImageIO tool executables.
On Window it adds .exe extension if missing from tool argument.
On Windows it adds .exe extension if missing from tool argument.
Args:
tool (string): Tool name (oiiotool, maketx, ...).
tool (string): Tool name 'oiiotool', 'maketx', etc.
Default is "oiiotool".
"""
if CachedToolPaths.is_tool_cached(tool):
return CachedToolPaths.get_executable_path(tool)
if AYON_SERVER_ENABLED:
args = _get_ayon_oiio_tool_args(tool)
if args:
if len(args) > 1:
raise ValueError(
"AYON oiio arguments consist of multiple arguments."
)
tool_executable_path = args[0]
CachedToolPaths.cache_executable_path(tool, tool_executable_path)
return tool_executable_path
custom_paths_str = os.environ.get("OPENPYPE_OIIO_PATHS") or ""
tool_executable_path = find_tool_in_custom_paths(
custom_paths_str.split(os.pathsep),
@ -321,7 +358,33 @@ def get_oiio_tools_path(tool="oiiotool"):
return tool_executable_path
def _ffmpeg_executable_validation(filepath):
def get_oiio_tool_args(tool_name, *extra_args):
"""Arguments to launch OpenImageIO tool.
Args:
tool_name (str): Tool name 'oiiotool', 'maketx', etc.
*extra_args (str): Extra arguments to add to after tool arguments.
Returns:
list[str]: List of arguments.
"""
extra_args = list(extra_args)
if AYON_SERVER_ENABLED:
args = _get_ayon_oiio_tool_args(tool_name)
if args:
return args + extra_args
path = get_oiio_tools_path(tool_name)
if path:
return [path] + extra_args
raise ToolNotFoundError(
"OIIO '{}' tool not found.".format(tool_name)
)
def _ffmpeg_executable_validation(args):
"""Validate ffmpeg tool executable if can be executed.
Validation has 2 steps. First is using 'find_executable' to fill possible
@ -338,24 +401,45 @@ def _ffmpeg_executable_validation(filepath):
It does not validate if the executable is really a ffmpeg tool.
Args:
filepath (str): Path to executable.
args (Union[str, list[str]]): Arguments to launch tool or
path to tool executable.
Returns:
bool: Filepath is valid executable.
"""
filepath = find_executable(filepath)
if not filepath:
if not args:
return False
return _check_args_returncode([filepath, "-version"])
if not isinstance(args, list):
filepath = find_executable(args)
if not filepath:
return False
args = [filepath]
return _check_args_returncode(args + ["--help"])
def _get_ayon_ffmpeg_tool_args(tool_name):
try:
# Use 'ayon-third-party' addon to get ffmpeg arguments
from ayon_third_party import get_ffmpeg_arguments
except Exception:
print("!!! Failed to import 'ayon_third_party' addon.")
return None
try:
return get_ffmpeg_arguments(tool_name)
except Exception as exc:
print("!!! Failed to get FFmpeg args. Reason: {}".format(exc))
return None
def get_ffmpeg_tool_path(tool="ffmpeg"):
"""Path to vendorized FFmpeg executable.
Args:
tool (string): Tool name (ffmpeg, ffprobe, ...).
tool (str): Tool name 'ffmpeg', 'ffprobe', etc.
Default is "ffmpeg".
Returns:
@ -365,6 +449,17 @@ def get_ffmpeg_tool_path(tool="ffmpeg"):
if CachedToolPaths.is_tool_cached(tool):
return CachedToolPaths.get_executable_path(tool)
if AYON_SERVER_ENABLED:
args = _get_ayon_ffmpeg_tool_args(tool)
if args is not None:
if len(args) > 1:
raise ValueError(
"AYON ffmpeg arguments consist of multiple arguments."
)
tool_executable_path = args[0]
CachedToolPaths.cache_executable_path(tool, tool_executable_path)
return tool_executable_path
custom_paths_str = os.environ.get("OPENPYPE_FFMPEG_PATHS") or ""
tool_executable_path = find_tool_in_custom_paths(
custom_paths_str.split(os.pathsep),
@ -390,19 +485,44 @@ def get_ffmpeg_tool_path(tool="ffmpeg"):
return tool_executable_path
def get_ffmpeg_tool_args(tool_name, *extra_args):
"""Arguments to launch FFmpeg tool.
Args:
tool_name (str): Tool name 'ffmpeg', 'ffprobe', exc.
*extra_args (str): Extra arguments to add to after tool arguments.
Returns:
list[str]: List of arguments.
"""
extra_args = list(extra_args)
if AYON_SERVER_ENABLED:
args = _get_ayon_ffmpeg_tool_args(tool_name)
if args:
return args + extra_args
executable_path = get_ffmpeg_tool_path(tool_name)
if executable_path:
return [executable_path] + extra_args
raise ToolNotFoundError(
"FFmpeg '{}' tool not found.".format(tool_name)
)
def is_oiio_supported():
"""Checks if oiiotool is configured for this platform.
Returns:
bool: OIIO tool executable is available.
"""
loaded_path = oiio_path = get_oiio_tools_path()
if oiio_path:
oiio_path = find_executable(oiio_path)
if not oiio_path:
log.debug("OIIOTool is not configured or not present at {}".format(
loaded_path
))
try:
args = get_oiio_tool_args("oiiotool")
except ToolNotFoundError:
args = None
if not args:
log.debug("OIIOTool is not configured or not present.")
return False
return True
return _oiio_executable_validation(args)

View file

@ -1,7 +1,7 @@
import os
import pyblish
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
run_subprocess
)
import tempfile
@ -20,9 +20,6 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
label = "Extract OTIO Audio Tracks"
hosts = ["hiero", "resolve", "flame"]
# FFmpeg tools paths
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
def process(self, context):
"""Convert otio audio track's content to audio representations
@ -91,13 +88,13 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
# temp audio file
audio_fpath = self.create_temp_file(name)
cmd = [
self.ffmpeg_path,
cmd = get_ffmpeg_tool_args(
"ffmpeg",
"-ss", str(start_sec),
"-t", str(duration_sec),
"-i", audio_file,
audio_fpath
]
)
# run subprocess
self.log.debug("Executing: {}".format(" ".join(cmd)))
@ -210,13 +207,13 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
max_duration_sec = max(end_secs)
# create empty cmd
cmd = [
self.ffmpeg_path,
cmd = get_ffmpeg_tool_args(
"ffmpeg",
"-f", "lavfi",
"-i", "anullsrc=channel_layout=stereo:sample_rate=48000",
"-t", str(max_duration_sec),
empty_fpath
]
)
# generate empty with ffmpeg
# run subprocess
@ -295,7 +292,7 @@ class ExtractOtioAudioTracks(pyblish.api.ContextPlugin):
filters_tmp_filepath = tmp_file.name
tmp_file.write(",".join(filters))
args = [self.ffmpeg_path]
args = get_ffmpeg_tool_args("ffmpeg")
args.extend(input_args)
args.extend([
"-filter_complex_script", filters_tmp_filepath,

View file

@ -20,7 +20,7 @@ import opentimelineio as otio
from pyblish import api
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
run_subprocess,
)
from openpype.pipeline import publish
@ -338,8 +338,6 @@ class ExtractOTIOReview(publish.Extractor):
Returns:
otio.time.TimeRange: trimmed available range
"""
# get rendering app path
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
# create path and frame start to destination
output_path, out_frame_start = self._get_ffmpeg_output()
@ -348,7 +346,7 @@ class ExtractOTIOReview(publish.Extractor):
out_frame_start += end_offset
# start command list
command = [ffmpeg_path]
command = get_ffmpeg_tool_args("ffmpeg")
input_extension = None
if sequence:

View file

@ -11,7 +11,7 @@ from copy import deepcopy
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
run_subprocess,
)
from openpype.pipeline import publish
@ -75,14 +75,12 @@ class ExtractOTIOTrimmingVideo(publish.Extractor):
otio_range (opentime.TimeRange): range to trim to
"""
# get rendering app path
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
# create path to destination
output_path = self._get_ffmpeg_output(input_file_path)
# start command list
command = [ffmpeg_path]
command = get_ffmpeg_tool_args("ffmpeg")
video_path = input_file_path
frame_start = otio_range.start_time.value

View file

@ -3,6 +3,7 @@ import re
import copy
import json
import shutil
import subprocess
from abc import ABCMeta, abstractmethod
import six
@ -11,7 +12,7 @@ import speedcopy
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
filter_profiles,
path_to_subprocess_arg,
run_subprocess,
@ -72,9 +73,6 @@ class ExtractReview(pyblish.api.InstancePlugin):
alpha_exts = ["exr", "png", "dpx"]
# FFmpeg tools paths
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
# Preset attributes
profiles = None
@ -787,8 +785,9 @@ class ExtractReview(pyblish.api.InstancePlugin):
arg = arg.replace(identifier, "").strip()
audio_filters.append(arg)
all_args = []
all_args.append(path_to_subprocess_arg(self.ffmpeg_path))
all_args = [
subprocess.list2cmdline(get_ffmpeg_tool_args("ffmpeg"))
]
all_args.extend(input_args)
if video_filters:
all_args.append("-filter:v")

View file

@ -1,5 +1,6 @@
import os
import re
import subprocess
from pprint import pformat
import pyblish.api
@ -7,7 +8,7 @@ import pyblish.api
from openpype.lib import (
path_to_subprocess_arg,
run_subprocess,
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
get_ffprobe_data,
get_ffprobe_streams,
get_ffmpeg_codec_args,
@ -47,8 +48,6 @@ class ExtractReviewSlate(publish.Extractor):
self.log.info("_ slates_data: {}".format(pformat(slates_data)))
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
if "reviewToWidth" in inst_data:
use_legacy_code = True
else:
@ -260,7 +259,7 @@ class ExtractReviewSlate(publish.Extractor):
_remove_at_end.append(slate_v_path)
slate_args = [
path_to_subprocess_arg(ffmpeg_path),
subprocess.list2cmdline(get_ffmpeg_tool_args("ffmpeg")),
" ".join(input_args),
" ".join(output_args)
]
@ -281,7 +280,6 @@ class ExtractReviewSlate(publish.Extractor):
os.path.splitext(slate_v_path))
_remove_at_end.append(slate_silent_path)
self._create_silent_slate(
ffmpeg_path,
slate_v_path,
slate_silent_path,
audio_codec,
@ -309,12 +307,12 @@ class ExtractReviewSlate(publish.Extractor):
"[0:v] [1:v] concat=n=2:v=1:a=0 [v]",
"-map", '[v]'
]
concat_args = [
ffmpeg_path,
concat_args = get_ffmpeg_tool_args(
"ffmpeg",
"-y",
"-i", slate_v_path,
"-i", input_path,
]
)
concat_args.extend(fmap)
if offset_timecode:
concat_args.extend(["-timecode", offset_timecode])
@ -490,7 +488,6 @@ class ExtractReviewSlate(publish.Extractor):
def _create_silent_slate(
self,
ffmpeg_path,
src_path,
dst_path,
audio_codec,
@ -515,8 +512,8 @@ class ExtractReviewSlate(publish.Extractor):
one_frame_duration = str(int(one_frame_duration)) + "us"
self.log.debug("One frame duration is {}".format(one_frame_duration))
slate_silent_args = [
ffmpeg_path,
slate_silent_args = get_ffmpeg_tool_args(
"ffmpeg",
"-i", src_path,
"-f", "lavfi", "-i",
"anullsrc=r={}:cl={}:d={}".format(
@ -531,7 +528,7 @@ class ExtractReviewSlate(publish.Extractor):
"-shortest",
"-y",
dst_path
]
)
# run slate generation subprocess
self.log.debug("Silent Slate Executing: {}".format(
" ".join(slate_silent_args)

View file

@ -5,7 +5,12 @@ import shutil
import pyblish.api
from openpype.lib import run_subprocess, get_oiio_tools_path
from openpype.lib import (
run_subprocess,
get_oiio_tool_args,
ToolNotFoundError,
)
from openpype.pipeline import KnownPublishError
class ExtractScanlineExr(pyblish.api.InstancePlugin):
@ -45,11 +50,11 @@ class ExtractScanlineExr(pyblish.api.InstancePlugin):
stagingdir = os.path.normpath(repre.get("stagingDir"))
oiio_tool_path = get_oiio_tools_path()
if not os.path.exists(oiio_tool_path):
self.log.error(
"OIIO tool not found in {}".format(oiio_tool_path))
raise AssertionError("OIIO tool not found")
try:
oiio_tool_args = get_oiio_tool_args("oiiotool")
except ToolNotFoundError:
self.log.error("OIIO tool not found.")
raise KnownPublishError("OIIO tool not found")
for file in input_files:
@ -57,8 +62,7 @@ class ExtractScanlineExr(pyblish.api.InstancePlugin):
temp_name = os.path.join(stagingdir, "__{}".format(file))
# move original render to temp location
shutil.move(original_name, temp_name)
oiio_cmd = [
oiio_tool_path,
oiio_cmd = oiio_tool_args + [
os.path.join(stagingdir, temp_name), "--scanline", "-o",
os.path.join(stagingdir, original_name)
]

View file

@ -1,10 +1,11 @@
import os
import subprocess
import tempfile
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_oiio_tools_path,
get_ffmpeg_tool_args,
get_oiio_tool_args,
is_oiio_supported,
run_subprocess,
@ -174,12 +175,11 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
def create_thumbnail_oiio(self, src_path, dst_path):
self.log.info("Extracting thumbnail {}".format(dst_path))
oiio_tool_path = get_oiio_tools_path()
oiio_cmd = [
oiio_tool_path,
oiio_cmd = get_oiio_tool_args(
"oiiotool",
"-a", src_path,
"-o", dst_path
]
)
self.log.debug("running: {}".format(" ".join(oiio_cmd)))
try:
run_subprocess(oiio_cmd, logger=self.log)
@ -194,27 +194,27 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
def create_thumbnail_ffmpeg(self, src_path, dst_path):
self.log.info("outputting {}".format(dst_path))
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_path_args = get_ffmpeg_tool_args("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")
jpeg_items = [
subprocess.list2cmdline(ffmpeg_path_args)
]
# flag for large file sizes
max_int = 2147483647
jpeg_items.append("-analyzeduration {}".format(max_int))
jpeg_items.append("-probesize {}".format(max_int))
jpeg_items.extend([
"-y",
"-analyzeduration", str(max_int),
"-probesize", str(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)
))
jpeg_items.extend(["-i", 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")
jpeg_items.extend(["-vframes", "1"])
# output file
jpeg_items.append(path_to_subprocess_arg(dst_path))
subprocess_command = " ".join(jpeg_items)

View file

@ -17,8 +17,8 @@ import tempfile
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_oiio_tools_path,
get_ffmpeg_tool_args,
get_oiio_tool_args,
is_oiio_supported,
run_subprocess,
@ -144,12 +144,11 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin):
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,
oiio_cmd = get_oiio_tool_args(
"oiiotool",
"-a", src_path,
"-o", dst_path
]
)
self.log.info("Running: {}".format(" ".join(oiio_cmd)))
try:
run_subprocess(oiio_cmd, logger=self.log)
@ -162,18 +161,16 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin):
return False
def create_thumbnail_ffmpeg(self, src_path, dst_path):
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
max_int = str(2147483647)
ffmpeg_cmd = [
ffmpeg_path,
ffmpeg_cmd = get_ffmpeg_tool_args(
"ffmpeg",
"-y",
"-analyzeduration", max_int,
"-probesize", max_int,
"-i", src_path,
"-vframes", "1",
dst_path
]
)
self.log.info("Running: {}".format(" ".join(ffmpeg_cmd)))
try:

View file

@ -4,7 +4,7 @@ from pprint import pformat
import pyblish.api
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
run_subprocess,
)
from openpype.pipeline import publish
@ -32,7 +32,7 @@ class ExtractTrimVideoAudio(publish.Extractor):
instance.data["representations"] = list()
# get ffmpet path
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffmpeg_tool_args = get_ffmpeg_tool_args("ffmpeg")
# get staging dir
staging_dir = self.staging_dir(instance)
@ -76,8 +76,7 @@ class ExtractTrimVideoAudio(publish.Extractor):
if "trimming" not in fml
]
ffmpeg_args = [
ffmpeg_path,
ffmpeg_args = ffmpeg_tool_args + [
"-ss", str(clip_start_h / fps),
"-i", video_file_path,
"-t", str(clip_dur_h / fps)

View file

@ -8,21 +8,15 @@ from string import Formatter
import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins
from openpype.lib import (
get_ffmpeg_tool_path,
get_ffmpeg_tool_args,
get_ffmpeg_codec_args,
get_ffmpeg_format_args,
convert_ffprobe_fps_value,
convert_ffprobe_fps_to_float,
)
ffmpeg_path = get_ffmpeg_tool_path("ffmpeg")
ffprobe_path = get_ffmpeg_tool_path("ffprobe")
FFMPEG = (
'"{}"%(input_args)s -i "%(input)s" %(filters)s %(args)s%(output)s'
).format(ffmpeg_path)
'{}%(input_args)s -i "%(input)s" %(filters)s %(args)s%(output)s'
).format(subprocess.list2cmdline(get_ffmpeg_tool_args("ffmpeg")))
DRAWTEXT = (
"drawtext@'%(label)s'=fontfile='%(font)s':text=\\'%(text)s\\':"
@ -46,14 +40,14 @@ def _get_ffprobe_data(source):
:param str source: source media file
:rtype: [{}, ...]
"""
command = [
ffprobe_path,
command = get_ffmpeg_tool_args(
"ffprobe",
"-v", "quiet",
"-print_format", "json",
"-show_format",
"-show_streams",
source
]
)
kwargs = {
"stdout": subprocess.PIPE,
}

View file

@ -7,8 +7,8 @@ from openpype.style import get_objected_colors
from openpype.lib import (
run_subprocess,
is_oiio_supported,
get_oiio_tools_path,
get_ffmpeg_tool_path,
get_oiio_tool_args,
get_ffmpeg_tool_args,
)
from openpype.lib.transcoding import (
IMAGE_EXTENSIONS,
@ -481,12 +481,12 @@ def _convert_thumbnail_oiio(src_path, dst_path):
if not is_oiio_supported():
return None
oiio_cmd = [
get_oiio_tools_path(),
oiio_cmd = get_oiio_tool_args(
"oiiotool",
"-i", src_path,
"--subimage", "0",
"-o", dst_path
]
)
try:
_run_silent_subprocess(oiio_cmd)
except Exception:
@ -495,12 +495,12 @@ def _convert_thumbnail_oiio(src_path, dst_path):
def _convert_thumbnail_ffmpeg(src_path, dst_path):
ffmpeg_cmd = [
get_ffmpeg_tool_path(),
ffmpeg_cmd = get_ffmpeg_tool_args(
"ffmpeg",
"-y",
"-i", src_path,
dst_path
]
)
try:
_run_silent_subprocess(ffmpeg_cmd)
except Exception:

View file

@ -5,6 +5,8 @@ import clique
import subprocess
import openpype.lib
from qtpy import QtWidgets, QtCore
from openpype.lib import get_ffprobe_data
from . import DropEmpty, ComponentsList, ComponentItem
@ -269,26 +271,8 @@ class DropDataFrame(QtWidgets.QFrame):
self._process_data(data)
def load_data_with_probe(self, filepath):
ffprobe_path = openpype.lib.get_ffmpeg_tool_path("ffprobe")
args = [
"\"{}\"".format(ffprobe_path),
'-v', 'quiet',
'-print_format json',
'-show_format',
'-show_streams',
'"{}"'.format(filepath)
]
ffprobe_p = subprocess.Popen(
' '.join(args),
stdout=subprocess.PIPE,
shell=True
)
ffprobe_output = ffprobe_p.communicate()[0]
if ffprobe_p.returncode != 0:
raise RuntimeError(
'Failed on ffprobe: check if ffprobe path is set in PATH env'
)
return json.loads(ffprobe_output)['streams'][0]
ffprobe_data = get_ffprobe_data(filepath)
return ffprobe_data["streams"][0]
def get_file_data(self, data):
filepath = data['files'][0]