Merge pull request #8 from blw1138/blender_videos

Blender videos
This commit is contained in:
2023-06-05 16:46:03 -05:00
committed by GitHub
4 changed files with 93 additions and 14 deletions

View File

@@ -4,6 +4,9 @@ except ImportError:
from base_engine import * from base_engine import *
import json import json
import re import re
import logging
logger = logging.getLogger()
class Blender(BaseRenderEngine): class Blender(BaseRenderEngine):
@@ -61,7 +64,7 @@ class Blender(BaseRenderEngine):
scene_info = None scene_info = None
try: try:
results = cls.run_python_script(project_path, os.path.join(os.path.dirname(os.path.realpath(__file__)), results = cls.run_python_script(project_path, os.path.join(os.path.dirname(os.path.realpath(__file__)),
'scripts', 'get_blender_info.py'), timeout=timeout) 'scripts', 'blender', 'get_file_info.py'), timeout=timeout)
result_text = results.stdout.decode() result_text = results.stdout.decode()
for line in result_text.splitlines(): for line in result_text.splitlines():
if line.startswith('SCENE_DATA:'): if line.startswith('SCENE_DATA:'):
@@ -75,15 +78,10 @@ class Blender(BaseRenderEngine):
@classmethod @classmethod
def pack_project_file(cls, project_path, timeout=30): def pack_project_file(cls, project_path, timeout=30):
# Credit to L0Lock for pack script - https://blender.stackexchange.com/a/243935 # Credit to L0Lock for pack script - https://blender.stackexchange.com/a/243935
pack_expression = "import bpy\n" \
"bpy.ops.file.pack_all()\n" \
"bpy.ops.file.make_paths_absolute()\n" \
"myPath = bpy.data.filepath\n" \
"myPath = str(myPath)\n" \
"bpy.ops.wm.save_as_mainfile(filepath=myPath[:-6]+'_packed'+myPath[-6:])"
try: try:
results = Blender.run_python_expression(project_path, pack_expression, timeout=timeout) logger.info(f"Starting to pack Blender file: {project_path}")
results = cls.run_python_script(project_path, os.path.join(os.path.dirname(os.path.realpath(__file__)),
'scripts', 'blender', 'pack_project.py'), timeout=timeout)
result_text = results.stdout.decode() result_text = results.stdout.decode()
dir_name = os.path.dirname(project_path) dir_name = os.path.dirname(project_path)
@@ -93,10 +91,10 @@ class Blender(BaseRenderEngine):
for err in not_found: for err in not_found:
logger.error(err) logger.error(err)
p = re.compile('Info: Saved "(.*)"') p = re.compile('Saved to: (.*)\n')
match = p.search(result_text) match = p.search(result_text)
if match: if match:
new_path = os.path.join(dir_name, match.group(1)) new_path = os.path.join(dir_name, match.group(1).strip())
logger.info(f'Blender file packed successfully to {new_path}') logger.info(f'Blender file packed successfully to {new_path}')
return new_path return new_path
except Exception as e: except Exception as e:

View File

@@ -0,0 +1,53 @@
import bpy
import os
import shutil
import zipfile
def zip_files(paths, output_zip_path):
with zipfile.ZipFile(output_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for path in paths:
if os.path.isfile(path):
# If the path is a file, add it to the zip
zipf.write(path, arcname=os.path.basename(path))
elif os.path.isdir(path):
# If the path is a directory, add all its files and subdirectories
for root, dirs, files in os.walk(path):
for file in files:
full_path = os.path.join(root, file)
zipf.write(full_path, arcname=os.path.join(os.path.basename(path), os.path.relpath(full_path, path)))
# Get File path
project_path = str(bpy.data.filepath)
# Pack Files
bpy.ops.file.pack_all()
bpy.ops.file.make_paths_absolute()
# Temp dir
tmp_dir = os.path.join(os.path.dirname(project_path), 'tmp')
asset_dir = os.path.join(tmp_dir, 'assets')
os.makedirs(tmp_dir, exist_ok=True)
# Find images we could not pack - usually videos
for img in bpy.data.images:
if not img.packed_file and img.filepath and img.users:
os.makedirs(asset_dir, exist_ok=True)
shutil.copy2(img.filepath, os.path.join(asset_dir, os.path.basename(img.filepath)))
print(f"Copied {os.path.basename(img.filepath)} to tmp directory")
img.filepath = '//' + os.path.join('assets', os.path.basename(img.filepath))
# Save Output
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(tmp_dir, os.path.basename(project_path)), compress=True, relative_remap=False)
# Save Zip
zip_path = os.path.join(os.path.dirname(project_path), f"{os.path.basename(project_path).split('.')[0]}.zip")
zip_files([os.path.join(tmp_dir, os.path.basename(project_path)), asset_dir], zip_path)
if os.path.exists(zip_path):
print(f'Saved to: {zip_path}')
else:
print("Error saving zip file!")
# Cleanup
shutil.rmtree(tmp_dir, ignore_errors=True)

View File

@@ -7,6 +7,7 @@ import shutil
import socket import socket
import threading import threading
import time import time
import zipfile
from datetime import datetime from datetime import datetime
from zipfile import ZipFile from zipfile import ZipFile
@@ -297,7 +298,7 @@ def add_job_handler():
job_dir = os.path.join(server.config['UPLOAD_FOLDER'], '_'.join( job_dir = os.path.join(server.config['UPLOAD_FOLDER'], '_'.join(
[datetime.now().strftime("%Y.%m.%d_%H.%M.%S"), [datetime.now().strftime("%Y.%m.%d_%H.%M.%S"),
jobs_list[0]['renderer'], jobs_list[0]['renderer'],
uploaded_file.filename])) os.path.splitext(uploaded_file.filename)[0]]))
os.makedirs(job_dir, exist_ok=True) os.makedirs(job_dir, exist_ok=True)
upload_dir = os.path.join(job_dir, 'source') upload_dir = os.path.join(job_dir, 'source')
@@ -350,8 +351,7 @@ def add_job(job_params, remove_job_dir_on_failure=False):
args = job_params.get('args', {}) args = job_params.get('args', {})
client = job_params.get('client', None) or RenderQueue.hostname client = job_params.get('client', None) or RenderQueue.hostname
force_start = job_params.get('force_start', False) force_start = job_params.get('force_start', False)
custom_id = None job_dir = None # todo: I dont think this gets set anywhere
job_dir = None
# check for minimum render requirements # check for minimum render requirements
if None in [renderer, input_path, output_path]: if None in [renderer, input_path, output_path]:
@@ -359,6 +359,34 @@ def add_job(job_params, remove_job_dir_on_failure=False):
logger.error(err_msg) logger.error(err_msg)
return {'error': err_msg, 'code': 400} return {'error': err_msg, 'code': 400}
# process uploaded zip files
if '.zip' in input_path:
zip_path = input_path
work_path = os.path.dirname(zip_path)
try:
with zipfile.ZipFile(zip_path, 'r') as myzip:
myzip.extractall(os.path.dirname(zip_path))
project_files = [x for x in os.listdir(work_path) if os.path.isfile(os.path.join(work_path, x))]
project_files = [x for x in project_files if '.zip' not in x]
supported_exts = RenderWorkerFactory.class_for_name(renderer).engine.supported_extensions
if supported_exts:
project_files = [file for file in project_files if any(file.endswith(ext) for ext in supported_exts)]
if len(project_files) != 1: # we have to narrow down to 1 main project file, otherwise error
return {'error': f'Cannot find valid project file in {os.path.basename(zip_path)}'}, 400
extracted_project_path = os.path.join(work_path, project_files[0])
logger.info(f"Extracted zip file to {extracted_project_path}")
input_path = extracted_project_path
except (zipfile.BadZipFile, zipfile.LargeZipFile) as e:
err_msg = f"Error processing zip file: {e}"
logger.error(err_msg)
return {'error': err_msg, 'code': 400}
finally:
os.remove(zip_path)
logger.info(f"Removed zip: {zip_path}")
# local renders # local renders
if client == RenderQueue.hostname: if client == RenderQueue.hostname:
logger.info(f"Creating job locally - {name if name else input_path}") logger.info(f"Creating job locally - {name if name else input_path}")