[laneC] /rhubarb viseme endpoint (ffmpeg-style 503 gating)
GET /rhubarb?path= -> rhubarb -f json -> mouthCues for Lane A's viseme lane; 503 when the binary is absent (not installed on ultra yet). Path-guarded. test_server.py: +503 gating assert (9 groups green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
a15612eed0
commit
fb59601cc3
@ -45,6 +45,7 @@ MEDIA_TYPES = {
|
||||
SCENES.mkdir(parents=True, exist_ok=True)
|
||||
RENDERS.mkdir(parents=True, exist_ok=True)
|
||||
HAVE_FFMPEG = shutil.which("ffmpeg") is not None
|
||||
HAVE_RHUBARB = shutil.which("rhubarb") is not None
|
||||
|
||||
# MODELBEAST proxy (M4) — off unless SCENEGOD_MB=1. Token read from disk at
|
||||
# request time, never logged. Contract mirrors MESHGOD meshgod/ops.py.
|
||||
@ -347,6 +348,23 @@ def render_out(rid: str):
|
||||
return FileResponse(out, media_type="video/mp4")
|
||||
|
||||
|
||||
# ---- viseme lip-sync (M4) — feeds Lane A's viseme lane ----
|
||||
@app.get("/rhubarb")
|
||||
def rhubarb(path: str):
|
||||
"""Rhubarb Lip Sync on an asset audio file -> {metadata, mouthCues:[...]}.
|
||||
503 if rhubarb absent (same pattern as ffmpeg). ponytail: synchronous —
|
||||
VO clips are short; make it a render-style session if that ever bites."""
|
||||
if not HAVE_RHUBARB:
|
||||
raise HTTPException(503, "rhubarb not installed (see github.com/DanielSWolf/rhubarb-lip-sync)")
|
||||
f = safe_under(ASSETS, path)
|
||||
if not f.is_file():
|
||||
raise HTTPException(404, "not found")
|
||||
p = subprocess.run(["rhubarb", "-f", "json", str(f)], capture_output=True, text=True)
|
||||
if p.returncode != 0:
|
||||
raise HTTPException(500, f"rhubarb failed: {p.stderr[-500:]}")
|
||||
return json.loads(p.stdout)
|
||||
|
||||
|
||||
# ---- MODELBEAST proxy (M4, gated) ----
|
||||
def _mb_post(path: str, data: bytes, content_type: str) -> dict:
|
||||
req = urllib.request.Request(MB_HOST + path, data=data, method="POST",
|
||||
|
||||
@ -176,6 +176,11 @@ def main():
|
||||
else:
|
||||
print("(render test skipped — ffmpeg/ffprobe not found)")
|
||||
|
||||
# --- rhubarb: 503 when the binary is absent (happy path needs rhubarb) ---
|
||||
if not shutil.which("rhubarb"):
|
||||
assert req("GET", "/rhubarb?path=audio/x.wav")[0] == 503
|
||||
n += 1
|
||||
|
||||
# --- MODELBEAST proxy: gating + two-step contract (mock MB, no farm jobs) ---
|
||||
assert req("POST", "/mb/submit", json.dumps({"operator": "tts"}))[0] == 503 # gated off
|
||||
n += 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user