Realtime
Conversations vocales bidirectionnelles en temps réel basées sur WebSocket (protocole OpenAI Realtime) — conçues pour les assistants vocaux, la traduction en direct et autres scénarios à faible latence.
Connexion
Le nom du modèle est passé dans la chaîne de requête ; l'authentification est la même que pour les points de terminaison HTTP :
wss://test.kailin.com.cn/v1/realtime?model=gpt-4o-realtime-preview
const ws = new WebSocket(
'wss://test.kailin.com.cn/v1/realtime?model=gpt-4o-realtime-preview',
{
headers: {
Authorization: 'Bearer sk-your-token',
'OpenAI-Beta': 'realtime=v1',
},
}
);
Le new WebSocket du navigateur ne permet pas de définir des en-têtes personnalisés. Passez le token via les paramètres de sous-protocole, ou proxifiez le WebSocket via votre propre backend (recommandé, cela évite d'exposer le token côté frontend).
Format des messages
Tous les messages sont des trames texte JSON avec un champ type.
Configuration de la session
Après la connexion, le serveur envoie session.created. Le client envoie généralement d'abord session.update pour configurer la voix et la détection de tour de parole :
{
"type": "session.update",
"session": {
"instructions": "You are a voice assistant. Keep answers short.",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"input_audio_transcription": { "model": "whisper-1" },
"turn_detection": { "type": "server_vad" }
}
}
Envoi de l'audio utilisateur
L'audio est envoyé par fragments en PCM16 encodé en Base64 (24 kHz mono) :
{ "type": "input_audio_buffer.append", "audio": "<base64 pcm16>" }
{ "type": "input_audio_buffer.commit" }
Avec server_vad activé, le serveur détecte la fin de la parole et valide automatiquement — aucun commit manuel n'est nécessaire.
Déclencher une réponse
{
"type": "response.create",
"response": { "modalities": ["text", "audio"], "instructions": "Be enthusiastic." }
}
Événements serveur
| Événement | Description |
|---|---|
session.created / session.updated | Session créée / configuration appliquée |
input_audio_buffer.speech_started / _stopped | Le VAD a détecté le début / la fin de la parole |
input_audio_buffer.committed | Tampon audio validé |
conversation.item.created | Élément de conversation créé |
response.audio_transcript.delta / _done | Delta / fin de la transcription de la réponse |
response.audio.delta / _done | Delta audio de la réponse (Base64 PCM16) |
response.text.delta / _done | Delta d'une réponse textuelle uniquement |
response.done | Réponse en cours terminée |
error | Événement d'erreur |
Exemple de flux complet
const ws = new WebSocket(url);
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'session.update',
session: { voice: 'alloy', turn_detection: { type: 'server_vad' } },
}));
// send an audio chunk…
ws.send(JSON.stringify({
type: 'input_audio_buffer.append',
audio: btoa(String.fromCharCode(...pcmChunk)),
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case 'response.audio.delta':
playPcmChunk(atob(msg.delta));
break;
case 'response.audio_transcript.delta':
appendSubtitle(msg.delta);
break;
case 'response.done':
console.log('turn finished', msg.response.usage);
break;
}
};
Les points de terminaison Realtime facturent selon la durée de l'audio et coûtent nettement plus cher que le texte. Surveillez la durée de vos sessions pendant les tests. La disponibilité dépend des modèles configurés dans votre canal.