mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-11 17:29:03 +02:00
- Liaison Hermes : l'échec de l'API des crons (/api/jobs absente ou refusée) ne fait plus passer la liaison en « dégradé » ; l'onglet Crons affiche la raison. Les états « healthy / ready / ok » sont reconnus et un état « degraded » détaille les contrôles en échec. - Chat completions : une réponse sans fragment n'affiche plus « … » ; le corps est relu (JSON non streamé, erreur renvoyée en HTTP 200) et sinon l'erreur explicite « Réponse vide de Hermes » est affichée avec le début du corps. - Voix : transcriptions parasites de Whisper (« (cliquant) », « *Claire* », « [Musique] », génériques de sous-titres) ignorées au lieu d'être envoyées. - Préférence de voix masculine / féminine (Paramètres → Voix), appliquée à tous les moteurs : Piper Tom / Pierre en local (téléchargement automatique), onyx / nova en API OpenAI, Paul / Hortense en voix Windows. Genre des voix du catalogue déduit des libellés. Tests : 42 tests unitaires (santé, récupération de réponse, filtre de bruit, préférence de voix) ; e2e Electron inchangé et vert. Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y Co-authored-by: Claude <noreply@anthropic.com>
128 lines
3.0 KiB
TypeScript
128 lines
3.0 KiB
TypeScript
/** Local voice engine contract (sherpa-onnx in a utility process). Shared by main and renderer. */
|
|
|
|
export type VoiceModelKind = 'stt' | 'tts' | 'kws' | 'vad';
|
|
export type VoiceEngineKind = 'whisper' | 'sense-voice' | 'nemo-transducer' | 'kokoro' | 'piper' | 'kws-transducer' | 'silero';
|
|
|
|
export interface VoiceSpeaker {
|
|
id: number;
|
|
name: string;
|
|
lang: string;
|
|
/** m = masculine, f = feminine (from the catalog label). */
|
|
gender?: 'm' | 'f';
|
|
}
|
|
|
|
export interface VoiceModelSpec {
|
|
id: string;
|
|
kind: VoiceModelKind;
|
|
engine: VoiceEngineKind;
|
|
name: string;
|
|
description: string;
|
|
languages: string[];
|
|
sizeMb: number;
|
|
url: string;
|
|
/** Folder created by the archive (files are referenced relative to it). */
|
|
dir: string;
|
|
/** Files that must exist once installed. */
|
|
files: string[];
|
|
speakers?: VoiceSpeaker[];
|
|
sampleRate?: number;
|
|
recommended?: boolean;
|
|
}
|
|
|
|
export interface VoiceModelStatus extends VoiceModelSpec {
|
|
installed: boolean;
|
|
downloading: boolean;
|
|
installedBytes: number;
|
|
}
|
|
|
|
export interface VoiceDownloadProgress {
|
|
id: string;
|
|
phase: 'download' | 'extract' | 'done' | 'error' | 'cancelled';
|
|
received: number;
|
|
total: number;
|
|
percent: number;
|
|
message?: string;
|
|
}
|
|
|
|
export interface TranscribeRequest {
|
|
modelId: string;
|
|
wav: Uint8Array;
|
|
language: string; // 'fr', 'en', 'auto'
|
|
}
|
|
|
|
export interface TranscribeResult {
|
|
text: string;
|
|
language?: string;
|
|
durationMs: number;
|
|
audioSec: number;
|
|
}
|
|
|
|
export interface SynthesizeRequest {
|
|
modelId: string;
|
|
text: string;
|
|
speaker: number;
|
|
speed: number;
|
|
}
|
|
|
|
export interface SynthesizeResult {
|
|
wav: Uint8Array;
|
|
sampleRate: number;
|
|
durationMs: number;
|
|
audioSec: number;
|
|
}
|
|
|
|
export interface KwsStartRequest {
|
|
modelId: string;
|
|
/** Wake phrases in plain text (e.g. "jarvis", "hey jarvis"). */
|
|
keywords: string[];
|
|
/** 1 (strict) .. 5 (eager) */
|
|
sensitivity: number;
|
|
}
|
|
|
|
export interface KwsDetection {
|
|
keyword: string;
|
|
at: number;
|
|
}
|
|
|
|
export interface VadStartRequest {
|
|
modelId: string;
|
|
/** Silence that ends an utterance, in ms. */
|
|
silenceMs: number;
|
|
/** Detection threshold 0..1 (0.5 default). */
|
|
threshold: number;
|
|
maxUtteranceSec: number;
|
|
}
|
|
|
|
export type VadEvent =
|
|
| { type: 'speech-start' }
|
|
| { type: 'segment'; wav: Uint8Array; durationSec: number }
|
|
| { type: 'error'; message: string };
|
|
|
|
export interface VoiceEngineStatus {
|
|
available: boolean;
|
|
error?: string;
|
|
version?: string;
|
|
loaded: string[];
|
|
modelsDir: string;
|
|
}
|
|
|
|
export const VOICE_IPC = {
|
|
status: 'voice:status',
|
|
modelsList: 'voice:models:list',
|
|
modelsDownload: 'voice:models:download',
|
|
modelsCancel: 'voice:models:cancel',
|
|
modelsRemove: 'voice:models:remove',
|
|
modelsProgress: 'voice:models:progress',
|
|
transcribe: 'voice:transcribe',
|
|
synthesize: 'voice:synthesize',
|
|
unload: 'voice:unload',
|
|
kwsStart: 'voice:kws:start',
|
|
kwsStop: 'voice:kws:stop',
|
|
kwsAudio: 'voice:kws:audio',
|
|
kwsDetected: 'voice:kws:detected',
|
|
vadStart: 'voice:vad:start',
|
|
vadStop: 'voice:vad:stop',
|
|
vadAudio: 'voice:vad:audio',
|
|
vadEvent: 'voice:vad:event'
|
|
} as const;
|