# -*- coding: utf-8 -*- """lucy_ready.py — Startklar-Check + finale Samples in EINEM Lauf. Bootet den ECHTEN Server (FastAPI-TestClient triggert lifespan: Modell-Load, A1-Cache, STATE), prüft /health, und rendert die finalen Hörproben über die REALEN Endpoints /tts und /tts/stream (exakt das, was die Lucy-App auf :8130 aufruft) — inkl. Live-TTFB der Streaming-Antwort. Legt die Samples auf den Desktop, schreibt lucy_ready_report.json. """ import os, time, json import numpy as np, soundfile as sf from fastapi.testclient import TestClient import pocket_server as ps DESK = os.path.join(os.path.expanduser("~"), "Desktop", "lucy_samples") os.makedirs(DESK, exist_ok=True) SENT = { "kurz": "Hallo Commander, ich höre dich.", "mittel": "Guten Morgen, Commander. Das Backup ist sauber durchgelaufen und es gab keine Fehler.", "lang": "Natürlich kümmere ich mich darum, Commander. Ich starte den Dienst neu, prüfe die " "Protokolle und melde mich, sobald alles wieder läuft.", } LONG = ("Guten Morgen, Commander. " "Das nächtliche Backup ist sauber durchgelaufen und es gab keine Fehler. " "Der Dienst läuft stabil und die Engine antwortet zügig. " "Wenn du möchtest, fasse ich die offenen Punkte für heute zusammen.") report = {} t0 = time.time() with TestClient(ps.app) as c: # <-- triggert lifespan (echter Boot) report["boot_s"] = round(time.time() - t0, 1) h = c.get("/health").json() report["health"] = h print(f"BOOT in {report['boot_s']}s health={h}") for name, text in SENT.items(): # /tts (ganze Datei) -> Desktop t = time.time(); r = c.post("/tts", json={"text": text}); dt = time.time() - t assert r.status_code == 200, f"/tts {name} -> {r.status_code}" open(os.path.join(DESK, f"lucy_final_{name}.wav"), "wb").write(r.content) print(f"/tts {name:6}: {dt:4.2f}s audio={r.headers.get('X-Audio-Seconds')}s") # /tts/stream: lange Antwort wie Lucy LIVE spricht -> TTFB messen + PCM zu WAV sr = int(h.get("sr") or 24000) t = time.time(); first = None; chunks = [] with c.stream("POST", "/tts/stream", json={"text": LONG}) as s: sr = int(s.headers.get("X-Sample-Rate", sr)) for ch in s.iter_bytes(): if ch: if first is None: first = time.time() - t chunks.append(ch) a = np.frombuffer(b"".join(chunks), dtype="