blender-render-studio / scripts /smoke_test.py
cpuai's picture
Default to CPU Eevee; retain optional GPU/Cycles and fix inherited task locks
5d6dcc3 verified
Raw History Blame Contribute Delete
4.2 kB
#!/usr/bin/env python3
"""真实集成烟测:本机启动 Gradio,上传工程/JSON,渲染PNG并验证下载。
运行:BLENDER_BIN=/path/to/blender python scripts/smoke_test.py
默认明确使用 CPU;不声称测试了 ZeroGPU。需要先安装 requirements。
"""
from __future__ import annotations
import json
import os
from pathlib import Path
import sys
import tempfile
import zipfile
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
os.environ['RENDER_BACKEND'] = 'cpu'
os.environ.setdefault('GRADIO_ANALYTICS_ENABLED', 'False')
os.environ['NO_PROXY'] = ','.join(filter(None, [os.environ.get('NO_PROXY', ''), '127.0.0.1', 'localhost']))
def main():
from gradio_client import Client, handle_file
from PIL import Image
with tempfile.TemporaryDirectory(prefix='blender-space-smoke-') as tmp:
temp = Path(tmp)
os.environ['RENDER_DATA_DIR'] = str(temp / 'jobs-data')
import app
import service
from blender_runtime import ensure_blender
binary = ensure_blender()
demo_file = ROOT / 'examples/demo.blend'
if not demo_file.is_file():
raise RuntimeError('缺少 examples/demo.blend,请先运行 scripts/create_demo.py。')
project = temp / 'project.zip'
with zipfile.ZipFile(project, 'w') as archive:
archive.write(demo_file, 'scene/demo.blend')
config = temp / 'render.json'
config.write_text(json.dumps({'blend_file':'scene/demo.blend','mode':'image',
'width':640,'height':360,'samples':16,'batch_size':1}), encoding='utf-8')
demo = app.build_app().queue()
_, url, _ = demo.launch(server_name='127.0.0.1', server_port=7867,
prevent_thread_lock=True, quiet=True, mcp_server=True,
allowed_paths=[str(service.PUBLIC_ROOT)],
theme=app.gr.themes.Soft(), css=app.CSS)
try:
client = Client(url, verbose=False, download_files=str(temp / 'downloads'),
httpx_kwargs={'trust_env':False})
environment = client.predict(api_name='/environment_info')
probe, _, _ = client.predict(api_name='/cpu_self_test')
assert probe['ok'] and probe['backend'] == 'CPU' and not probe['gpu_verified']
job_id, prepared = client.predict([handle_file(str(project))], '{}', handle_file(str(config)),
api_name='/prepare_job')
checked = client.predict(job_id, api_name='/inspect_job')
assert checked['status'] == 'ready', checked
status = client.predict(job_id, api_name='/render_chunk')
assert status['status'] == 'complete' and not status['error'], status
summary, files, image, video = client.predict(job_id, api_name='/finalize_job')
assert summary['export_complete'] and image and not video, summary
with Image.open(image) as rendered:
assert rendered.size == (640,360)
rendered.verify()
archive_file = next(Path(f) for f in files if str(f).endswith('.zip'))
with zipfile.ZipFile(archive_file) as result_zip:
assert 'frames/frame_000001.png' in result_zip.namelist()
assert result_zip.testzip() is None
artifacts = ROOT / 'test-artifacts'
artifacts.mkdir(exist_ok=True)
import shutil
shutil.copy2(image, artifacts / 'cpu-render-preview.png')
report = {'ok':True,'backend':'CPU','blender':probe['blender_version'],
'api_upload_zip':True,'api_upload_config':True,'api_render_png':True,
'image_dimensions':[640,360],'api_download_zip_verified':True,
'zero_gpu_tested':False,'environment':environment}
(artifacts / 'api-smoke-report.json').write_text(json.dumps(report,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(report,ensure_ascii=False,indent=2))
finally:
demo.close()
if __name__ == '__main__':
main()