v2.3 — Character-Aussehen + Portrait-Fix
Features: - Character-Bogen: Aussehen-Sektion mit Stil, Geschlecht, Alter, Größe, Statur, Haarfarbe, Frisur, Augenfarbe, Haut, Kleidung, Merkmale - Stil-Optionen: Anime, Realistisch, Comic, Cartoon, Pixel Art - ComfyUI Prompt wird aus appearance-Objekt gebaut - Portrait-Button: Async mit Polling (kein Timeout mehr) - Portrait-Button: 5-Minuten Timeout als Fallback - Poll-Errors werden ignoriert (kein vorzeitiger Abbruch) - Mara.json aktualisiert mit appearance-Objekt
This commit is contained in:
@@ -454,6 +454,7 @@ async def api_create_character(request: Request):
|
||||
"greeting": body.get("greeting", ""),
|
||||
"model": body.get("model", ""),
|
||||
"temperature": body.get("temperature", 0.8),
|
||||
"appearance": body.get("appearance", {}),
|
||||
}
|
||||
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
@@ -499,9 +500,12 @@ async def api_list_models():
|
||||
async def api_comfyui_status():
|
||||
return JSONResponse({"running": is_comfyui_running()})
|
||||
|
||||
# In-memory tracking for portrait generation
|
||||
_portrait_jobs = {}
|
||||
|
||||
@app.post("/api/character/{name}/portrait")
|
||||
async def api_generate_portrait(name: str, request: Request):
|
||||
"""Generiert ein Profilbild via ComfyUI."""
|
||||
"""Startet Portrait-Generierung — gibt sofort eine Job-ID zurück."""
|
||||
char = load_character(name)
|
||||
|
||||
if not is_comfyui_running():
|
||||
@@ -510,14 +514,27 @@ async def api_generate_portrait(name: str, request: Request):
|
||||
body = await request.json() if request.headers.get("content-type") == "application/json" else {}
|
||||
custom_prompt = body.get("prompt", "")
|
||||
|
||||
# Build description from character data
|
||||
desc = custom_prompt or f"{char.get('personality', '')}, {char.get('background', '')}"
|
||||
import uuid
|
||||
job_id = str(uuid.uuid4())[:8]
|
||||
_portrait_jobs[job_id] = {"status": "generating", "image": None, "error": None}
|
||||
|
||||
image_path = generate_portrait(name, desc)
|
||||
if image_path:
|
||||
return JSONResponse({"status": "ok", "image": image_path})
|
||||
else:
|
||||
return JSONResponse({"error": "Bildgenerierung fehlgeschlagen"}, status_code=500)
|
||||
async def run_generation():
|
||||
image_path = generate_portrait(name, char, custom_prompt)
|
||||
if image_path:
|
||||
_portrait_jobs[job_id] = {"status": "done", "image": image_path, "error": None}
|
||||
else:
|
||||
_portrait_jobs[job_id] = {"status": "error", "image": None, "error": "Generierung fehlgeschlagen"}
|
||||
|
||||
asyncio.create_task(run_generation())
|
||||
|
||||
return JSONResponse({"status": "started", "job_id": job_id})
|
||||
|
||||
@app.get("/api/portrait/status/{job_id}")
|
||||
async def api_portrait_status(job_id: str):
|
||||
"""Fragt den Status einer Portrait-Generierung ab."""
|
||||
if job_id not in _portrait_jobs:
|
||||
return JSONResponse({"status": "not_found"}, status_code=404)
|
||||
return JSONResponse(_portrait_jobs[job_id])
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
Reference in New Issue
Block a user