mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-17 12:18:29 +02:00
feat: voix JARVIS, Parakeet v3 pour le français, worklets audio sous CSP stricte (v2.4.1) (#19)
* feat: voix JARVIS, Parakeet v3 pour le français, worklets audio sous CSP stricte (v2.4.1) Voix - Timbre « JARVIS » (Web Audio) : hauteur légèrement abaissée, chaleur dans les basses, présence, compression douce, courte réverbération d'intercom. Activé par défaut, réglable dans Paramètres → Voix. - Préréglage « Voix JARVIS » en un clic : moteur local, voix masculine française (Piper Tom téléchargé automatiquement, Kokoro n'ayant pas de voix française masculine), débit calme. Affichage de la voix active. - Boutons Masculine / Féminine désormais lisibles (style du sélecteur ajouté). Reconnaissance - Parakeet TDT 0.6B v3 (NVIDIA NeMo, int8, 25 langues européennes dont le français) ajouté au catalogue et recommandé : plus précis et plus rapide que Whisper sur processeur, ponctuation incluse. - 0,4 s de silence ajoutées avant et après chaque énoncé avant la reconnaissance (syllabes coupées, hallucinations de Whisper sur les clips courts). Écoute permanente - Les modules AudioWorklet sont livrés en fichiers statiques (public/worklets) chargés depuis l'application : en version installée, la CSP stricte (script-src 'self') refusait les URL blob et l'écoute permanente échouait avec « Unable to load a worklet's module ». Repli blob conservé pour le dev. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y * docs: mesures Parakeet vs Whisper et worklets dans la feuille de route Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
d1b12c16c5
commit
5ef440e8cf
13 files changed
+221
-11
No files matched your search
@@ -374,7 +374,32 @@ export function SettingsDrawer({ onClose }: Props) {
|
||||
<button className={(settings.speech.voiceGender ?? 'male') === 'male' ? 'active' : ''} onClick={() => { update({ speech: { voiceGender: 'male' } }); void ensurePreferredVoice().then((m) => m && setTtsTest({ status: 'ok', message: m })); }}>Masculine</button>
|
||||
<button className={settings.speech.voiceGender === 'female' ? 'active' : ''} onClick={() => { update({ speech: { voiceGender: 'female' } }); void ensurePreferredVoice().then((m) => m && setTtsTest({ status: 'ok', message: m })); }}>Féminine</button>
|
||||
</div>
|
||||
<span className="hint">S’applique à tous les moteurs : voix locale (Piper Tom ou Pierre pour le masculin, téléchargée automatiquement si besoin), voix OpenAI (onyx / nova), voix système Windows (Paul / Hortense).</span>
|
||||
<span className="hint">S’applique à tous les moteurs : voix locale (Piper Tom ou Pierre pour le masculin, téléchargée automatiquement si besoin), voix OpenAI (onyx / nova), voix système Windows (Paul / Hortense). Kokoro n’a pas de voix française masculine.</span>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Timbre</label>
|
||||
<div className="segmented">
|
||||
<button className={settings.speech.timbre === 'jarvis' ? 'active' : ''} onClick={() => update({ speech: { timbre: 'jarvis' } })}>JARVIS</button>
|
||||
<button className={settings.speech.timbre !== 'jarvis' ? 'active' : ''} onClick={() => update({ speech: { timbre: 'natural' } })}>Naturel</button>
|
||||
</div>
|
||||
<span className="hint">JARVIS : voix légèrement plus grave et posée, chaleur dans les basses, présence, courte réverbération d’intercom, comme dans le film.</span>
|
||||
</div>
|
||||
<div className="row" style={{ marginBottom: 10 }}>
|
||||
<button
|
||||
className="btn small primary"
|
||||
onClick={() => {
|
||||
update({ speech: { provider: 'local', voiceGender: 'male', timbre: 'jarvis', speed: 0.97, autoSpeak: true } });
|
||||
setTtsTest({ status: 'running', message: 'préparation de la voix JARVIS (téléchargement de Piper Tom si nécessaire)…' });
|
||||
void ensurePreferredVoice().then((m) => setTtsTest({ status: 'ok', message: m || 'Voix JARVIS prête.' })).catch((e: Error) => setTtsTest({ status: 'fail', message: e.message }));
|
||||
}}
|
||||
>
|
||||
<Volume2 size={13} /> Préréglage voix JARVIS (français, masculine, locale)
|
||||
</button>
|
||||
<span className="status-pill">
|
||||
{settings.speech.provider === 'local'
|
||||
? `voix active : ${voiceModels.find((m) => m.id === settings.speech.localModel)?.speakers?.find((s) => s.id === settings.speech.localSpeaker)?.name ?? settings.speech.localModel}`
|
||||
: `moteur : ${settings.speech.provider}`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Moteur de synthèse</label>
|
||||
|
||||
Reference in new issue
Block a user