09a1c98514
- pocket_server.py (Produktions-TTS mit Stimmen-Waechter), text_norm, Bench-/Diag-Skripte - lucy-f5: f5_server/f5_test/bench_dml (DirectML-Experiment, Phase C/D offen) - .gitignore: venvs/Modelle/Audio/Logs der beiden Ordner + box_recon/gemma_swap-Scratch Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
65 lines
3.1 KiB
Python
65 lines
3.1 KiB
Python
# -*- 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}")
|