Choisissez l’API utilisée par votre application. Chaque API a ses propres mécanismes d’authentification et de création de sessions, ainsi que son propre contrat d’événements.
Connectez un serveur à GPT-Live
Utilisez une connexion WebSocket principale lorsque votre serveur capture de l’audio ou relaie un flux audio pour un client. Elle transporte l’audio et les événements JSON dans les deux sens. Conservez la clé API du projet sur ce serveur de confiance. Pour les applications mobiles et les applications exécutées dans un navigateur, commencez par WebRTC.
Ce guide traite de la connexion audio principale. Une connexion auxiliaire permet à un serveur d’observer et de contrôler une session Live existante. Une connexion WebSocket Responses relie votre backend à l’API Responses pour le raisonnement et les outils. Aucune des deux ne remplace la connexion audio principale.
Authentifiez-vous et démarrez la session
- Connectez-vous à
wss://api.openai.com/v1/live/sessionssans paramètres de requête. Authentifiez-vous avecAuthorization: Bearer $OPENAI_API_KEYet incluez les en-têtes de connexion présentés dans l’exemple. - Envoyez
session.startcomme premier message. Placez le modèle, les instructions de conversation, le format audio, la voix et la configuration de délégation dans l’objetsession. - Attendez
session.startedavant d’envoyer de l’audio ou des commandes de l’application. Cet événement contient la configuration effective de la session et son identifiant.
L’exemple ci-dessous utilise Marin, de l’audio PCM16 à 24 kHz et un backend Responses avec recherche web. Gardez les instructions de conversation courtes. Configurez les instructions du backend, les outils et leurs autorisations en suivant le guide Délégation et outils.
Transmettez de l’audio en continu avec un SDK
Pour Node.js, installez openai et ws avec npm install openai ws, puis enregistrez l’exemple JavaScript dans client.mjs. Pour Python sur macOS ou Linux, installez openai[realtime] et enregistrez l’exemple Python dans client.py. Définissez OPENAI_API_KEY dans l’environnement du serveur. Ces exemples nécessitent une version du SDK prenant en charge Live. L’exemple lit de l’audio brut mono PCM16 à 24 kHz depuis l’entrée standard et écrit l’audio renvoyé dans le même format sur la sortie standard. Reliez ces flux aux fonctions de capture et de lecture audio de votre application. Les journaux et les événements de transcription sont écrits sur la sortie d’erreur standard afin de ne pas corrompre le flux audio.
import OpenAI from "openai";
import { LiveWS } from "openai/resources/live/ws";
// stdin and stdout carry raw mono PCM16 audio at 24 kHz, not WAV files.
// Supply microphone bytes continuously and play stdout in the same format.
process.stdin.pause();
const ws = new LiveWS(new OpenAI());
let started = false;
let closing = false;
let finalized = false;
let pendingByte = Buffer.alloc(0);
let closeTimeout;
ws.socket.on("open", () => {
ws.send({
type: "session.start",
event_id: "event_start",
session: {
model: "gpt-live-1",
instructions:
"Be concise. Delegate requests needing current information to the backend, which can search the web.",
audio: {
format: { type: "audio/pcm", rate: 24000 },
output: { voice: "marin" },
},
delegation: {
type: "responses",
responses: {
model: "gpt-5.6-luna",
tools: [{ type: "web_search" }],
tool_choice: "auto",
},
},
},
});
});
process.stdin.on("data", (chunk) => {
if (!started || closing || ws.socket.readyState !== 1) return;
const bytes = Buffer.concat([pendingByte, chunk]);
const completeLength = bytes.length - (bytes.length % 2);
pendingByte = bytes.subarray(completeLength);
if (completeLength) {
ws.send({
type: "session.input_audio.append",
audio: bytes.subarray(0, completeLength).toString("base64"),
});
}
});
// Register the final-event handler before any close command can be sent.
ws.on("event", (event) => {
if (event.type === "session.started") {
started = true;
console.error("Session ready", event.session.id);
process.stdin.resume();
} else if (event.type === "session.output_audio.delta") {
process.stdout.write(Buffer.from(event.delta, "base64"));
} else if (event.type === "session.closed") {
finalized = true;
clearTimeout(closeTimeout);
process.stdin.pause();
console.error("Final session usage", event.usage);
ws.close();
} else {
// Includes transcript deltas and nested response.event usage.
console.error(JSON.stringify(event));
}
});
process.on("SIGINT", () => {
if (closing) return;
if (!started || ws.socket.readyState !== 1) {
ws.socket.platformSocket.terminate();
return;
}
closing = true;
process.stdin.pause();
ws.send({ type: "session.close" });
closeTimeout = setTimeout(() => {
console.error("Incomplete finalization: session.closed was not received");
process.exitCode = 1;
ws.socket.platformSocket.terminate();
}, 15_000);
});
ws.on("error", (error) => {
console.error(error.message);
process.exitCode = 1;
});
ws.socket.on("close", () => {
clearTimeout(closeTimeout);
process.stdin.pause();
if (!finalized) {
console.error("Connection closed without final session usage");
process.exitCode = 1;
}
});Exécutez node client.mjs ou python client.py après avoir raccordé votre source audio et votre lecteur. Une fois Session ready affiché, fournissez un flux continu provenant du microphone, au rythme de sa fréquence d’échantillonnage à l’enregistrement. Envoyer un fichier entier d’un seul coup via un pipe ne simule pas un microphone en direct. La fin de fichier (EOF) sur la source audio ne met pas fin à la conversation. Envoyez SIGINT au processus pour demander une fermeture propre.
L’exemple relie les flux audio ; votre application gère la capture, la mise en mémoire tampon, la lecture et le rééchantillonnage si nécessaire. Testez ces éléments avec vos appareils et votre réseau avant d’évaluer le comportement du modèle.
Choisissez le format audio
Définissez session.audio.format au démarrage. Un même format s’applique à l’entrée et à la sortie et ne peut pas être modifié pendant la session.
{"type":"audio/pcm","rate":24000}: PCM mono signé sur 16 bits, en petit-boutiste, à 24 kHz ; format par défaut.{"type":"audio/pcm","rate":16000}: PCM mono signé sur 16 bits, en petit-boutiste, à 16 kHz.{"type":"audio/pcmu","rate":8000}: G.711 μ-law à 8 kHz, un octet par échantillon.{"type":"audio/pcma","rate":8000}: G.711 A-law à 8 kHz, un octet par échantillon.
Encodez les octets bruts en base64, sans en-tête WAV ni en-tête d’un autre conteneur. Les blocs PCM doivent contenir des échantillons complets de 16 bits ; leur taille en octets doit donc être paire. L’exemple reporte tout octet restant à la fin d’un bloc dans le bloc d’entrée suivant. En dehors de cette contrainte, les limites des blocs sont arbitraires : conservez un flux continu et ordonné.
Rééchantillonnez l’audio lorsque sa fréquence d’échantillonnage diffère de la fréquence configurée. Modifier le paramètre de format ne convertit pas les octets d’entrée. Pour adapter l’exemple à G.711, transmettez les octets encodés de chaque bloc sans appliquer la logique d’alignement sur deux octets propre au PCM, et configurez le lecteur de sortie pour le même codec. Un flux G.711 correspondant peut être transmis sans conversion en PCM. Consultez Intégrations téléphoniques pour connecter un appel téléphonique.
Envoyez et recevez des événements
Envoyez chaque événement sous forme de message texte JSON. L’audio est transmis en base64 dans ces messages.
- Envoi audio : envoyez
session.input_audio.appendavec les octets bruts encodés en base64 dansaudio. Les ajouts audio ne font l’objet d’aucun accusé de réception. - Réception audio : décodez
deltadans chaque événementsession.output_audio.deltaet placez l’audio dans une file d’attente pour le lire dans l’ordre, au format configuré. - Réception des transcriptions : ajoutez le texte contenu dans
deltades événementssession.input_transcript.deltaetsession.output_transcript.deltaà la transcription correspondante. - Réception des événements du backend : lorsque vous utilisez la délégation à Responses, traitez le champ
eventimbriqué dans chaque envelopperesponse.event. - Gestion des erreurs : traitez les commandes rejetées et les erreurs de session signalées par les événements
error. Utilisezerror.client_event_id, lorsqu’il est présent, pour identifier la commande.
Les événements audio de sortie ne comportent aucun champ temporel, et GPT-Live n’émet pas d’événement output-audio-done. Suivez votre file d’attente de lecture pour savoir quelles données audio reçues ont été lues. Les horodatages des transcriptions décrivent des intervalles sur la chronologie de la session ; ils n’indiquent pas la fin de la lecture audio. La fin d’une réponse du backend ne signifie pas non plus que l’assistant a fini de parler.
GPT-Live détermine quand écouter et quand parler pendant la transmission audio en continu. Il n’utilise pas la boucle de tours de parole de Realtime, fondée sur la validation du tampon d’entrée et response.create. Dans Live, response.create démarre ou poursuit le travail délégué au backend. Consultez Délégation et outils pour ce workflow.
Configurez une session en cours
Le modèle Live, les instructions initiales de conversation, le format audio, la voix et le mode de délégation sont fixés au démarrage. Utilisez session.update pour modifier les paramètres pris en charge dans le mode de délégation actuel ; les paramètres omis conservent leur valeur actuelle. Une mise à jour réussie renvoie session.updated avec la configuration effective de la session.
Utilisez session.instructions.append pour ajouter des instructions de conversation, et session.input_audio.mute ou session.input_audio.unmute pour contrôler l’audio entrant. Couper l’audio d’entrée n’annule pas le travail du backend et n’arrête pas la parole générée. Consultez Gestion des sessions pour les mises à jour du contexte, les transcriptions, les commandes de contrôle de l’entrée et les données d’utilisation.
Fermez la session
Envoyez session.close lorsque la conversation se termine. Enregistrez d’abord le gestionnaire d’événement session.closed, continuez à recevoir les événements jusqu’à son arrivée, puis libérez la connexion. L’exemple attend jusqu’à 15 secondes et signale une finalisation incomplète si l’événement de fin n’arrive pas.
Conservez les données finales d’utilisation vocale de session.closed ainsi que les événements d’utilisation du backend déjà reçus. Les mises à jour de durée vocale sont des instantanés cumulatifs ; ne les additionnez pas. Une défaillance du transport ou un dépassement du délai avant session.closed laisse l’utilisation finale non confirmée. Consultez Gestion des sessions pour le cycle de vie complet.
L’API WebSockets, largement prise en charge pour le transfert de données en temps réel, est un excellent choix pour se connecter à la Realtime API d’OpenAI dans les applications serveur à serveur. Pour les clients mobiles et les clients exécutés dans un navigateur, nous recommandons une connexion via WebRTC.
Dans une intégration serveur à serveur avec Realtime, votre backend se connecte directement à la Realtime API via WebSocket. Vous pouvez utiliser une clé API standard pour authentifier cette connexion, puisque le token ne sera accessible que sur votre serveur backend sécurisé.
Connectez-vous via WebSocket
Vous trouverez ci-dessous plusieurs exemples de connexion à la Realtime API via WebSocket. En plus d’utiliser l’URL WebSocket ci-dessous, vous devrez transmettre un en-tête d’authentification contenant votre clé API OpenAI. Si votre application attribue des identifiants de sécurité, transmettez l’identifiant stable et respectueux de la vie privée de l’utilisateur final dans l’en-tête OpenAI-Safety-Identifier.
Il est possible d’utiliser WebSocket dans les navigateurs avec un token API éphémère, comme le montre le guide de connexion WebRTC. Toutefois, si vous vous connectez depuis un client tel qu’un navigateur ou une application mobile, WebRTC sera une solution plus robuste dans la plupart des cas.
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
});
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});# example requires websocket-client library:
# pip install websocket-client
import os
import json
import websocket
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1"
headers = [
"Authorization: Bearer " + OPENAI_API_KEY,
"OpenAI-Safety-Identifier: hashed-user-id",
]
def on_open(ws):
print("Connected to server.")
def on_message(ws, message):
data = json.loads(message)
print("Received event:", json.dumps(data, indent=2))
ws = websocket.WebSocketApp(
url,
header=headers,
on_open=on_open,
on_message=on_message,
)
ws.run_forever()Installez les gems nécessaires avec
gem install openai async-websocket.
require "openai"
client = OpenAI::Client.new(
default_headers: { "OpenAI-Safety-Identifier" => "hashed-user-id" }
)
client.realtime.connect(model: "gpt-realtime-2.1") do |connection|
puts("Connected to the Realtime API: #{connection.url.host}")
connection.each { |event| puts("Received event: #{event.type}") }
end/*
Note that in client-side environments like web browsers, we recommend
using WebRTC instead. It is possible, however, to use the standard
WebSocket interface in browser-like environments like Deno and
Cloudflare Workers.
*/
const ws = new WebSocket(
"wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1",
[
"realtime",
// Use a short-lived token fetched from your application server.
"openai-insecure-api-key." + OPENAI_REALTIME_EPHEMERAL_KEY,
// Optional
"openai-organization." + OPENAI_ORG_ID,
"openai-project." + OPENAI_PROJECT_ID,
]
);
ws.addEventListener("open", function open() {
console.log("Connected to server.");
});
ws.addEventListener("message", function incoming(event) {
console.log(event.data);
});Envoi et réception d’événements
Les sessions de la Realtime API sont gérées à l’aide de deux types d’événements : les événements envoyés par le client, que vous émettez en tant que développeur, et les événements envoyés par le serveur, que la Realtime API crée pour signaler les événements du cycle de vie de la session.
Avec une connexion WebSocket, vous envoyez et recevez des événements sérialisés en JSON sous forme de chaînes de caractères, comme dans l’exemple Node.js ci-dessous (les mêmes principes s’appliquent aux autres bibliothèques WebSocket) :
import WebSocket from "ws";
const url = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1";
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
"OpenAI-Safety-Identifier": "hashed-user-id",
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});L’interface WebSocket est peut-être l’interface de plus bas niveau disponible pour interagir avec un modèle Realtime. Vous devez y gérer vous-même l’envoi et le traitement des segments audio encodés en Base64 qui transitent par la connexion socket.
Pour savoir comment envoyer et recevoir de l’audio via WebSockets, consultez le guide des conversations Realtime.