mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
moving out specific method from generic library
This commit is contained in:
parent
23a63d6abf
commit
ede1b17370
3 changed files with 149 additions and 134 deletions
|
|
@ -107,7 +107,6 @@ from .transcoding import (
|
|||
convert_ffprobe_fps_to_float,
|
||||
get_rescaled_command_arguments,
|
||||
get_media_mime_type,
|
||||
get_image_info_metadata,
|
||||
)
|
||||
|
||||
from .plugin_tools import (
|
||||
|
|
@ -207,7 +206,6 @@ __all__ = [
|
|||
"convert_ffprobe_fps_to_float",
|
||||
"get_rescaled_command_arguments",
|
||||
"get_media_mime_type",
|
||||
"get_image_info_metadata",
|
||||
|
||||
"compile_list_of_regexes",
|
||||
|
||||
|
|
|
|||
|
|
@ -835,134 +835,6 @@ def get_ffprobe_streams(path_to_file, logger=None):
|
|||
return get_ffprobe_data(path_to_file, logger)["streams"]
|
||||
|
||||
|
||||
def get_image_info_metadata(
|
||||
path_to_file,
|
||||
keys=None,
|
||||
logger=None,
|
||||
):
|
||||
"""Get metadata from image file.
|
||||
|
||||
At first it will try to detect if the image input is supported by
|
||||
OpenImageIO. If it is then it gets the metadata from the image using
|
||||
OpenImageIO. If it is not supported by OpenImageIO then it will try to
|
||||
get the metadata using FFprobe.
|
||||
|
||||
Args:
|
||||
path_to_file (str): Path to image file.
|
||||
keys (list[str]): List of keys that should be returned. If None then
|
||||
all keys are returned. Keys are expected all lowercase.
|
||||
Additional keys are:
|
||||
- "framerate" - will be created from "r_frame_rate" or
|
||||
"framespersecond" and evaluated to float value.
|
||||
logger (logging.Logger): Logger used for logging.
|
||||
"""
|
||||
if logger is None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def _ffprobe_metadata_conversion(metadata):
|
||||
"""Convert ffprobe metadata unified format."""
|
||||
output = {}
|
||||
for key, val in metadata.items():
|
||||
if key in ("tags", "disposition"):
|
||||
output.update(val)
|
||||
else:
|
||||
output[key] = val
|
||||
return output
|
||||
|
||||
def _get_video_metadata_from_ffprobe(ffprobe_stream):
|
||||
"""Extract video metadata from ffprobe stream.
|
||||
|
||||
Args:
|
||||
ffprobe_stream (dict): Stream data obtained from ffprobe.
|
||||
|
||||
Returns:
|
||||
dict: Video metadata extracted from the ffprobe stream.
|
||||
"""
|
||||
video_stream = None
|
||||
for stream in ffprobe_stream["streams"]:
|
||||
if stream["codec_type"] == "video":
|
||||
video_stream = stream
|
||||
break
|
||||
metadata_stream = _ffprobe_metadata_conversion(video_stream)
|
||||
return metadata_stream
|
||||
|
||||
metadata_stream = None
|
||||
ext = os.path.splitext(path_to_file)[-1].lower()
|
||||
if ext not in IMAGE_EXTENSIONS:
|
||||
logger.info((
|
||||
"File extension \"{}\" is not supported by OpenImageIO."
|
||||
" Trying to get metadata using FFprobe."
|
||||
).format(ext))
|
||||
ffprobe_stream = get_ffprobe_data(path_to_file, logger)
|
||||
if "streams" in ffprobe_stream and len(ffprobe_stream["streams"]) > 0:
|
||||
metadata_stream = _get_video_metadata_from_ffprobe(ffprobe_stream)
|
||||
|
||||
if not metadata_stream and is_oiio_supported():
|
||||
oiio_stream = get_oiio_info_for_input(path_to_file, logger=logger)
|
||||
if "attribs" in (oiio_stream or {}):
|
||||
metadata_stream = {}
|
||||
for key, val in oiio_stream["attribs"].items():
|
||||
if "smpte:" in key.lower():
|
||||
key = key.replace("smpte:", "")
|
||||
metadata_stream[key.lower()] = val
|
||||
for key, val in oiio_stream.items():
|
||||
if key == "attribs":
|
||||
continue
|
||||
metadata_stream[key] = val
|
||||
else:
|
||||
logger.info((
|
||||
"OpenImageIO is not supported on this system."
|
||||
" Trying to get metadata using FFprobe."
|
||||
))
|
||||
ffprobe_stream = get_ffprobe_data(path_to_file, logger)
|
||||
if "streams" in ffprobe_stream and len(ffprobe_stream["streams"]) > 0:
|
||||
metadata_stream = _get_video_metadata_from_ffprobe(ffprobe_stream)
|
||||
|
||||
if not metadata_stream:
|
||||
logger.warning("Failed to get metadata from image file.")
|
||||
return {}
|
||||
|
||||
if keys is None:
|
||||
return metadata_stream
|
||||
|
||||
# create framerate key from available ffmpeg:r_frame_rate
|
||||
# or oiiotool:framespersecond and evaluate its string expression
|
||||
# value into flaot value
|
||||
if (
|
||||
"r_frame_rate" in metadata_stream
|
||||
or "framespersecond" in metadata_stream
|
||||
):
|
||||
rate_info = metadata_stream.get("r_frame_rate")
|
||||
if rate_info is None:
|
||||
rate_info = metadata_stream.get("framespersecond")
|
||||
|
||||
# calculate framerate from string expression
|
||||
if "/" in str(rate_info):
|
||||
time, frame = str(rate_info).split("/")
|
||||
rate_info = float(time) / float(frame)
|
||||
|
||||
try:
|
||||
metadata_stream["framerate"] = float(str(rate_info))
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"Failed to evaluate '{}' value to framerate. Error: {}".format(
|
||||
rate_info, e)
|
||||
)
|
||||
|
||||
# aggregate all required metadata from prepared metadata stream
|
||||
output = {}
|
||||
for key in keys:
|
||||
for k, v in metadata_stream.items():
|
||||
if key == k:
|
||||
output[key] = v
|
||||
break
|
||||
if isinstance(v, dict) and key in v:
|
||||
output[key] = v[key]
|
||||
break
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def get_ffmpeg_format_args(ffprobe_data, source_ffmpeg_cmd=None):
|
||||
"""Copy format from input metadata for output.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
|
||||
|
|
@ -5,8 +7,15 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
|
||||
from ayon_api import get_representations
|
||||
from ayon_core.pipeline import load, Anatomy
|
||||
from ayon_core.lib import get_image_info_metadata
|
||||
from ayon_core import resources, style
|
||||
from ayon_core.lib.transcoding import (
|
||||
IMAGE_EXTENSIONS,
|
||||
get_oiio_info_for_input,
|
||||
)
|
||||
from ayon_core.lib import (
|
||||
get_ffprobe_data,
|
||||
is_oiio_supported,
|
||||
)
|
||||
from ayon_core.pipeline.load import get_representation_path_with_anatomy
|
||||
from ayon_core.tools.utils import show_message_dialog
|
||||
|
||||
|
|
@ -228,9 +237,10 @@ class ExportOTIOOptionsDialog(QtWidgets.QDialog):
|
|||
version = self._version_by_representation_id[
|
||||
representation["id"]
|
||||
]
|
||||
name = f'{self._version_path_by_id[version["id"]]}/{representation["name"]}'.replace(
|
||||
"/", "_"
|
||||
)
|
||||
name = (
|
||||
f'{self._version_path_by_id[version["id"]]}'
|
||||
f'/{representation["name"]}'
|
||||
).replace("/", "_")
|
||||
|
||||
clips_data[name] = {
|
||||
"representation": representation,
|
||||
|
|
@ -405,3 +415,138 @@ class ExportOTIOOptionsDialog(QtWidgets.QDialog):
|
|||
0, timeline_framerate)
|
||||
|
||||
self.OTIO.adapters.write_to_file(timeline, output_path)
|
||||
|
||||
|
||||
def get_image_info_metadata(
|
||||
path_to_file,
|
||||
keys=None,
|
||||
logger=None,
|
||||
):
|
||||
"""Get flattened metadata from image file
|
||||
|
||||
With combined approach via FFMPEG and OIIOTool.
|
||||
|
||||
At first it will try to detect if the image input is supported by
|
||||
OpenImageIO. If it is then it gets the metadata from the image using
|
||||
OpenImageIO. If it is not supported by OpenImageIO then it will try to
|
||||
get the metadata using FFprobe.
|
||||
|
||||
Args:
|
||||
path_to_file (str): Path to image file.
|
||||
keys (list[str]): List of keys that should be returned. If None then
|
||||
all keys are returned. Keys are expected all lowercase.
|
||||
Additional keys are:
|
||||
- "framerate" - will be created from "r_frame_rate" or
|
||||
"framespersecond" and evaluated to float value.
|
||||
logger (logging.Logger): Logger used for logging.
|
||||
"""
|
||||
if logger is None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def _ffprobe_metadata_conversion(metadata):
|
||||
"""Convert ffprobe metadata unified format."""
|
||||
output = {}
|
||||
for key, val in metadata.items():
|
||||
if key in ("tags", "disposition"):
|
||||
output.update(val)
|
||||
else:
|
||||
output[key] = val
|
||||
return output
|
||||
|
||||
def _get_video_metadata_from_ffprobe(ffprobe_stream):
|
||||
"""Extract video metadata from ffprobe stream.
|
||||
|
||||
Args:
|
||||
ffprobe_stream (dict): Stream data obtained from ffprobe.
|
||||
|
||||
Returns:
|
||||
dict: Video metadata extracted from the ffprobe stream.
|
||||
"""
|
||||
video_stream = None
|
||||
for stream in ffprobe_stream["streams"]:
|
||||
if stream["codec_type"] == "video":
|
||||
video_stream = stream
|
||||
break
|
||||
metadata_stream = _ffprobe_metadata_conversion(video_stream)
|
||||
return metadata_stream
|
||||
|
||||
metadata_stream = None
|
||||
ext = os.path.splitext(path_to_file)[-1].lower()
|
||||
if ext not in IMAGE_EXTENSIONS:
|
||||
logger.info(
|
||||
(
|
||||
'File extension "{}" is not supported by OpenImageIO.'
|
||||
" Trying to get metadata using FFprobe."
|
||||
).format(ext)
|
||||
)
|
||||
ffprobe_stream = get_ffprobe_data(path_to_file, logger)
|
||||
if "streams" in ffprobe_stream and len(ffprobe_stream["streams"]) > 0:
|
||||
metadata_stream = _get_video_metadata_from_ffprobe(ffprobe_stream)
|
||||
|
||||
if not metadata_stream and is_oiio_supported():
|
||||
oiio_stream = get_oiio_info_for_input(path_to_file, logger=logger)
|
||||
if "attribs" in (oiio_stream or {}):
|
||||
metadata_stream = {}
|
||||
for key, val in oiio_stream["attribs"].items():
|
||||
if "smpte:" in key.lower():
|
||||
key = key.replace("smpte:", "")
|
||||
metadata_stream[key.lower()] = val
|
||||
for key, val in oiio_stream.items():
|
||||
if key == "attribs":
|
||||
continue
|
||||
metadata_stream[key] = val
|
||||
else:
|
||||
logger.info(
|
||||
(
|
||||
"OpenImageIO is not supported on this system."
|
||||
" Trying to get metadata using FFprobe."
|
||||
)
|
||||
)
|
||||
ffprobe_stream = get_ffprobe_data(path_to_file, logger)
|
||||
if "streams" in ffprobe_stream and len(ffprobe_stream["streams"]) > 0:
|
||||
metadata_stream = _get_video_metadata_from_ffprobe(ffprobe_stream)
|
||||
|
||||
if not metadata_stream:
|
||||
logger.warning("Failed to get metadata from image file.")
|
||||
return {}
|
||||
|
||||
if keys is None:
|
||||
return metadata_stream
|
||||
|
||||
# create framerate key from available ffmpeg:r_frame_rate
|
||||
# or oiiotool:framespersecond and evaluate its string expression
|
||||
# value into flaot value
|
||||
if (
|
||||
"r_frame_rate" in metadata_stream
|
||||
or "framespersecond" in metadata_stream
|
||||
):
|
||||
rate_info = metadata_stream.get("r_frame_rate")
|
||||
if rate_info is None:
|
||||
rate_info = metadata_stream.get("framespersecond")
|
||||
|
||||
# calculate framerate from string expression
|
||||
if "/" in str(rate_info):
|
||||
time, frame = str(rate_info).split("/")
|
||||
rate_info = float(time) / float(frame)
|
||||
|
||||
try:
|
||||
metadata_stream["framerate"] = float(str(rate_info))
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"Failed to evaluate '{}' value to framerate. Error: {}".format(
|
||||
rate_info, e
|
||||
)
|
||||
)
|
||||
|
||||
# aggregate all required metadata from prepared metadata stream
|
||||
output = {}
|
||||
for key in keys:
|
||||
for k, v in metadata_stream.items():
|
||||
if key == k:
|
||||
output[key] = v
|
||||
break
|
||||
if isinstance(v, dict) and key in v:
|
||||
output[key] = v[key]
|
||||
break
|
||||
|
||||
return output
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue