refactor(A2): replace blender-renderer HTTP service with render-worker Celery container
- Create render-worker/ with Dockerfile (Ubuntu + cadquery + Blender via host mount) - Add render-worker/check_version.py: verifies Blender >= 5.0.1 at startup, Exit 1 on failure - Add render-worker/scripts/: blender_render.py, still_render.py, turntable_render.py - Create backend/app/services/render_blender.py: direct subprocess rendering - convert_step_to_stl() and export_per_part_stls() using cadquery - render_still(): STEP → STL → PNG via Blender subprocess - is_blender_available(): detects BLENDER_BIN env for render-worker context - Create backend/app/domains/rendering/tasks.py: render_still_task + render_turntable_task - Update step_processor.py: use subprocess path when BLENDER_BIN env is set (render-worker) - Update step_tasks.py: generate_stl_cache uses direct cadquery instead of HTTP - Remove blender-renderer and threejs-renderer from docker-compose.yml - Replace worker-thumbnail with render-worker (Ubuntu + cadquery + Blender mount) - Remove Docker SDK from backend Dockerfile (was only for flamenco scaling) - Update .env.example: BLENDER_VERSION=5.0.1 documented - Update celery_app.py: include domains.rendering.tasks in autodiscover Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -329,8 +329,9 @@ def _generate_thumbnail(
|
||||
"height": 512,
|
||||
})
|
||||
elif renderer == "threejs":
|
||||
size = int(settings["threejs_render_size"])
|
||||
render_log.update({"width": size, "height": size})
|
||||
# Three.js renderer removed in v2; treat as pillow fallback
|
||||
renderer = "pillow"
|
||||
render_log.update({"renderer": "pillow", "threejs_removed": True})
|
||||
|
||||
logger.info(f"Thumbnail renderer={renderer}, format={fmt}")
|
||||
|
||||
@@ -340,29 +341,25 @@ def _generate_thumbnail(
|
||||
if renderer == "blender":
|
||||
engine = settings["blender_engine"]
|
||||
samples = int(settings[f"blender_{engine}_samples"])
|
||||
extra = {
|
||||
"engine": engine,
|
||||
"samples": samples,
|
||||
"stl_quality": settings["stl_quality"],
|
||||
"smooth_angle": int(settings["blender_smooth_angle"]),
|
||||
"cycles_device": settings["cycles_device"],
|
||||
}
|
||||
rendered_png, service_data = _render_via_service(
|
||||
"http://blender-renderer:8100/render", step_path, tmp_png, extra
|
||||
)
|
||||
if not rendered_png:
|
||||
logger.warning("Blender renderer failed; falling back to Pillow placeholder")
|
||||
|
||||
elif renderer == "threejs":
|
||||
size = int(settings["threejs_render_size"])
|
||||
extra2: dict = {"width": size, "height": size}
|
||||
if part_colors is not None:
|
||||
extra2["part_colors"] = part_colors
|
||||
rendered_png, service_data = _render_via_service(
|
||||
"http://threejs-renderer:8101/render", step_path, tmp_png, extra2
|
||||
)
|
||||
if not rendered_png:
|
||||
logger.warning("Three.js renderer failed; falling back to Pillow placeholder")
|
||||
from app.services.render_blender import is_blender_available, render_still
|
||||
if is_blender_available():
|
||||
try:
|
||||
service_data = render_still(
|
||||
step_path=step_path,
|
||||
output_path=tmp_png,
|
||||
engine=engine,
|
||||
samples=samples,
|
||||
stl_quality=settings["stl_quality"],
|
||||
smooth_angle=int(settings["blender_smooth_angle"]),
|
||||
cycles_device=settings["cycles_device"],
|
||||
)
|
||||
rendered_png = tmp_png if tmp_png.exists() else None
|
||||
except Exception as exc:
|
||||
logger.warning("Blender subprocess render failed: %s", exc)
|
||||
rendered_png = None
|
||||
else:
|
||||
logger.warning("Blender not available in this container — falling back to Pillow placeholder")
|
||||
|
||||
# Merge rich service response data into render_log
|
||||
if service_data:
|
||||
@@ -669,20 +666,43 @@ def render_to_file(
|
||||
extra["denoising_quality"] = denoising_quality
|
||||
if denoising_use_gpu:
|
||||
extra["denoising_use_gpu"] = denoising_use_gpu
|
||||
rendered_png, service_data = _render_via_service(
|
||||
"http://blender-renderer:8100/render", step, tmp_png, extra, job_id=job_id
|
||||
)
|
||||
from app.services.render_blender import is_blender_available, render_still
|
||||
if is_blender_available():
|
||||
try:
|
||||
service_data = render_still(
|
||||
step_path=step,
|
||||
output_path=tmp_png,
|
||||
engine=actual_engine,
|
||||
samples=actual_samples,
|
||||
stl_quality=settings["stl_quality"],
|
||||
smooth_angle=int(settings["blender_smooth_angle"]),
|
||||
cycles_device=actual_cycles_device,
|
||||
width=w, height=h,
|
||||
transparent_bg=transparent_bg,
|
||||
part_colors=part_colors,
|
||||
template_path=template_path,
|
||||
target_collection=target_collection,
|
||||
material_library_path=material_library_path,
|
||||
material_map=material_map,
|
||||
part_names_ordered=part_names_ordered,
|
||||
lighting_only=lighting_only,
|
||||
shadow_catcher=shadow_catcher,
|
||||
rotation_x=rotation_x, rotation_y=rotation_y, rotation_z=rotation_z,
|
||||
noise_threshold=noise_threshold, denoiser=denoiser,
|
||||
denoising_input_passes=denoising_input_passes,
|
||||
denoising_prefilter=denoising_prefilter,
|
||||
denoising_quality=denoising_quality,
|
||||
denoising_use_gpu=denoising_use_gpu,
|
||||
)
|
||||
rendered_png = tmp_png if tmp_png.exists() else None
|
||||
except Exception as exc:
|
||||
logger.warning("Blender subprocess render failed: %s", exc)
|
||||
rendered_png = None
|
||||
else:
|
||||
logger.warning("Blender not available in this container — using Pillow fallback")
|
||||
elif renderer == "threejs":
|
||||
default_size = int(settings["threejs_render_size"])
|
||||
w = width or default_size
|
||||
h = height or default_size
|
||||
render_log.update({"width": w, "height": h})
|
||||
extra2: dict = {"width": w, "height": h}
|
||||
if part_colors is not None:
|
||||
extra2["part_colors"] = part_colors
|
||||
rendered_png, service_data = _render_via_service(
|
||||
"http://threejs-renderer:8101/render", step, tmp_png, extra2
|
||||
)
|
||||
# Three.js renderer removed in v2 — fall through to Pillow placeholder
|
||||
logger.warning("Three.js renderer removed; using Pillow fallback")
|
||||
|
||||
if service_data:
|
||||
for key in ("total_duration_s", "stl_duration_s", "render_duration_s",
|
||||
|
||||
Reference in New Issue
Block a user