Aller au contenu principal

Runtime vocal : consentement, identité, interruption, données personnelles, moteurs

Version anglaise : en/voice-runtime.md. Briques F-05 à F-12, exigences MULT-001 à MULT-012 et RELE-011, scénario 18 du kit.

Consentement et conservation (MULT-008)​

  • Un enregistrement de consentement par session et par participant : POST /v1/realtime/sessions/{id}/consents avec purpose (finalité), recording_allowed, transcription_allowed, retention_days (1 à 3650) et method (verbal, click, written, api). L'appelant est enregistré dans captured_by, l'heure dans captured_at. Révocation : POST /v1/realtime/sessions/{id}/consents/{consent_id}/revoke, effective dès l'événement audio suivant.
  • EAI_REALTIME_CONSENT_REQUIRED (non défini : requis hors dev et test ; false refusé au démarrage en production). Sans consentement actif autorisant la transcription, chaque événement audio reçoit l'erreur WebSocket consent_required (purpose: transcription), aucune transcription n'est lancée et le tour refusé est audité realtime.turn.refused avec une décision de refus.
  • L'enregistrement (config.record: true) exige toujours recording_allowed, dans tous les environnements. L'audio accumulé entre deux input_audio.commit est scellé avec la clé du tenant (eai.realtime_recordings, empreinte sha256 et taille en clair) et l'événement recording.saved est envoyé.
  • Conservation : transcriptions et enregistrements expirent retention_days après la capture. POST /v1/retention/run (type de ressource realtime, inclus dans une exécution sans type) supprime les lignes expirées et rend les compteurs.
  • Tables (migration V145, RLS activée et forcée) : realtime_consents, realtime_turns, realtime_transcripts, realtime_recordings ; nouvelles colonnes participant_identity, on_behalf_of, agent_id de realtime_sessions.

Identité (MULT-012, RELE-011)​

  • Un utilisateur ouvre une session pour lui-même (on_behalf_of différent de l'appelant : 403 identity_mismatch) et peut nommer l'agent_id avec lequel il parle. Un principal agent l'ouvre on_behalf_of un utilisateur ; son identifiant devient agent_id.
  • L'identité du participant LiveKit est l'identifiant de l'appelant ; les métadonnées du jeton portent tenant_id, session_id, on_behalf_of, agent_id et actor_kind. Le test du vrai serveur LiveKit les retrouve dans ListParticipants.
  • Chaque tour (input ou response) enregistre et audite participant_id, user_id, agent_id, session_id et trace_id (l'événement d'audit porte la même trace). GET /v1/realtime/sessions/{id}/turns les liste avec le statut et la latence mesurée.

Interruption (MULT-010)​

response.create {text} démarre un tour de réponse : l'adaptateur TTS s'exécute dans un thread et l'audio part en morceaux response.audio.delta de 100 ms, au rythme du temps réel (config.response_pace, 0 sans rythme). Une prise de parole (input_audio.speech_started, tout input_audio.append pendant la réponse, ou response.cancel) arrête le flux au morceau suivant, abandonne un appel TTS encore en cours, enregistre le tour cancelled avec chunks_sent et la raison, audite realtime.turn.cancelled et envoie response.cancelled. Le response.create suivant démarre un tour neuf.

Données personnelles des transcriptions (MULT-009)​

La transcription passe par la DLP du domaine privacy (mode mask par défaut, tokenize ou block ; detect est refusé pour une session temps réel) avant d'être stockée, envoyée au client ou au modèle. Les lignes stockées gardent le texte filtré et seulement les types de détection avec leur nombre. Les adaptateurs ne journalisent jamais l'audio ni la transcription ; les tests vérifient les lignes stockées, les journaux, les événements d'audit et les spans.

Moteurs sur CPU (MULT-003, MULT-005, MULT-006)​

tools/multimodal/setup.sh crée /tmp/toolchains/voice-venv (faster-whisper 1.2.1, ctranslate2 4.6.0, onnxruntime 1.22.1, numpy 2.2.6, kokoro-onnx 0.6.1 depuis PyPI) et /tmp/toolchains/voice-models, chaque fichier épinglé et vérifié par sha256 :

MoteurSource (épinglée)Fichiersha256Licence
faster-whisper tiny.enHugging Face Systran/faster-whisper-tiny.en révision 0d3d19a32d3338f10357c0889762bd8d64bbdebamodel.bin1a5afae06a4db91c975c9a9d78be5cc110ee4ea022ad57d55492e4550e936b2aMIT
Silero VADGitHub snakers4/silero-vad étiquette v6.2.3silero_vad.onnx1a153a22f4509e292a94e67d6f9b85e8deb25b4988682b7e174c65279d8788e3MIT
Kokoro v1.0 int8GitHub thewh1teagle/kokoro-onnx publication model-files-v1.0 (export de hexgrad/Kokoro-82M)kokoro-v1.0.int8.onnx6e742170d309016e5891a994e1ce1559c702a2ccd0075e67ef7157974f6406cbApache-2.0
Voix Kokoromême publicationvoices-v1.0.binbca610b8308e8d99f32e6fe4197e7ec01679264efed0cac9140fe9c29f1fbf7dApache-2.0
Serveur LiveKit 1.13.11GitHub livekit/livekit publication v1.13.11livekit_1.13.11_linux_amd64.tar.gz1e9ee90ca301e1842b2887fc77cb122759756a9c8aeb4334ee91de3325ec43fbApache-2.0

Le worker vocal HTTP tools/multimodal/voice_worker.py (127.0.0.1 seulement) sert /audio/transcriptions, /audio/speech et /vad ; la plateforme l'atteint par les adaptateurs openai-compatible-stt (EAI_STT_URL), openai-compatible-tts (EAI_TTS_URL) et http-vad (EAI_VAD_URL) à travers la garde de sortie. Des adaptateurs en processus existent aussi : kokoro (EAI_KOKORO_MODEL, EAI_KOKORO_VOICES), silero-onnx (EAI_SILERO_VAD_MODEL), faster-whisper (EAI_WHISPER_MODEL).

Exceptions de licence enregistrées : kokoro-onnx phonétise avec espeak-ng (GPL-3.0) via phonemizer (GPL-3.0) et espeakng-loader : ils ne tournent que dans le processus séparé du worker vocal, jamais dans le plan de contrôle. ffmpeg (/usr/bin/ffmpeg, LGPL-2.1 ou GPL selon la compilation) est appelé comme programme externe pour l'extraction des images et de l'audio des vidéos. Piper n'est pas livré : sa version maintenue piper1-gpl (piper-tts 1.3 et suivantes) est en GPL-3.0 ; Kokoro est le moteur TTS de référence.

Latences mesurées (CPU, cette machine)​

Écrites par tests/test_voice_engines_real.py dans /tmp/eai-voice-latency.json : synthèse Kokoro d'une phrase environ 4,1 s au premier appel (chargement du modèle compris) et 1,2 s ensuite, Silero VAD sur 4,5 s d'audio environ 0,1 s, faster-whisper tiny.en environ 1,0 s, tour d'entrée par la WebSocket (VAD, STT, DLP) environ 1,9 s, DLP sous 2 ms.

Limites​

  • MULT-001, MULT-002 : le serveur LiveKit est réellement démarré, le jeton de la plateforme est validé et le participant rejoint la salle par la WebSocket de signalisation ; le média WebRTC (UDP, ICE, codecs) exige un navigateur ou un client WebRTC et n'est pas testé.
  • MULT-004 : les poids pyannote sont à accès restreint sur Hugging Face (EAI_HF_TOKEN) ; l'adaptateur n'est testé qu'avec une simulation.
  • MULT-007 : les images des vidéos sont extraites par le vrai ffmpeg et analysées par l'adaptateur de vision face à un faux VLM ; un vrai VLM exige un GPU et des poids.