Pre-existing work committed before starting Ralph self-improvement run on ralph/echo-improve branch, so that branch's diff stays isolated to the pocket-tts integration. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.8 KiB
6.8 KiB
Vreau să integrezi pocket-tts (Kyutai) ca motor TTS nou în echo-core, alături de Supertonic (motorul actual). Task arhitectural, nu un fix simplu — intră în plan mode înainte să atingi cod, și trece planul prin /plan-eng-review (arhitectură, edge cases, cum ating fișierele existente fără să stric fluxul live) înainte de implementare. Nu implementa nimic până planul nu e aprobat.
Context — ce există deja
- Motor actual: Supertonic, rulează ca serviciu systemd separat (
supertonic-tts.service), HTTP pe127.0.0.1:7788. Wrapper:tools/tts.py(synthesize(text, voice, lang)). - Comandă on-demand:
/audio(Discord slash command,src/adapters/discord_bot.py~L911-995) — parametrivoce(M1-M5/F1-F5),text_sau_url,rezumat. Apeleazăfast_dispatch("audio", ...)dinsrc/fast_commands.py, care întoarce__AUDIO__:<path>— interceptat de discord_bot.py și trimis ca attachment. - Mod live: Discord Voice (
/voice join),src/voice/pipeline.py+src/voice/tts_stream.py— streaming TTS pe clauze (clause_segments()), buget de latență strict (~5s perceput end-to-end, filler audio după 3s fără răspuns). Foloseștetools/tts.pyintern. - Credențiale: keyring, serviciu
"echo-core"(src/credential_store.py). Există dejadiscord_tokenșihf_token(HuggingFace, pentru modelul gated pocket-tts cu voice cloning — vezi mai jos).
Research + teste deja făcute (nu le repeta)
Am evaluat deja pocket-tts manual într-o sesiune anterioară (vezi memory: project_pocket_tts_voice_clone_eval.md):
- Nu suportă română oficial — doar english, french, german, portuguese, italian, spanish. Testele confirmă: text românesc sintetizat cu modelul englez sună cu accent englezesc puternic.
- Voice cloning funcționează bine din sample-uri scurte (~4-35s testate), via
get_state_for_audio_prompt(path_sau_nume_voce_predefinita). - Viteză reală măsurată pe acest CPU: ~2.7-2.9x faster-than-real-time (Kyutai raportează 6x pe Apple M4 — CPU-ul ăsta e mai lent per-core, dar tot confortabil peste real-time).
- Modelul cu voice cloning e gated pe HuggingFace — cere account + accept termeni + token (
HF_TOKEN). Tokenul lui Marius e deja în keyring (hf_token). - Instalare testată:
pip install pocket-tts(venv izolat de test la/tmp/pocket-tts-test/.venv, nu producție). CLI:pocket-tts generate --text "..." --voice <nume_sau_path.wav> --output-path out.wav. - Sample-uri de voce ale lui Marius, deja înregistrate (la
~/workspace/pocket-tts-test/, convertite la wav mono 24kHz):marius_real_voice.wav(7.8s) → devine voce "Marius 1"marius_real_voice_2.wav(12.6s) → devine voce "Marius 2"marius_real_voice_3.wav(35s, mai expresiv) → devine voce "Marius 3"
- Tool nou creat, deja în repo:
tools/discord_send_file.py— trimite fișier direct pe un canal Discord via REST API (necesar pentru că__AUDIO__:prefix nu funcționează în afara fast_commands — vezi docstring din script șipersonality/TOOLS.md§ "Discord — trimite fișier direct").
Cerințe confirmate de Marius (decizii arhitecturale — NU le renegocia, doar implementează)
- pocket-tts rulează ca proces/serviciu separat, exact ca Supertonic — systemd propriu, port propriu, apelat via HTTP din restul codului. Nu integrat direct în procesul bot (evită să bagi
torchca dependență grea în.venvprincipal). - pocket-tts = engine default. Supertonic = fallback.
- pocket-tts răspunde MEREU în engleză (fonetic), indiferent de limba textului de intrare — inclusiv pe text românesc (va suna cu accent, e acceptat/intenționat). Nu face rutare automată pe limbă.
- Fallback pe Supertonic doar la:
- (a) eșec tehnic pocket-tts (model indisponibil, HF token expirat, server jos, etc.)
- (b) comandă manuală de schimbare engine de la Marius — trebuie adăugată o comandă nouă pentru switch engine (ex:
/engine supertonic//engine pockettts, sau similar — alege convenția care se potrivește cel mai bine cu comenzile existente).
- Scope complet: atât mod live (Discord Voice, streaming pe clauze) cât și on-demand (
/audio). Nu doar unul din ele. - Selector de voce unificat: vocile Supertonic existente (M1-M5, F1-F5) plus vocile clonate, ca opțiuni suplimentare în același selector/aceeași comandă.
- Voci clonate salvate ca
.safetensors(export viaexport_model_state(), încărcare rapidă — vezi README pocket-tts pentru API exact), cu convenție de nume<Nume> <N>(ex:Marius 1,Marius 2,Marius 3; extensibil la alte persoane, ex:Paula 1, dacă Marius mai trimite sample-uri). - Marius va mai trimite sample-uri de voce în timp — trebuie un flux clar (comandă + atașament) pentru a adăuga o voce clonată nouă la catalog, fără intervenție manuală de cod de fiecare dată.
Ce trebuie să decidă/detalieze planul (edge cases de rezolvat explicit)
- Cum se comportă fallback-ul din mod live dacă pocket-tts pică la mijlocul unei conversații (schimbare de engine mid-sesiune, fără să rupă turul curent)?
- Ce se întâmplă cu
lang="ro"/--langparametrul existent dintools/tts.pyodată ce pocket-tts (mereu engleză) devine default — rămâne relevant doar pentru calea Supertonic? - Cum se integrează streaming-ul propriu al pocket-tts cu
clause_segments()dintts_stream.py(format audio, sample rate, chunking) — pocket-tts produce 24kHz, pipeline-ul Discord așteaptă 48kHz stereo s16le (vezi_ffmpeg_resampleîntts_stream.py). - Unde se stochează fișierele
.safetensorsale vocilor clonate (director nou în repo?models/voices/?~/workspace/?) — și cum se mapează nume → fișier (config nou înconfig.json, sau fișier JSON dedicat). - Cum se gestionează HF_TOKEN pentru serviciul systemd nou (environment file, similar cu cum
discord_tokene disponibil altor procese). - Comanda de switch engine — ephemeral (doar sesiunea curentă) sau persistă în
config.json/sessions/active.json? - Ce se întâmplă cu comanda
/audioexistentă când alegi o voce clonată — flow-ul de azi (fast_dispatch→__AUDIO__:prefix) rămâne valid pentru pocket-tts, sau outputul trebuie tratat diferit?
Instrucțiuni pentru sesiunea care preia
- Citește
memory/kb/relevant +project_pocket_tts_voice_clone_eval.mddin memory pentru context complet de research. - Intră în plan mode, scrie un plan concret care acoperă toate punctele de mai sus.
- Rulează planul prin
/plan-eng-review(arhitectură, edge cases, performance) înainte de orice modificare de cod. - Prezintă planul lui Marius pentru aprobare explicită înainte de implementare.
- Respectă principiile din
CLAUDE.md: impact minim, fără scope creep, verifică înainte de "done".