Sovereign Render Worker
Fixed Python script — run this on your local machine or Google Colab to process render jobs.
No jobs in the queue right now — nothing to stage.
Blender Worker — Golden Schema
Save this as /SOVEREIGN_SYSTEM/blender_worker.py. It claims jobs, runs the integrity check against your ASSETS folders, renders headless, and reports back.
/SOVEREIGN_SYSTEM/ ├── ASSETS/ WORLDS/ AVATARS/ CARS/ WIDGETS/ ├── QUEUE/ PENDING/ PROCESSING/ CONFLICT/ └── OUTPUT/ RAW/ FINAL/ GIFS/
ENV RENDER_WORKER_SECRET — same value as the app secret
ENV SOVEREIGN_ROOT — defaults to /SOVEREIGN_SYSTEM
ENV BLENDER_BIN — path to your Blender executable
ENV PUBLIC_MEDIA_BASE — public URL serving OUTPUT/FINAL (required to auto-publish)
# ==============================================================================
# SOVEREIGN BLENDER WORKER — /SOVEREIGN_SYSTEM/blender_worker.py
# Claims jobs from the app, validates every asset (circuit breaker),
# renders in Blender headless, stitches with FFmpeg, reports back.
# Run: python blender_worker.py
# ==============================================================================
import os, sys, json, time, uuid, glob, subprocess, requests
BRIDGE_URL = "https://lip-sync-magical-studioscom-afa6bbe1.base44.app/functions/blenderWorkerBridge"
SYSTEM_TOKEN = os.environ.get("RENDER_WORKER_SECRET", "PUT_YOUR_SECRET_HERE")
BLENDER_BIN = os.environ.get("BLENDER_BIN", "blender")
# Public base URL that serves /OUTPUT/FINAL/ (your CDN, S3 bucket, or web host).
PUBLIC_MEDIA_BASE = os.environ.get("PUBLIC_MEDIA_BASE", "").rstrip("/")
ROOT = os.environ.get("SOVEREIGN_ROOT", "/SOVEREIGN_SYSTEM")
ASSETS = os.path.join(ROOT, "ASSETS")
WORLDS = os.path.join(ASSETS, "WORLDS")
AVATARS = os.path.join(ASSETS, "AVATARS")
CARS = os.path.join(ASSETS, "CARS")
WIDGETS = os.path.join(ASSETS, "WIDGETS")
Q_PEND = os.path.join(ROOT, "QUEUE", "PENDING")
Q_PROC = os.path.join(ROOT, "QUEUE", "PROCESSING")
Q_CONF = os.path.join(ROOT, "QUEUE", "CONFLICT")
OUT_RAW = os.path.join(ROOT, "OUTPUT", "RAW")
OUT_FIN = os.path.join(ROOT, "OUTPUT", "FINAL")
for d in (WORLDS, AVATARS, CARS, WIDGETS, Q_PEND, Q_PROC, Q_CONF, OUT_RAW, OUT_FIN):
os.makedirs(d, exist_ok=True)
def bridge(payload):
payload["systemToken"] = SYSTEM_TOKEN
r = requests.post(BRIDGE_URL, json=payload, timeout=30)
if r.status_code != 200:
print(" bridge error", r.status_code, r.text[:200])
return {}
return r.json()
def find_asset(folder, name, exts):
"""Golden naming: exact stem match, any approved extension."""
if not name:
return None
for ext in exts:
p = os.path.join(folder, f"{name}{ext}")
if os.path.exists(p):
return p
return None
# ── CIRCUIT BREAKER: no asset, no GPU cycles ──────────────────────────────────
def validate(job):
m = job.get("manifest", {}) or {}
missing, resolved = [], {}
world = (m.get("world") or {}).get("id") or m.get("world_file")
wp = find_asset(WORLDS, f"world_{world}" if world and not str(world).startswith("world_") else world, [".blend"])
if wp: resolved["world_file"] = wp
else: missing.append(f"WORLDS/{world}.blend")
avatar = job.get("avatar_rig_id") or m.get("avatar_asset")
ap = find_asset(AVATARS, avatar, [".vrm", ".fbx", ".blend", ".png"])
if ap: resolved["avatar_asset"] = ap
else: missing.append(f"AVATARS/{avatar}")
car = (m.get("car") or {}).get("id") if isinstance(m.get("car"), dict) else m.get("car_asset")
if car:
cp = find_asset(CARS, car, [".blend", ".fbx"])
if cp: resolved["car_asset"] = cp
else: missing.append(f"CARS/{car}")
audio = job.get("audio_binary_path")
if audio:
ap2 = audio if os.path.exists(audio) else find_asset(ASSETS, audio, [".mp3", ".wav"])
if ap2: resolved["audio_source"] = ap2
else: missing.append(f"AUDIO/{audio}")
render = m.get("render", {}) or {}
resolved["resolution"] = render.get("resolution") or m.get("resolution") or "1920x1080"
resolved["fps"] = int(render.get("fps") or m.get("fps") or 30)
resolved["codec"] = render.get("codec") or m.get("codec") or "h264"
return resolved, missing
def render_job(job, resolved):
rid = job["render_id"]
frames_dir = os.path.join(OUT_RAW, rid)
os.makedirs(frames_dir, exist_ok=True)
w, h = resolved["resolution"].split("x")
cmd = [BLENDER_BIN, "-b", resolved["world_file"], "-o",
os.path.join(frames_dir, "frame_####"), "-F", "PNG",
"-x", "1", "-a"]
print(" blender:", " ".join(cmd))
subprocess.run(cmd, check=True)
final = os.path.join(OUT_FIN, f"{rid}.mp4")
ff = ["ffmpeg", "-y", "-framerate", str(resolved["fps"]),
"-i", os.path.join(frames_dir, "frame_%04d.png")]
if resolved.get("audio_source"):
ff += ["-i", resolved["audio_source"], "-shortest"]
ff += ["-c:v", "libx264", "-pix_fmt", "yuv420p",
"-vf", f"scale={w}:{h}", final]
subprocess.run(ff, check=True)
return final
def duration_of(path):
try:
out = subprocess.run(["ffprobe", "-v", "error", "-show_entries",
"format=duration", "-of", "csv=p=0", path],
capture_output=True, text=True).stdout.strip()
return int(float(out))
except Exception:
return 0
def process(job):
rid = job["render_id"]
lock = os.path.join(Q_PROC, f"{rid}.json")
with open(lock, "w") as f:
json.dump(job, f, indent=2)
resolved, missing = validate(job)
if missing:
reason = "Missing assets: " + ", ".join(missing)
print(" CONFLICT —", reason)
os.replace(lock, os.path.join(Q_CONF, f"{rid}.json"))
bridge({"action": "conflict", "render_id": rid, "reason": reason})
return
try:
final = render_job(job, resolved)
except subprocess.CalledProcessError as e:
os.replace(lock, os.path.join(Q_CONF, f"{rid}.json"))
bridge({"action": "conflict", "render_id": rid, "reason": f"Render failed: {e}"})
return
if not PUBLIC_MEDIA_BASE:
print(" RENDERED:", final, "— set PUBLIC_MEDIA_BASE to auto-publish.")
os.replace(lock, os.path.join(Q_CONF, f"{rid}.json"))
bridge({"action": "conflict", "render_id": rid,
"reason": f"Rendered locally at {final} but PUBLIC_MEDIA_BASE is not set"})
return
url = f"{PUBLIC_MEDIA_BASE}/{os.path.basename(final)}"
res = bridge({"action": "complete", "render_id": rid, "video_url": url,
"duration_seconds": duration_of(final)})
print(" PUBLISHED:", url, res)
if os.path.exists(lock):
os.remove(lock)
if __name__ == "__main__":
print("=" * 70)
print("SOVEREIGN BLENDER WORKER — root:", ROOT)
print("=" * 70)
while True:
data = bridge({"action": "claim", "limit": 3})
jobs = data.get("jobs", [])
if not jobs:
print("No jobs waiting. Sleeping 30s...")
time.sleep(30)
continue
for job in jobs:
print("JOB", job.get("render_id"))
with open(os.path.join(Q_PEND, f"{job['render_id']}.json"), "w") as f:
json.dump(job, f, indent=2)
process(job)
Bugs Fixed From Original
How To Use
1. Download the script below
2. Put your avatar PNGs in avatars/ folder (named by avatar ID)
3. Install: pip install pillow requests + FFmpeg on your system
4. Run: python sovereign_worker.py
5. Launch jobs from the MP4 Render Lab page — worker picks them up automatically
6. MP4s appear in output_cinema/ — upload them and paste URLs into the pipeline
# ==============================================================================
# SOVEREIGN RENDER WORKER — FIXED & PRODUCTION READY
# Polls the Base44 queue, renders frames with PIL, stitches with FFmpeg
# Run: python sovereign_worker.py
# ==============================================================================
BASE44_QUEUE_URL = "https://lip-sync-magical-studioscom-afa6bbe1.base44.app/functions/sovereignRenderQueue"
SOVEREIGN_SHARED_SECRET = "Dollars#1000"
WORKER_ID = "colab-worker-01"
import os, sys, time, json, requests, subprocess
from math import ceil
from PIL import Image, ImageDraw, ImageFont
print("=" * 70)
print(f"SOVEREIGN WORKER STARTING: {WORKER_ID}")
print("=" * 70)
# Install deps if needed
try:
import torch
except ImportError:
subprocess.run(["pip", "install", "torch", "torchvision", "pillow", "requests"], check=True)
os.makedirs("temp_render", exist_ok=True)
os.makedirs("output_cinema", exist_ok=True)
os.makedirs("motion_templates", exist_ok=True)
RESOLUTION = (2560, 1080)
FPS = 30
def init_motion_templates():
idle_path = "motion_templates/idle.json"
if not os.path.exists(idle_path):
with open(idle_path, "w") as f:
json.dump({"frames": [{"y_offset": 0}, {"y_offset": 2}, {"y_offset": 4}, {"y_offset": 2}]}, f)
walk_path = "motion_templates/walk.json"
if not os.path.exists(walk_path):
with open(walk_path, "w") as f:
json.dump({"frames": [{"x_offset": 0}, {"x_offset": 4}, {"x_offset": 8}, {"x_offset": 4}]}, f)
print("Motion templates ready.")
def fetch_render_job():
"""Poll the queue for the next available job."""
print(f"Polling queue...")
payload = {
"worker_id": WORKER_ID,
"secret": SOVEREIGN_SHARED_SECRET,
"timestamp": int(time.time())
}
try:
response = requests.post(BASE44_QUEUE_URL, json=payload, timeout=15)
if response.status_code == 200: # FIXED: was response.status_with (typo)
data = response.json()
if data.get("job"):
print(f"Got job: {data['job'].get('task_id')}")
return data["job"]
else:
print("No jobs in queue.")
return None
else:
print(f"Queue returned {response.status_code}")
return None
except Exception as e:
print(f"Queue offline: {e}")
return None
def render_frames(job):
"""Render PNG frames for the job."""
dialogue = job.get("dialogue", "No dialogue")
avatar_id = job.get("avatar_skeleton_id", "default")
total_frames = 90 # 3 seconds @ 30fps
print(f"Rendering {total_frames} frames for: {dialogue[:60]}...")
# Load avatar PNG if available
avatar_img = None
avatar_path = f"avatars/{avatar_id}.png"
if os.path.exists(avatar_path):
avatar_img = Image.open(avatar_path).convert("RGBA")
avatar_img = avatar_img.resize((400, 600))
# Viseme mouth shapes mapped to dialogue characters (simple phoneme map)
MOUTH_SIZES = [10, 30, 20, 40, 15, 35, 25, 10, 20, 30]
for frame_idx in range(total_frames):
progress = frame_idx / total_frames
bounce = int(8 * abs((frame_idx % 20) / 10.0 - 1.0)) # breathing bob
frame = Image.new("RGB", RESOLUTION, color="#0a0a0f")
draw = ImageDraw.Draw(frame)
# Grid background
for x in range(0, RESOLUTION[0], 80):
draw.line([(x, 0), (x, RESOLUTION[1])], fill="#1a1a2e", width=1)
for y in range(0, RESOLUTION[1], 80):
draw.line([(0, y), (RESOLUTION[0], y)], fill="#1a1a2e", width=1)
# Newsroom glow bar at top
draw.rectangle([0, 0, RESOLUTION[0], 6], fill="#22d3ee")
# Anchor position — center
anchor_x = RESOLUTION[0] // 2
anchor_y = RESOLUTION[1] // 2 - 100 + bounce
if avatar_img:
# Paste the actual avatar PNG
paste_x = anchor_x - 200
paste_y = anchor_y - 300
frame.paste(avatar_img, (paste_x, paste_y), avatar_img)
else:
# Fallback: draw cartoon head
head_x, head_y = anchor_x - 80, anchor_y - 150
draw.ellipse([head_x, head_y, head_x+160, head_y+200], fill="#d4956a", outline="#22d3ee", width=3)
# Eyes
draw.ellipse([head_x+35, head_y+60, head_x+65, head_y+90], fill="#1a0a00")
draw.ellipse([head_x+95, head_y+60, head_x+125, head_y+90], fill="#1a0a00")
# Eye whites
draw.ellipse([head_x+45, head_y+65, head_x+58, head_y+78], fill="white")
draw.ellipse([head_x+105, head_y+65, head_x+118, head_y+78], fill="white")
# Mouth — lip sync via viseme cycling
mouth_open = MOUTH_SIZES[frame_idx % len(MOUTH_SIZES)]
mouth_y = head_y + 140
draw.ellipse([head_x+50, mouth_y, head_x+110, mouth_y+mouth_open], fill="#8B3A3A")
if mouth_open > 15:
draw.ellipse([head_x+55, mouth_y+2, head_x+105, mouth_y+mouth_open-4], fill="#2a0808")
# Teeth
draw.ellipse([head_x+58, mouth_y+2, head_x+102, mouth_y+8], fill="white")
# Lower third
draw.rectangle([0, RESOLUTION[1]-120, RESOLUTION[0], RESOLUTION[1]], fill="#000000cc")
draw.rectangle([0, RESOLUTION[1]-120, 8, RESOLUTION[1]], fill="#22d3ee")
draw.rectangle([0, RESOLUTION[1]-6, RESOLUTION[0], RESOLUTION[1]], fill="#dc2626")
# Dialogue text (wrap at 80 chars)
words = dialogue.split()
show_words = int(len(words) * min(progress * 1.5, 1.0))
visible = " ".join(words[:max(show_words, 3)])
try:
draw.text((30, RESOLUTION[1]-100), visible[:120], fill="white")
except:
pass
# Frame counter
draw.text((30, 20), f"FRAME {frame_idx:04d} | SOVEREIGN RENDER | {WORKER_ID}", fill="#22d3ee")
# Progress bar
bar_w = int(RESOLUTION[0] * progress)
draw.rectangle([0, RESOLUTION[1]-128, bar_w, RESOLUTION[1]-122], fill="#22d3ee")
frame.save(f"temp_render/frame_{frame_idx:04d}.png", "PNG")
print(f"All {total_frames} frames saved to temp_render/")
def compile_video(job):
"""Stitch frames into MP4 with FFmpeg."""
task_id = job.get("task_id", f"render_{int(time.time())}")
output_path = f"output_cinema/{task_id}.mp4"
ffmpeg_cmd = [
"ffmpeg", "-y",
"-framerate", str(FPS),
"-i", "temp_render/frame_%04d.png",
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-vf", f"scale={RESOLUTION[0]}:{RESOLUTION[1]}",
output_path
]
try:
subprocess.run(ffmpeg_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f"MP4 ready: {output_path}")
return output_path
except FileNotFoundError:
print("FFmpeg not found. Frames saved — install FFmpeg to stitch.")
return None
except subprocess.CalledProcessError as e:
print(f"FFmpeg error: {e}")
return None
def report_result(job_id, output_path, error=None):
"""Tell Base44 the job is done (or failed)."""
payload = {
"secret": SOVEREIGN_SHARED_SECRET,
"job_id": job_id,
}
if output_path:
# For now report local path — later upload to storage and send URL
payload["output_url"] = f"file://{os.path.abspath(output_path)}"
payload["error"] = None
else:
payload["error"] = error or "Render failed"
try:
requests.post(BASE44_QUEUE_URL, json=payload, timeout=10)
print("Result reported to queue.")
except Exception as e:
print(f"Could not report result: {e}")
# ==============================================================================
# MAIN LOOP
# ==============================================================================
if __name__ == "__main__":
init_motion_templates()
while True:
job = fetch_render_job()
if job:
job_id = job.get("id")
try:
render_frames(job)
output_path = compile_video(job)
report_result(job_id, output_path)
except Exception as e:
print(f"Render error: {e}")
report_result(job_id, None, error=str(e))
else:
print("Waiting 10s for next job...")
time.sleep(10)