mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-15 19:27:29 +02:00
* 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>
189 lines
7.3 KiB
TypeScript
189 lines
7.3 KiB
TypeScript
import type { VoiceModelSpec, VoiceSpeaker } from '../../shared/voice';
|
||
|
||
const ASR = 'https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models';
|
||
const KWS = 'https://github.com/k2-fsa/sherpa-onnx/releases/download/kws-models';
|
||
const TTS = 'https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models';
|
||
|
||
const KOKORO_SPEAKERS: VoiceSpeaker[] = [
|
||
{ id: 30, name: 'Siwis (femme, français)', lang: 'fr' },
|
||
{ id: 3, name: 'Heart (femme, anglais US)', lang: 'en' },
|
||
{ id: 2, name: 'Bella (femme, anglais US)', lang: 'en' },
|
||
{ id: 7, name: 'Nova (femme, anglais US)', lang: 'en' },
|
||
{ id: 11, name: 'Adam (homme, anglais US)', lang: 'en' },
|
||
{ id: 16, name: 'Michael (homme, anglais US)', lang: 'en' },
|
||
{ id: 17, name: 'Onyx (homme, anglais US)', lang: 'en' },
|
||
{ id: 21, name: 'Emma (femme, anglais UK)', lang: 'en' },
|
||
{ id: 24, name: 'Daniel (homme, anglais UK)', lang: 'en' },
|
||
{ id: 26, name: 'George (homme, anglais UK)', lang: 'en' }
|
||
];
|
||
|
||
export const VOICE_CATALOG: VoiceModelSpec[] = [
|
||
{
|
||
id: 'whisper-base',
|
||
kind: 'stt',
|
||
engine: 'whisper',
|
||
name: 'Whisper base (multilingue)',
|
||
description: 'Le plus rapide sur CPU ; précision moyenne en français, suffisante pour des commandes courtes.',
|
||
languages: ['fr', 'en', 'multi'],
|
||
sizeMb: 208,
|
||
url: `${ASR}/sherpa-onnx-whisper-base.tar.bz2`,
|
||
dir: 'sherpa-onnx-whisper-base',
|
||
files: ['base-encoder.int8.onnx', 'base-decoder.int8.onnx', 'base-tokens.txt'],
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'whisper-small',
|
||
kind: 'stt',
|
||
engine: 'whisper',
|
||
name: 'Whisper small (multilingue)',
|
||
description: 'Recommandé pour le français : nettement plus précis que base, environ trois fois plus lent.',
|
||
languages: ['fr', 'en', 'multi'],
|
||
sizeMb: 640,
|
||
url: `${ASR}/sherpa-onnx-whisper-small.tar.bz2`,
|
||
dir: 'sherpa-onnx-whisper-small',
|
||
files: ['small-encoder.int8.onnx', 'small-decoder.int8.onnx', 'small-tokens.txt'],
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'parakeet-v3',
|
||
kind: 'stt',
|
||
engine: 'nemo-transducer',
|
||
name: 'Parakeet TDT 0.6B v3 (25 langues européennes, français)',
|
||
description: 'Le plus précis en français et nettement plus rapide que Whisper sur processeur (NVIDIA NeMo, int8). Ponctuation et majuscules incluses.',
|
||
languages: ['fr', 'en', 'de', 'es', 'it', 'multi'],
|
||
sizeMb: 640,
|
||
url: `${ASR}/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8.tar.bz2`,
|
||
dir: 'sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8',
|
||
files: ['encoder.int8.onnx', 'decoder.int8.onnx', 'joiner.int8.onnx', 'tokens.txt'],
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'whisper-turbo',
|
||
kind: 'stt',
|
||
engine: 'whisper',
|
||
name: 'Whisper large-v3 turbo (multilingue)',
|
||
description: 'Très bonne précision multilingue ; 2 à 4 s par phrase sur un processeur récent. Parakeet est plus rapide en français.',
|
||
languages: ['fr', 'en', 'multi'],
|
||
sizeMb: 564,
|
||
url: `${ASR}/sherpa-onnx-whisper-turbo.tar.bz2`,
|
||
dir: 'sherpa-onnx-whisper-turbo',
|
||
files: ['turbo-encoder.int8.onnx', 'turbo-decoder.int8.onnx', 'turbo-tokens.txt']
|
||
},
|
||
{
|
||
id: 'sense-voice',
|
||
kind: 'stt',
|
||
engine: 'sense-voice',
|
||
name: 'SenseVoice small (zh / en / ja / ko)',
|
||
description: 'Très rapide, mais ne comprend pas le français.',
|
||
languages: ['en', 'zh', 'ja', 'ko'],
|
||
sizeMb: 163,
|
||
url: `${ASR}/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2`,
|
||
dir: 'sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17',
|
||
files: ['model.int8.onnx', 'tokens.txt']
|
||
},
|
||
{
|
||
id: 'kws-en',
|
||
kind: 'kws',
|
||
engine: 'kws-transducer',
|
||
name: 'Détecteur de mot-clé (zipformer, 3 Mo)',
|
||
description: 'Écoute permanente du mot d’activation, quasi gratuite en CPU. Mot-clé libre (« jarvis », « hey jarvis »…).',
|
||
languages: ['en', 'fr'],
|
||
sizeMb: 4,
|
||
url: `${KWS}/sherpa-onnx-kws-zipformer-gigaspeech-3.3M-2024-01-01.tar.bz2`,
|
||
dir: 'sherpa-onnx-kws-zipformer-gigaspeech-3.3M-2024-01-01',
|
||
files: [
|
||
'encoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx',
|
||
'decoder-epoch-12-avg-2-chunk-16-left-64.int8.onnx',
|
||
'joiner-epoch-12-avg-2-chunk-16-left-64.int8.onnx',
|
||
'tokens.txt'
|
||
],
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'silero-vad',
|
||
kind: 'vad',
|
||
engine: 'silero',
|
||
name: 'Silero VAD (fin de phrase neuronale, 0,6 Mo)',
|
||
description: 'Détecte précisément le début et la fin de la parole pendant l’écoute permanente ; moins de faux départs sur le bruit.',
|
||
languages: ['multi'],
|
||
sizeMb: 1,
|
||
url: `${ASR}/silero_vad.onnx`,
|
||
dir: 'silero-vad',
|
||
files: ['silero_vad.onnx'],
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'kokoro-v1',
|
||
kind: 'tts',
|
||
engine: 'kokoro',
|
||
name: 'Kokoro v1.0 multilingue',
|
||
description: 'Voix très naturelle, une voix française (Siwis) et de nombreuses voix anglaises. 24 kHz.',
|
||
languages: ['fr', 'en', 'multi'],
|
||
sizeMb: 349,
|
||
url: `${TTS}/kokoro-multi-lang-v1_0.tar.bz2`,
|
||
dir: 'kokoro-multi-lang-v1_0',
|
||
files: ['model.onnx', 'voices.bin', 'tokens.txt', 'lexicon-us-en.txt', 'lexicon-zh.txt', 'espeak-ng-data/phontab'],
|
||
speakers: KOKORO_SPEAKERS,
|
||
sampleRate: 24000,
|
||
recommended: true
|
||
},
|
||
{
|
||
id: 'piper-fr-siwis',
|
||
kind: 'tts',
|
||
engine: 'piper',
|
||
name: 'Piper Siwis (femme, français)',
|
||
description: 'Léger et instantané, rendu un peu plus mécanique que Kokoro. 22 kHz.',
|
||
languages: ['fr'],
|
||
sizeMb: 67,
|
||
url: `${TTS}/vits-piper-fr_FR-siwis-medium.tar.bz2`,
|
||
dir: 'vits-piper-fr_FR-siwis-medium',
|
||
files: ['fr_FR-siwis-medium.onnx', 'tokens.txt', 'espeak-ng-data/phontab'],
|
||
speakers: [{ id: 0, name: 'Siwis', lang: 'fr' }],
|
||
sampleRate: 22050
|
||
},
|
||
{
|
||
id: 'piper-fr-tom',
|
||
kind: 'tts',
|
||
engine: 'piper',
|
||
name: 'Piper Tom (homme, français)',
|
||
description: 'Voix masculine légère et instantanée. 22 kHz.',
|
||
languages: ['fr'],
|
||
sizeMb: 67,
|
||
url: `${TTS}/vits-piper-fr_FR-tom-medium.tar.bz2`,
|
||
dir: 'vits-piper-fr_FR-tom-medium',
|
||
files: ['fr_FR-tom-medium.onnx', 'tokens.txt', 'espeak-ng-data/phontab'],
|
||
speakers: [{ id: 0, name: 'Tom', lang: 'fr' }],
|
||
sampleRate: 22050
|
||
},
|
||
{
|
||
id: 'piper-fr-upmc',
|
||
kind: 'tts',
|
||
engine: 'piper',
|
||
name: 'Piper UPMC (Jessica et Pierre, français)',
|
||
description: 'Deux voix françaises, une féminine et une masculine. 22 kHz.',
|
||
languages: ['fr'],
|
||
sizeMb: 80,
|
||
url: `${TTS}/vits-piper-fr_FR-upmc-medium.tar.bz2`,
|
||
dir: 'vits-piper-fr_FR-upmc-medium',
|
||
files: ['fr_FR-upmc-medium.onnx', 'tokens.txt', 'espeak-ng-data/phontab'],
|
||
speakers: [
|
||
{ id: 0, name: 'Jessica (femme)', lang: 'fr' },
|
||
{ id: 1, name: 'Pierre (homme)', lang: 'fr' }
|
||
],
|
||
sampleRate: 22050
|
||
}
|
||
];
|
||
|
||
export function findModel(id: string): VoiceModelSpec | undefined {
|
||
return VOICE_CATALOG.find((m) => m.id === id);
|
||
}
|
||
|
||
// Speaker gender from the label ("(homme, …)", "(femme, …)", known first names) so the UI and the
|
||
// voice preference can pick a masculine or feminine voice without a lookup table per model.
|
||
const MALE = /\b(homme|tom|pierre|adam|michael|eric|liam|george|lewis|daniel|fenrir|puck|onyx|echo|santa)\b/i;
|
||
for (const spec of VOICE_CATALOG) {
|
||
for (const sp of spec.speakers ?? []) {
|
||
if (!sp.gender) sp.gender = /\b(femme|female)\b/i.test(sp.name) ? 'f' : MALE.test(sp.name) ? 'm' : /\bfemme\b/i.test(spec.name) ? 'f' : /\bhomme\b/i.test(spec.name) ? 'm' : undefined;
|
||
}
|
||
}
|