For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navigation principale
Theme

WebSockets

Connectez les flux audio gérés par votre serveur via WebSocket.

Choisissez votre API pour afficher les étapes de connexion et les événements de session correspondants.

Connexion d’un serveur à GPT-Live

Nous recommandons WebRTC pour les connexions audio à GPT-Live, y compris pour les intégrations de serveur à serveur.

GPT-Live prend également en charge les connexions WebSocket. La connexion WebSocket principale transporte l’audio et les événements JSON dans les deux sens. Conservez la clé API du projet sur votre serveur de confiance.

Ce guide explique comment transmettre un flux audio à GPT-Live. Pour surveiller ou piloter une session existante, consultez Contrôles côté serveur. Pour connecter un backend chargé du raisonnement et de l’exécution des outils à l’API Responses, consultez Mode WebSocket de l’API Responses.

Authentification et démarrage de la session

  1. Connectez-vous à wss://api.openai.com/v1/live/sessions sans paramètre de requête. Authentifiez-vous avec Authorization: Bearer $OPENAI_API_KEY et incluez les en-têtes de connexion indiqués dans l’exemple.
  2. Envoyez session.start comme premier message. Dans l’objet session, indiquez le modèle, les instructions de conversation, le format audio, la voix et la configuration de la délégation.
  3. Attendez l’événement session.started avant d’envoyer des données 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 la voix Marin, de l’audio PCM16 à 24 kHz et un backend Responses avec recherche web. Formulez des instructions de conversation courtes. Pour configurer les instructions du backend, ses outils et leurs autorisations, consultez Délégation et outils.

Transmission d’un flux audio avec un SDK

Pour Node.js, installez openai et ws avec npm install openai ws, puis enregistrez l’exemple JavaScript sous le nom client.mjs. Pour Python sur macOS ou Linux, installez openai[realtime], puis enregistrez l’exemple Python sous le nom client.py. Définissez OPENAI_API_KEY dans l’environnement du serveur. Ces exemples nécessitent une version du SDK compatible avec Live. L’exemple lit un flux audio brut PCM16 mono à 24 kHz sur l’entrée standard et écrit l’audio reçu 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 pour préserver l’intégrité du flux audio.

Pour Go, utilisez Go 1.26 ou une version ultérieure, enregistrez l’exemple sous le nom main.go, initialisez un module avec go mod init live-demo, puis installez github.com/openai/openai-go/v3@v3.85.1 avec go get. Pour Java, utilisez Java 17 ou une version ultérieure, ajoutez la dépendance Maven com.openai:openai-java:4.95.0 et utilisez la classe LiveConnectionWebsocketExample. Pour Ruby 3.3 ou une version ultérieure, installez le SDK avec gem install openai -v 0.110.0, installez sa dépendance WebSocket avec gem install async-websocket, puis enregistrez l’exemple sous le nom client.rb.

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, python client.py, go run ., ruby client.rb ou votre application Java après avoir connecté votre source audio et votre lecteur. Une fois le message Session ready affiché, transmettez en continu l’audio du microphone au rythme de l’enregistrement, en respectant sa fréquence d’échantillonnage. Envoyer tout un fichier d’un seul coup via un tube ne simule pas un microphone en direct. La fin du flux (EOF) de 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 assure la capture, la mise en mémoire tampon, la lecture et, si nécessaire, le rééchantillonnage. Testez ces fonctions avec vos appareils et votre réseau avant d’évaluer le comportement du modèle.

Choix du format audio

Définissez session.audio.format au démarrage. Le même format s’applique à l’entrée et à la sortie et reste fixe pendant toute la session.

  • {"type":"audio/pcm","rate":24000} : PCM mono signé sur 16 bits à 24 kHz, octet de poids faible en premier (format par défaut).
  • {"type":"audio/pcm","rate":16000} : PCM mono signé sur 16 bits à 16 kHz, octet de poids faible en premier.
  • {"type":"audio/pcmu","rate":8000} : G.711 loi μ à 8 kHz, un octet par échantillon.
  • {"type":"audio/pcma","rate":8000} : G.711 loi A à 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. Chaque bloc PCM doit contenir des échantillons complets de 16 bits et donc un nombre pair d’octets. S’il reste un octet en fin de bloc, l’exemple le reporte au début du bloc d’entrée suivant. Pour le reste, vous pouvez découper le flux librement, à condition de préserver sa continuité et l’ordre des données.

Rééchantillonnez l’audio si sa fréquence d’échantillonnage diffère de la fréquence configurée. Modifier le format dans la configuration ne convertit pas les octets d’entrée. Pour adapter l’exemple à G.711, transmettez les octets encodés de chaque bloc sans appliquer l’alignement sur deux octets propre au PCM, puis configurez le lecteur de sortie pour qu’il utilise le même codec. Un flux G.711 conforme à la configuration peut être transmis sans conversion en PCM. Pour connecter un appel téléphonique, consultez Intégrations téléphoniques.

Envoi et réception d’événements

Envoyez chaque événement dans un message texte au format JSON. Ces messages transportent l’audio encodé en base64.

  • Envoi de l’audio : envoyez session.input_audio.append en plaçant les octets bruts encodés en base64 dans audio. Les ajouts de données audio ne donnent lieu à aucun accusé de réception.
  • Réception de l’audio : décodez delta dans chaque événement session.output_audio.delta, puis placez les blocs audio dans la file de lecture dans l’ordre de réception, en utilisant le format configuré.
  • Réception des transcriptions : ajoutez le texte du champ delta des événements session.input_transcript.delta et session.output_transcript.delta à la transcription correspondante.
  • Réception des événements du backend : si vous utilisez la délégation à Responses, traitez l’objet event imbriqué dans chaque enveloppe response.event.
  • Gestion des erreurs : traitez les rejets de commandes et les erreurs de session signalés par les événements error. Utilisez error.client_event_id, s’il est présent, pour identifier la commande.

Suivez la lecture à l’aide de la file d’attente audio de votre application. La connexion WebSocket principale de GPT-Live transmet l’audio de sortie sans champs temporels ni événement signalant la fin de l’audio de sortie. Utilisez les horodatages des transcriptions pour organiser les sous-titres et les événements du backend pour suivre les tâches déléguées.

Pendant la transmission continue de l’audio, GPT-Live détermine quand écouter et quand prendre la parole. Utilisez response.create pour lancer ou poursuivre une tâche déléguée au backend. Pour en savoir plus sur cette procédure, consultez Délégation et outils.

Configuration d’une session en cours

Le modèle Live, les instructions de conversation initiales, 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. Si la mise à jour réussit, vous recevez 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 couper ou réactiver l’entrée audio. Couper l’entrée audio n’annule pas les tâches du backend et n’interrompt pas la parole générée. Pour en savoir plus sur les mises à jour du contexte, les transcriptions, les commandes d’entrée et les données d’utilisation, consultez Gestion des sessions.

Fermeture de la session

Envoyez session.close à la fin de la conversation. Enregistrez au préalable un gestionnaire pour session.closed, continuez à recevoir les événements jusqu’à la réception de cet événement final, puis libérez la connexion. L’exemple attend jusqu’à 15 secondes et signale que la fermeture n’a pas abouti si l’événement final n’arrive pas.

Conservez les données finales d’utilisation de la voix fournies par session.closed ainsi que les événements d’utilisation du backend déjà reçus. Chaque mise à jour de la durée d’utilisation de la voix indique un total cumulé. Ne les additionnez pas. En cas d’erreur de transport ou d’expiration du délai avant la réception de session.closed, les données finales d’utilisation restent à confirmer. Pour consulter l’ensemble du cycle de vie, reportez-vous à Gestion des sessions.