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>
54 lines
2.6 KiB
Python
54 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Qualitäts-Sweep: noise_clamp (nie getestet, Hypothese: dämpft Artefakte+Kollaps) × lsd, temp 0.9.
|
||
Produktions-äquivalente Verarbeitung (LEAD + cleanup v4 wie der Server) -> faires A/B gegen lucy_final."""
|
||
import os, time, numpy as np, soundfile as sf, librosa
|
||
from pocket_tts import TTSModel
|
||
|
||
BASE = r"F:\Coding Stuff\mission-control-2\client\lucy-tts"
|
||
OUT = r"C:\Users\TobisPC\Desktop\lucy_quality_sweep"; os.makedirs(OUT, exist_ok=True)
|
||
src, _ = librosa.load(os.path.join(BASE, "ref.mp3"), sr=24000, mono=True)
|
||
srt, _ = librosa.effects.trim(src, top_db=30); ref = os.path.join(BASE, "ref.wav")
|
||
sf.write(ref, srt[:int(18*24000)], 24000)
|
||
LEAD, TARGET_RMS = "Tja. ", 0.09
|
||
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 crop_lead(a, sr):
|
||
iv = librosa.effects.split(a, top_db=35)
|
||
if len(iv) >= 2:
|
||
cut = max(iv[0][1], iv[1][0] - int(0.06*sr)); a = a[cut:]
|
||
return a
|
||
def cleanup(a, sr):
|
||
a = np.asarray(a, dtype=np.float32).reshape(-1)
|
||
if a.size == 0: return a
|
||
a = crop_lead(a, sr)
|
||
rev,_ = librosa.effects.trim(a[::-1], top_db=45); a = rev[::-1] if rev.size else a
|
||
rms = float(np.sqrt(np.mean(a**2))) or 1e-9; a = a*(TARGET_RMS/rms)
|
||
peak = float(np.max(np.abs(a)))
|
||
if peak > 0.9: a = a*(0.9/peak)
|
||
fi = min(int(0.008*sr), a.size//2)
|
||
if fi>0: a[:fi]*=np.linspace(0.,1.,fi,dtype=np.float32); a[-fi:]*=np.linspace(1.,0.,fi,dtype=np.float32)
|
||
pad = np.zeros(int(0.08*sr), dtype=np.float32)
|
||
return np.concatenate([pad, a, pad])
|
||
|
||
# (tag, lsd, noise_clamp)
|
||
COMBOS = [
|
||
("A_baseline_lsd6_ncNone", 6, None),
|
||
("B_lsd6_nc2", 6, 2.0),
|
||
("C_lsd6_nc3", 6, 3.0),
|
||
("D_lsd10_nc3", 10, 3.0),
|
||
]
|
||
for tag, lsd, nc in COMBOS:
|
||
t0 = time.time()
|
||
m = TTSModel.load_model(language="german_24l", lsd_decode_steps=lsd, temp=0.9, noise_clamp=nc)
|
||
vs = m.get_state_for_audio_prompt(ref); sr = m.sample_rate
|
||
print(f"== {tag} (load {time.time()-t0:.1f}s) ==", flush=True)
|
||
for name, text in SENT.items():
|
||
t0 = time.time(); a = m.generate_audio(vs, LEAD+text, frames_after_eos=4); dt = time.time()-t0
|
||
a = a.numpy() if hasattr(a,"numpy") else np.asarray(a)
|
||
a = cleanup(a, sr); secs = a.size/sr
|
||
sf.write(os.path.join(OUT, f"{tag}_{name}.wav"), a, sr)
|
||
print(f" [{name:6}] gen={dt:4.1f}s audio={secs:4.1f}s RTF={dt/max(secs,0.01):.2f}", flush=True)
|
||
print("SWEEP_DONE", flush=True)
|