## API vocale – Guide d'intégration client Cette documentation explique comment intégrer la partie **vocale** de l'API côté client (web ou autre) : - établir une **connexion WebRTC** avec le serveur, - envoyer l'**audio du micro** et recevoir la **réponse audio** de l'agent, - récupérer l'**historique de transcription texte** de la conversation, - configurer les **paramètres VAD** (Voice Activity Detection) à la connexion et en cours de session. ### Choix du transport via capabilities Le client doit interroger `GET /voice/capabilities` (avec Bearer JWT) pour savoir quel transport est disponible. Le champ `daily_available` dépend de la présence de `DAILY_API_KEY` côté serveur. | `daily_available` | Action recommandée | |-------------------|--------------------| | `true` | Utiliser `POST /voice/daily-start` (recommandé en cloud, HF Spaces) | | `false` | Utiliser `POST /voice/offer` (SmallWebRTC) | ```javascript // 1. Obtenir le transport disponible const capRes = await fetch("/voice/capabilities", { headers: { "Authorization": "Bearer " + jwt }, }); const { daily_available } = await capRes.json(); // 2. Choisir l'endpoint if (daily_available) { // Flux Daily : POST /voice/daily-start → room_url + token → SDK Daily const res = await fetch("/voice/daily-start?model=...", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + jwt }, body: JSON.stringify({}), }); const { room_url, token } = await res.json(); // Joindre avec Daily.createCallObject() ou createFrame() } else { // Flux SmallWebRTC : GET /voice/ice-servers → POST /voice/offer → PATCH /voice/offer // Voir section 1 } ``` ### Choix du transport (référence) | Transport | Endpoint principal | Page de test | Contexte recommandé | |----------------|-------------------------|------------------------|-----------------------------------------------| | **SmallWebRTC** | `POST /voice/offer` | `GET /voice-test` | Réseau local, connectivité directe | | **Daily.co** | `POST /voice/daily-start` | `GET /voice-daily` | Hugging Face Spaces, cloud, NAT strict | | **Daily minimal** | `POST /voice/daily-start` | `GET /voice-daily-minimal` | Même que Daily, mais sans iframe, UI intégrée | ### Endpoints principaux - `POST /auth/token` – obtenir un JWT (authentification). - `GET /voice/capabilities` – savoir si Daily est disponible. Réponse : `{ "daily_available": bool }` (selon `DAILY_API_KEY`). - **SmallWebRTC** : `GET /voice/ice-servers`, `POST /voice/offer`, `PATCH /voice/offer` – WebRTC direct. - **Daily.co** : `POST /voice/daily-start` – créer une room Daily et rejoindre (recommandé pour HF Spaces). - `GET /voice/transcript/{conversation_id}` – lecture des transcriptions (valide pour tous les transports). --- ## 1bis. Connexion via Daily.co (recommandé pour HF Spaces) Sur Hugging Face Spaces ou environnements cloud, la connexion WebRTC directe (SmallWebRTC) peut échouer (timeout ICE, NAT). **Daily.co** gère le routage média et le NAT traversal côté infrastructure, ce qui permet à la voix de fonctionner sans serveur TURN dédié. ### 1bis.1. Prérequis - Compte Daily.co et clé API (`DAILY_API_KEY` configurée côté serveur). - SDK `@daily-co/daily-js` : ```html ``` - Pages de test : `GET /voice-daily` (avec iframe) ou `GET /voice-daily-minimal` (sans iframe). ### 1bis.2. Flux côté client 1. Obtenir un JWT via `POST /auth/token`. 2. Appeler `POST /voice/daily-start` avec `Authorization: Bearer ` et (optionnel) `?model=...&project_id=...`. 3. La réponse contient `room_url`, `token` et `conversation_id`. 4. Joindre la room Daily avec le SDK `@daily-co/daily-js` – soit avec `createFrame()` (iframe Prebuilt, §1bis.4), soit avec `createCallObject()` (mode minimal, §1bis.5). ```javascript const res = await fetch("/voice/daily-start?model=mistral-large-latest", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer " + jwt }, body: JSON.stringify({}), // ou { request_data: { vad_stop_secs: 0.8 } } pour VAD }); const { room_url, token, conversation_id } = await res.json(); // Utiliser room_url et token pour Daily.createFrame() ou Daily.createCallObject() ``` ### 1bis.3. Endpoint `POST /voice/daily-start` - **Auth** : Bearer JWT. - **Query** : `model`, `project_id` (optionnels). - **Body** : `{ "request_data": { vad_stop_secs, vad_start_secs, ... } }` (optionnel, pour les paramètres VAD). - **Réponse** : `{ room_url, token, conversation_id }`. ### 1bis.4. Mode Prebuilt (avec iframe Daily) Utiliser l'interface préfabriquée Daily pour un test rapide : ```javascript const { room_url, token } = await res.json(); const callFrame = window.Daily.createFrame(containerElement, { showLeaveButton: true, iframeStyle: { width: "100%", height: "400px", border: "0" }, }); await callFrame.join({ url: room_url, token }); ``` ### 1bis.5. Mode minimal (sans iframe, votre propre UI) Pour intégrer dans votre propre UI sans le module Prebuilt, utilisez `Daily.createCallObject()` et attachez la piste audio du bot à un élément `