mirror of
https://github.com/blw1138/Zordon.git
synced 2025-12-17 08:48:13 +00:00
* Add get_detected_gpus() and supported_render_engines() to Blender class * Parse help args for Blender * Return dict instead of list * Parse args for FFMPEG * Add API to get renderer args * Only return available renderers * Parse help args for Blender * Return dict instead of list * Parse args for FFMPEG * Rebase off master * Rebase * Change methods from class methods to instance methods * FFMPEG format fetching
92 lines
3.8 KiB
Python
92 lines
3.8 KiB
Python
try:
|
|
from .base_engine import *
|
|
except ImportError:
|
|
from base_engine import *
|
|
import re
|
|
|
|
|
|
class FFMPEG(BaseRenderEngine):
|
|
|
|
def version(self):
|
|
version = None
|
|
try:
|
|
ver_out = subprocess.check_output([self.renderer_path(), '-version'],
|
|
timeout=SUBPROCESS_TIMEOUT).decode('utf-8')
|
|
match = re.match(".*version\s*(\S+)\s*Copyright", ver_out)
|
|
if match:
|
|
version = match.groups()[0]
|
|
except Exception as e:
|
|
logger.error("Failed to get FFMPEG version: {}".format(e))
|
|
return version
|
|
|
|
def get_encoders(self):
|
|
raw_stdout = subprocess.check_output([self.renderer_path(), '-encoders'], stderr=subprocess.DEVNULL,
|
|
timeout=SUBPROCESS_TIMEOUT).decode('utf-8')
|
|
pattern = '(?P<type>[VASFXBD.]{6})\s+(?P<name>\S{2,})\s+(?P<description>.*)'
|
|
encoders = [m.groupdict() for m in re.finditer(pattern, raw_stdout)]
|
|
return encoders
|
|
|
|
def get_formats(self):
|
|
encoders = [x['name'] for x in self.get_all_formats() if 'E' in x['type']]
|
|
return encoders
|
|
|
|
def get_all_formats(self):
|
|
formats_raw = subprocess.check_output([self.renderer_path(), '-formats'], stderr=subprocess.DEVNULL,
|
|
timeout=SUBPROCESS_TIMEOUT).decode('utf-8')
|
|
pattern = '(?P<type>[DE]{1,2})\s+(?P<id>\S{2,})\s+(?P<name>.*)'
|
|
all_formats = [m.groupdict() for m in re.finditer(pattern, formats_raw)]
|
|
return all_formats
|
|
|
|
def extension_for_format(self, ffmpeg_format):
|
|
# Extract the common extension using regex
|
|
muxer_flag = 'muxer' if 'E' in ffmpeg_format['type'] else 'demuxer'
|
|
format_detail_raw = subprocess.check_output(
|
|
[self.renderer_path(), '-hide_banner', '-h', f"{muxer_flag}={ffmpeg_format['id']}"]).decode('utf-8')
|
|
pattern = r"Common extensions: (\w+)"
|
|
common_extensions = re.findall(pattern, format_detail_raw)
|
|
found_extensions = []
|
|
if common_extensions:
|
|
found_extensions = common_extensions[0].split(',')
|
|
return found_extensions
|
|
|
|
def get_output_formats(self):
|
|
return [x for x in self.get_all_formats() if 'E' in x['type'].upper()]
|
|
|
|
def get_frame_count(self, path_to_file):
|
|
raw_stdout = subprocess.check_output([self.default_renderer_path(), '-i', path_to_file, '-map', '0:v:0', '-c', 'copy',
|
|
'-f', 'null', '-'], stderr=subprocess.STDOUT,
|
|
timeout=SUBPROCESS_TIMEOUT).decode('utf-8')
|
|
match = re.findall(r'frame=\s*(\d+)', raw_stdout)
|
|
if match:
|
|
frame_number = int(match[-1])
|
|
return frame_number
|
|
|
|
def get_arguments(self):
|
|
help_text = subprocess.check_output([self.renderer_path(), '-h', 'long'], stderr=subprocess.STDOUT).decode('utf-8')
|
|
lines = help_text.splitlines()
|
|
|
|
options = {}
|
|
current_category = None
|
|
|
|
for line in lines:
|
|
line = line.strip()
|
|
|
|
if line.endswith(":") and "options" in line.lower():
|
|
current_category = line.split('options')[0].strip()
|
|
options[current_category] = {}
|
|
elif line: # Ignore blank lines
|
|
split_line = line.split(' ', 2)
|
|
flag = split_line[0]
|
|
argument = split_line[1] if len(split_line) > 1 else ''
|
|
description = split_line[2] if len(split_line) > 2 else ''
|
|
|
|
if current_category:
|
|
name = flag.strip('-')
|
|
options[current_category][name] = {
|
|
'flag': flag, 'description': description.strip(), 'takes_argument': bool(argument)
|
|
}
|
|
return options
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(FFMPEG().get_all_formats()) |