# -*- coding: utf-8 -*- """make_samples.py — erzeugt Lucy-Hörproben auf dem Desktop, um A1 (safetensors-Cache) und A2 (Referenz-Cleaning) hörbar zu testen. Nutzt 1:1 die Produktionslogik aus pocket_server.py (cleanup + Doppel-Wächter _gen_gated), läuft offline mit dem lokal gecachten german_24l-Modell. Output: %USERPROFILE%\\Desktop\\lucy_samples\\ lucy_clean_{kurz,mittel,lang}.wav (A2 AN: Highpass+Peak-Norm, Stimme aus safetensors-Cache) lucy_raw_{kurz,mittel,lang}.wav (A2 AUS: Roh-Referenz, direkt geklont) So hörst du den Cleaning-Unterschied direkt im A/B. """ import os, time import numpy as np, soundfile as sf, librosa from pocket_tts import TTSModel import pocket_server as ps # reuse: _prep_ref, cleanup, _gen_gated, _fingerprint, Konstanten 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.", } def build(ref_clean: bool, tag: str, use_cache: bool): ps.REF_CLEAN = ref_clean # A2-Schalter zur Laufzeit setzen ref = ps._prep_ref() # schreibt ref.wav (ggf. gecleant) print(f"\n[{tag}] lade Modell {ps.LANG} (lsd={ps.LSD} temp={ps.TEMP} nc={ps.NOISE_CLAMP}) ...") t0 = time.time() m = TTSModel.load_model(language=ps.LANG, lsd_decode_steps=ps.LSD, temp=ps.TEMP, noise_clamp=ps.NOISE_CLAMP, quantize=ps.QUANTIZE) sr = m.sample_rate print(f"[{tag}] Modell in {time.time()-t0:.1f}s (sr={sr})") if use_cache: # A1: einmal exportieren, dann aus Cache laden vs = m.get_state_for_audio_prompt(ref) try: ps.export_model_state(vs, ps.VOICE_ST) vs = m.get_state_for_audio_prompt(ps.VOICE_ST) print(f"[{tag}] Voice-State exportiert+geladen <- {os.path.basename(ps.VOICE_ST)}") except Exception as e: print(f"[{tag}] Export/Cache fehlgeschlagen, nutze Live-Klon: {e}") else: vs = m.get_state_for_audio_prompt(ref) ref_audio, _ = librosa.load(ref, sr=sr, mono=True) ps.STATE.update(m=m, vs=vs, sr=sr, ref_fp=ps._fingerprint(ref_audio, sr)) for name, text in SENT.items(): t0 = time.time() a = ps.cleanup(ps._gen_gated(text), sr) # Produktions-Wächter + cleanup dt = time.time() - t0 p = os.path.join(DESK, f"lucy_{tag}_{name}.wav") sf.write(p, a, sr) print(f"[{tag}] {name:6} gen={dt:5.2f}s audio={a.size/sr:4.1f}s -> {p}") ps.STATE.clear() del m if __name__ == "__main__": print("=== A2 AN (Highpass+Norm) + A1 safetensors-Cache ===") build(ref_clean=True, tag="clean", use_cache=True) print("\n=== A2 AUS (Roh-Referenz, direkt geklont) ===") build(ref_clean=False, tag="raw", use_cache=False) print(f"\nFERTIG. Samples liegen in: {DESK}")