PROCITY/pipeline/gen_props_fal.py
m3ultra 8644d3f7ac Lane E round 5 (E3): fal Hunyuan glass_case + bus_shelter + magazine_rack (~$0.64)
The 2 R3 TRELLIS glass rejects + optional magazine-rack, generated on fal.ai
Hunyuan3D v2 (John-authorized, $22 balance). pipeline/gen_props_fal.py drives the
fal operator using the FAL_KEY from MODELBEAST settings (never hardcoded). Frosted/
opaque flux_local concepts gave the reconstructor a surface (clear glass defeated
TRELLIS). glass-case 1 att, bus-shelter 2 att (opaque back wall), magazine-rack 1 att
= ~$0.64 total, guardrail held. All baked to <=8k via bake_lowpoly.py (switched to
EMIT albedo bake — Hunyuan materials bake near-black under DIFFUSE). Verified loading
in vendored GLTFLoader, published, validate --depot 0 err. Manifest 17 fittings + 9
furniture; aliases wire glass_case/glass_cabinets/magazine_rack/fridge/listening_corner.
Costs logged in AUDIT R5. Last 2 primitive-only fittings retired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 21:20:44 +10:00

49 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""fal.ai Hunyuan3D v2 image->GLB for the two TRELLIS glass rejects (glass-case, bus-shelter).
Paid — John-authorized (ROUND5 decision #4; account topped up). ~14-17c/gen, <=2 attempts each,
every gen logged to AUDIT.md by the caller. Uses the owner's FAL_KEY configured in MODELBEAST
settings (never hardcoded here) via MODELBEAST's own settings loader — the same env-injection the
server does. MUST run with MODELBEAST's server venv python (it has fal_client):
MBPY=~/Documents/MODELBEAST/.venv/bin/python
$MBPY pipeline/gen_props_fal.py CONCEPT.png OUT.glb
Prints `FAL_OK <glb> ~$0.16` on success (cost is the caller's to record), `FAL_ERR ...` on failure.
"""
import sys, os, subprocess, json, glob, shutil
MB = os.path.expanduser("~/Documents/MODELBEAST")
sys.path.insert(0, MB)
from server import db, settings as S # noqa: E402
ENDPOINT = "fal-ai/hunyuan3d/v2" # ~$0.16 geo (+ texture); see MESHGOD_BATCH.md pricing
COST = 0.16
def main():
concept, out = sys.argv[1], sys.argv[2]
con = db.connect()
env = os.environ.copy()
env.update(S.env_for_operator(S.get_all(con), ["FAL_KEY"]))
if not env.get("FAL_KEY"):
print("FAL_ERR FAL_KEY not configured in MODELBEAST settings"); sys.exit(2)
opdir = os.path.join(MB, "server/operators/fal_hunyuan3d")
outdir = os.path.join(os.path.dirname(out) or ".", "_fal_" + os.path.basename(out).replace(".glb", ""))
os.makedirs(outdir, exist_ok=True)
params = json.dumps({"seed": 0, "textured_mesh": True})
r = subprocess.run([sys.executable, os.path.join(opdir, "run.py"),
"--input", concept, "--outdir", outdir, "--params", params],
env=env, capture_output=True, text=True, timeout=600)
glbs = glob.glob(os.path.join(outdir, "**", "*.glb"), recursive=True)
if not glbs:
print("FAL_ERR " + (r.stderr or r.stdout or "no glb")[-300:]); sys.exit(1)
shutil.move(sorted(glbs)[0], out)
shutil.rmtree(outdir, ignore_errors=True)
print(f"FAL_OK {out} ~${COST:.2f} ({ENDPOINT})")
if __name__ == "__main__":
main()