moving out specific method from generic library

This commit is contained in:
Jakub Jezek 2024-09-17 10:26:45 +02:00
parent 23a63d6abf
commit ede1b17370
No known key found for this signature in database
GPG key ID: 06DBD609ADF27FD9
3 changed files with 149 additions and 134 deletions

View file

@ -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",

View file

@ -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.

View file

@ -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