## 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 `