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}/consentsavecpurpose(finalité),recording_allowed,transcription_allowed,retention_days(1 à 3650) etmethod(verbal,click,written,api). L'appelant est enregistré danscaptured_by, l'heure danscaptured_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 ;falserefusé au démarrage en production). Sans consentement actif autorisant la transcription, chaque événement audio reçoit l'erreur WebSocketconsent_required(purpose: transcription), aucune transcription n'est lancée et le tour refusé est auditérealtime.turn.refusedavec une décision de refus.- L'enregistrement (
config.record: true) exige toujoursrecording_allowed, dans tous les environnements. L'audio accumulé entre deuxinput_audio.commitest scellé avec la clé du tenant (eai.realtime_recordings, empreinte sha256 et taille en clair) et l'événementrecording.savedest envoyé. - Conservation : transcriptions et enregistrements expirent
retention_daysaprès la capture.POST /v1/retention/run(type de ressourcerealtime, 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 colonnesparticipant_identity,on_behalf_of,agent_idderealtime_sessions.
Identité (MULT-012, RELE-011)
- Un utilisateur ouvre une session pour lui-même (
on_behalf_ofdifférent de l'appelant : 403identity_mismatch) et peut nommer l'agent_idavec lequel il parle. Un principal agent l'ouvreon_behalf_ofun utilisateur ; son identifiant devientagent_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_idetactor_kind. Le test du vrai serveur LiveKit les retrouve dansListParticipants. - Chaque tour (
inputouresponse) enregistre et auditeparticipant_id,user_id,agent_id,session_idettrace_id(l'événement d'audit porte la même trace).GET /v1/realtime/sessions/{id}/turnsles 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 :
| Moteur | Source (épinglée) | Fichier | sha256 | Licence |
|---|---|---|---|---|
| faster-whisper tiny.en | Hugging Face Systran/faster-whisper-tiny.en révision 0d3d19a32d3338f10357c0889762bd8d64bbdeba | model.bin | 1a5afae06a4db91c975c9a9d78be5cc110ee4ea022ad57d55492e4550e936b2a | MIT |
| Silero VAD | GitHub snakers4/silero-vad étiquette v6.2.3 | silero_vad.onnx | 1a153a22f4509e292a94e67d6f9b85e8deb25b4988682b7e174c65279d8788e3 | MIT |
| Kokoro v1.0 int8 | GitHub thewh1teagle/kokoro-onnx publication model-files-v1.0 (export de hexgrad/Kokoro-82M) | kokoro-v1.0.int8.onnx | 6e742170d309016e5891a994e1ce1559c702a2ccd0075e67ef7157974f6406cb | Apache-2.0 |
| Voix Kokoro | même publication | voices-v1.0.bin | bca610b8308e8d99f32e6fe4197e7ec01679264efed0cac9140fe9c29f1fbf7d | Apache-2.0 |
| Serveur LiveKit 1.13.11 | GitHub livekit/livekit publication v1.13.11 | livekit_1.13.11_linux_amd64.tar.gz | 1e9ee90ca301e1842b2887fc77cb122759756a9c8aeb4334ee91de3325ec43fb | Apache-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.