Après vous être connecté à GPT-Live, utilisez les événements de session pour mettre à jour le contexte, afficher les transcriptions et gérer le cycle de vie de la connexion. Le modèle peut écouter et parler en même temps : gérez donc séparément les événements reçus, la lecture audio et l’état des tâches backend dans votre application.
Ce guide suppose que votre connexion a émis session.started. Consultez Connexions pour la configuration de la connexion et la diffusion audio en continu, et Délégation et outils pour les tâches backend.
Configurez une session
Choisissez le modèle, la voix et le mode de délégation lors de la création de la session. Donnez au modèle des instructions pour la conversation et incluez l’historique pertinent. GPT-Live gère automatiquement le contexte à mesure que la conversation s’allonge.
Champs de configuration
| Paramètre | Configuration au démarrage | Modification en cours de session |
|---|---|---|
| Modèle | Renseignez le champ obligatoire model. | Démarrez une nouvelle session pour le modifier. |
| Instructions | Définissez instructions pour guider le comportement pendant la conversation, dans la limite de 16 384 tokens. | Ajoutez des instructions avec session.instructions.append. |
| Historique | Renseignez input avec les messages texte antérieurs pertinents. Sa valeur par défaut est []. | Ajoutez du contexte ; ne remplacez pas l’historique fourni au démarrage. |
| Voix | Définissez audio.output.voice sur une voix prise en charge ou une voix personnalisée autorisée. La valeur par défaut est marin. | Démarrez une nouvelle session pour la modifier. |
| Délégation | Définissez delegation.type sur client ou responses. Si la délégation est omise ou vaut null, le mode client est sélectionné. | Mettez à jour les paramètres Responses dans le mode actuel. |
| Stockage | Définissez store sur true pour pouvoir forker la session. Sa valeur par défaut est false. | Choisissez au démarrage. |
Voix disponibles
Choisissez une voix lors de la création de la session. Définissez audio.output.voice sur son nom dans l’API, par exemple "quartz". GPT-Live propose les voix supplémentaires suivantes :
| Voix | Nom dans l’API | Langue | Influence régionale | Présentation | Source |
|---|---|---|---|---|---|
| Quartz | quartz | Anglais | Australienne | Féminine | Générée |
| Ripple | ripple | Anglais | Australienne | Masculine | Naturelle |
| Vesper | vesper | Anglais | Britannique | Masculine | Naturelle |
| Willow | willow | Anglais | Irlandaise | Féminine | Naturelle |
| Stone | stone | Anglais | Irlandaise | Masculine | Naturelle |
| Gleam | gleam | Anglais | Nord-américaine | Féminine | Naturelle |
| Meridian | meridian | Anglais | Nord-américaine | Masculine | Naturelle |
| Bossa | bossa | Portugais | Brésilienne | Féminine | Naturelle |
| Tempo | tempo | Portugais | Brésilienne | Masculine | Naturelle |
| Beacon | beacon | Anglais | Philippine | Masculine | Générée |
| Delta | delta | Anglais | Sud des États-Unis | Féminine | Générée |
| Cinder | cinder | Anglais | Sud des États-Unis | Masculine | Générée |
L’influence régionale décrit la façon de parler d’une voix, sans garantir la fidélité de son accent. Pour utiliser une voix approuvée créée à partir de votre propre enregistrement, consultez Voix personnalisées.
Avec WebSocket, choisissez le format partagé audio.format au démarrage ; il ne peut pas être modifié pendant la session. Avec WebRTC, omettez ce champ, car la connexion négocie son format audio. Consultez Formats audio WebSocket pour en savoir plus sur les formats et la diffusion en continu.
Mettez à jour une session en cours
Utilisez session.update pour modifier session.delegation.responses dans une session qui utilise déjà la délégation à Responses. Envoyez uniquement les paramètres que vous souhaitez modifier ; les paramètres omis conservent leurs valeurs. Consultez Configurez la délégation à Responses pour connaître les paramètres et le workflow de mise à jour.
Vous ne pouvez pas modifier le mode de délégation après le démarrage. En particulier, définir delegation sur null sélectionne le mode client ; cela ne réinitialise pas une session Responses. Les champs de démarrage model, instructions, input, audio et store ne sont pas acceptés dans les mises à jour. Les champs de configuration inconnus sont rejetés.
Une mise à jour réussie émet session.updated avec la configuration complète et résolue de la session. Lorsque vous fournissez un event_id, l’accusé de réception le renvoie dans client_event_id. Surveillez les commandes rejetées ainsi que les accusés de réception. L’acceptation confirme la mise à jour de la configuration ; elle ne prouve pas qu’une tâche backend a été exécutée ou que le modèle a parlé.
Fournissez un historique et du contexte
Utilisez l’historique fourni au démarrage pour reprendre un sujet, puis ajoutez du contexte pertinent au fil de la conversation. Séparez les instructions fiables de l’application des messages utilisateur et des résultats factuels.
Initialisez une session avec une conversation antérieure
Incluez les messages texte antérieurs dans session.input lors de la création de la session. Par exemple, ajoutez ce champ input à votre configuration de création de session :
export const session = {
model: "gpt-live-1",
input: [
{
type: "message",
role: "user",
content: [
{
type: "input_text",
text: "I need help with my recent order.",
},
],
},
{
type: "message",
role: "assistant",
content: [
{
type: "output_text",
text: "What is the order number?",
},
],
},
],
};La liste accepte jusqu’à 128 messages et 8 192 tokens au total. Les rôles pris en charge sont developer, user et assistant, chacun avec une seule partie textuelle. Les messages du développeur et de l’utilisateur utilisent input_text ; les messages de l’assistant utilisent text ou output_text. Placez les instructions fiables de l’application dans instructions ou dans un message du développeur. La liste n’accepte pas le rôle system.
Sélectionnez l’historique nécessaire à l’interaction suivante. input est un champ de démarrage et ne permet pas de remplacer l’historique pendant une session en cours. Il n’accepte pas non plus tous les types d’éléments d’entrée backend utilisés dans la délégation à Responses.
Comprenez quand le contexte parvient au modèle
L’intégralité du contenu de input fourni à la création de la session est disponible pour le modèle dès le démarrage. Placez dans ce champ le contexte dont le modèle a besoin dès le début.
Pendant une session en cours, les événements session.instructions.append, session.thinking.append et session.commentary.append transmettent progressivement du contenu au modèle. Leurs accusés de réception ne sont émis que lorsque la progression des trames atteint la fin estimée de l’injection du contexte. Les valeurs start_ms et end_ms renvoyées décrivent un intervalle estimé sur la chronologie de la session, et non la fin de la prise de parole ou de la lecture audio. Elles ne prouvent pas que le modèle a traité l’intégralité de la mise à jour. Ne supposez pas que sa prochaine prise de parole tiendra compte de toute la mise à jour.
Si la progression des trames s’arrête, un accusé de réception peut rester en attente. La fermeture de la session signale une erreur pour les ajouts en attente. Associez chaque accusé de réception à l’event_id envoyé à l’aide de client_event_id, et continuez à gérer les erreurs pendant l’attente.
Ajoutez du contexte pendant la conversation
Choisissez un événement selon la façon dont le modèle doit utiliser la mise à jour :
session.instructions.append: ajoutez des instructions fiables de l’application qui influencent le comportement et les propos du modèle.session.thinking.append: ajoutez du contexte factuel sans demander au modèle de l’énoncer immédiatement.session.commentary.append: fournissez des informations que le modèle doit énoncer à voix haute, et qu’il peut reformuler.
Chaque événement reçoit un champ content sous forme de chaîne de caractères simple de 500 tokens maximum, ainsi qu’un champ delegation_id obligatoire. Utilisez null pour le contexte qui s’applique à toute la session. Par exemple, envoyez ceci après que votre application a vérifié l’accord de l’utilisateur et lancé la recherche :
export function sendUpdate(connection) {
connection.send({
type: "session.thinking.append",
event_id: "context_1",
delegation_id: null,
content:
"The user has already accepted the terms. The account lookup is still running.",
});
}Attendez session.thinking.appended avec client_event_id: "context_1", ou gérez l’erreur éventuelle. L’accusé de réception confirme que le contexte a été accepté. Il ne confirme ni une prise de parole, ni la lecture audio, ni l’achèvement d’une action externe.
Le contexte fourni sans demande de prise de parole peut influencer les propos ultérieurs ; il n’offre aucune garantie de confidentialité. N’incluez dans aucun de ces trois événements des identifiants de connexion, des secrets ou du texte que le modèle ne doit jamais révéler. Utilisez l’événement d’instructions pour transmettre les comportements définis par l’application, et non des sorties d’outils non fiables. Faites respecter les autorisations et les confirmations requises dans votre application.
Pour la navigation entre les pages, les sélections et les autres changements de l’interface, consultez Partagez le contexte de l’interface afin d’envoyer des mises à jour concises qui aident GPT-Live à comprendre à quoi l’utilisateur fait référence.
Pour les résultats liés à une tâche backend, utilisez un identifiant de délégation client connu et suivez les indications de Envoyez le bon type de mise à jour. Cet identifiant n’est ni un identifiant de réponse Responses ni un identifiant d’appel d’outil.
Utilisez des instructions pour orienter la conversation lorsqu’un contrôle de l’application se déclenche. Votre serveur peut surveiller les événements et envoyer ces corrections par une connexion WebSocket auxiliaire rattachée à la session existante, ou par sa connexion WebSocket principale. Consultez Appliquez des garde-fous à la conversation pour en savoir plus sur les contrôles simultanés, le blocage des actions et le contrôle de la lecture audio.
Créez l’interface de conversation
Affichez les transcriptions et l’état du microphone indépendamment de l’avancement des traitements du backend. La réception du texte de l’assistant ne vous indique pas quelle portion de l’audio l’utilisateur a entendue.
Fragments de transcription
Écoutez les événements session.input_transcript.delta pour les paroles de l’utilisateur et session.output_transcript.delta pour celles de l’assistant. Chaque événement contient un fragment de texte et l’intervalle correspondant sur la chronologie de la session :
{
"type": "session.input_transcript.delta",
"event_id": "event_transcript_1",
"delta": "What is",
"start_ms": 1000,
"end_ms": 1200
}
Ajoutez les fragments dans l’ordre pour chaque interlocuteur, en conservant start_ms et end_ms. Ces valeurs sont exprimées en millisecondes sur la chronologie de la session, avec des intervalles dont le début est inclus et la fin exclue. Elles ne correspondent ni à des horodatages absolus, ni aux heures d’arrivée des paquets, ni à un alignement exact des mots.
Seuls les intervalles contenant du texte de transcription produisent des événements, et leur acheminement par le réseau peut être irrégulier. Ne déduisez pas un silence de l’absence d’événement et ne considérez pas un fragment comme un tour de parole complet de l’utilisateur. Les fragments de transcription n’ont pas d’identifiant d’élément ni d’événement confirmant la fin d’un tour de parole.
Le traitement des fragments de transcription est facultatif. Vous pouvez les utiliser pour mettre à jour votre interface, effectuer des vérifications ou commencer un traitement de manière anticipée pendant que la conversation se poursuit. Pour des vérifications légères, envisagez un petit modèle tel que gpt-5.6-luna avec un faible effort de raisonnement. Consultez Réagissez aux fragments de transcription pour obtenir des exemples et des conseils de connexion.
Pour appliquer des garde-fous à la conversation, vérifiez le texte cumulé de l’utilisateur et de l’assistant à mesure qu’il arrive. La transmission des transcriptions ne fournit pas de tampon permettant d’approuver les paroles avant leur lecture. Consultez Contrôlez la lecture si nécessaire.
Si votre interface regroupe le texte en tours de parole, prévoyez de pouvoir réviser ce regroupement. Conservez les fragments d’origine, autorisez le chevauchement des intervalles de l’utilisateur et de l’assistant, et ajustez tout délai de séparation à partir de conversations enregistrées. Une brève marque d’acquiescement de l’autre interlocuteur peut faire partie d’un échange en cours. Le regroupement des fragments ne doit pas, à lui seul, déclencher l’exécution d’outils ou annuler des traitements du backend.
Distinguez les repères temporels de la transcription de la lecture audio. Les événements WebSocket session.output_audio.delta ne comportent aucun champ temporel et ne sont accompagnés d’aucun événement signalant la fin de l’audio de sortie ; WebRTC transmet l’audio via sa piste média. Consultez Connexions pour la gestion de l’audio.
Affichez les sous-titres
Créez des lignes de sous-titres qui peuvent s’enrichir pendant que les deux interlocuteurs parlent :
- Préservez le texte. Stockez les valeurs d’origine de
delta,start_msetend_mspour chaque interlocuteur. Concaténez le texte exactement tel qu’il est reçu, y compris les espaces et les mots répétés. Ne supprimez pas les espaces en début ou en fin de fragment et n’en insérez pas entre les fragments. - Mettez à jour le texte de chaque interlocuteur indépendamment. Permettez aux lignes de l’utilisateur et de l’assistant de s’enrichir lorsque leurs paroles se chevauchent. Gardez le texte précédent de l’assistant visible après une interruption et commencez une nouvelle ligne lorsqu’il reprend la parole.
- Gardez les lignes stables. Attribuez des identifiants d’affichage dans votre application et préservez l’ordre des lignes à mesure que le texte s’enrichit. Ne déduisez pas l’identité d’une ligne d’un texte changeant ou d’un horodatage de fin, et ne déplacez pas une ligne en bas de l’affichage chaque fois qu’elle reçoit un fragment.
- Révisez le regroupement pour les fragments tardifs. Utilisez les horodatages de transcription pour regrouper les fragments temporellement proches d’un même interlocuteur. Permettez au texte tardif de mettre à jour des lignes antérieures et révisez l’affectation des fragments tout en conservant les originaux. Ces groupes d’affichage ne constituent pas des tours de parole complets sur le plan sémantique ; tout seuil de séparation relève d’un choix de l’application qui doit être testé.
- Laissez le lecteur contrôler le défilement. Suivez le nouveau texte tant que le lecteur se trouve en bas de l’affichage. Suspendez le défilement automatique lorsqu’il remonte et prévoyez un moyen de revenir aux derniers sous-titres.
- Affichez l’avancement des outils dans une zone d’état. Utilisez les événements de transcription de l’assistant pour sous-titrer ses paroles. Affichez l’activité des outils et les résultats du backend en dehors des sous-titres ; recevoir un résultat ne signifie pas que l’assistant l’a énoncé.
Testez l’affichage avec des paroles qui se chevauchent, de brèves marques d’acquiescement, des interruptions, de longues pauses et des situations de traduction où le texte des deux interlocuteurs arrive à des rythmes différents.
Contrôlez l’entrée du microphone
Envoyez session.input_audio.mute pour couper l’entrée audio sans mettre fin à la session :
export function sendUpdate(connection) {
connection.send({
type: "session.input_audio.mute",
event_id: "mute_1",
});
}Attendez session.input_audio.muted avec client_event_id: "mute_1" avant de considérer la commande comme acceptée. Pour rétablir l’entrée audio, envoyez session.input_audio.unmute et attendez session.input_audio.unmuted. Gérez les erreurs pour chacune des deux commandes.
Couper l’entrée audio n’arrête ni l’inférence, ni les traitements délégués, ni la parole générée. Contrôlez séparément la capture du microphone et la lecture audio dans votre application lorsque ces commandes sont nécessaires.
Saluez l’appelant avant qu’il ne parle
Pour demander un message d’accueil après session.started :
- Envoyez un seul nouvel événement
session.instructions.appendavecdelegation_id: null. Incluez le message d’accueil, sa langue et une instruction explicite demandant de saluer immédiatement l’appelant sans attendre qu’il parle, puis de marquer une pause et d’écouter. Conservez les instructions de démarrage existantes. - Attendez
session.instructions.appendeden vérifiant que sonclient_event_idcorrespond à votre commande. Gérez tout rejet de la commande avant de continuer. - Maintenez le flux audio d’entrée actif, y compris le silence avant que l’appelant ne parle. Avec WebSocket, continuez à envoyer
session.input_audio.append; avec WebRTC, gardez la piste audio d’entrée négociée active. Surveillez la transcription et l’audio de sortie pour détecter le message d’accueil.
Utilisez la langue spécifiée par votre application jusqu’à ce que l’appelant parle ; ne la déduisez pas d’un nom, d’un numéro de téléphone ou d’un lieu. Consultez Conception de prompts pour les modèles vocaux pour concevoir vos prompts.
Si le message d’accueil doit respecter les instructions de l’application, envoyez ces instructions avec session.instructions.append, puis utilisez un court message session.commentary.append pour inviter l’assistant à commencer. Par exemple : “Begin the conversation now, following the instructions provided.” Maintenez le flux audio d’entrée actif, y compris le silence avant que l’appelant ne parle.
Les instructions demandent un message d’accueil ; elles ne garantissent ni une formulation exacte ni une lecture sans interruption. L’API n’émet aucun événement signalant la fin du message d’accueil, et un accusé de réception ne signifie pas que ce message a été entendu. Utilisez une lecture contrôlée par l’application si l’audio doit respecter le texte mot pour mot. Testez votre message d’accueil avec les langues et les interruptions prises en charge par votre application.
Diffusez un message d’information
Utilisez session.instructions.append pour demander une formulation précise à prononcer dans un message d’information. session.commentary.append peut reformuler le texte. Après session.started, envoyez par exemple :
export function sendUpdate(connection) {
connection.send({
type: "session.instructions.append",
event_id: "disclosure_1",
delegation_id: null,
content:
"Immediately say the following disclosure exactly and in full before responding to the caller: This call may be recorded for quality and training purposes.",
});
}Maintenez le flux audio d’entrée actif comme décrit dans Saluez l’appelant avant qu’il ne parle. Choisissez soigneusement le moment de la diffusion : une instruction envoyée pendant la conversation peut interrompre une prise de parole en cours.
Cette demande précise la formulation souhaitée ; elle ne garantit pas une restitution exacte. Vérifiez l’intégralité du message d’information prononcé et sa lecture effective avant de le marquer comme diffusé. session.instructions.appended confirme uniquement que l’instruction a été acceptée. Si une restitution audio exacte est requise, lisez un enregistrement vérifié ou un clip audio préalablement produit dans votre application et contrôlez la sortie de GPT-Live pendant sa lecture. Consultez Contrôlez la lecture si nécessaire.
Gérez les conversations longues
GPT-Live gère automatiquement le contexte lors des conversations longues ; aucun paramètre de configuration n’est nécessaire. Les instructions que vous fournissez au début de la session sont conservées tout au long du compactage. Vous n’avez pas besoin de les renvoyer.
La fenêtre de contexte par défaut contient 128 000 tokens, comprenant vos instructions, le texte de la conversation et les tokens audio qui n’apparaissent pas dans la transcription.
GPT-Live résume les parties anciennes de l’historique de conversation en arrière-plan. Lorsque l’utilisation du contexte dépasse 90 %, il démarre un moteur vocal de remplacement au sein de la même session. Ce moteur reçoit vos instructions d’origine et jusqu’à 8 192 tokens d’historique de conversation, comprenant les messages récents et, lorsqu’il est disponible, un résumé des messages plus anciens. La préparation d’un résumé ne modifie pas immédiatement le contexte du moteur en cours d’exécution.
Les détails plus anciens de la conversation peuvent être résumés ou omis. Conservez les faits importants, les actions confirmées et l’état actuel de la tâche dans votre application, et fournissez le contexte pertinent lorsque c’est nécessaire.
Stockez et forkez une session
Définissez store sur true dans la configuration de la session lors de sa création pour sauvegarder un enregistrement qui pourra être téléchargé ou servir à créer un fork ultérieurement. Le stockage est défini sur false par défaut et doit être activé pour votre projet. Les téléchargements et les forks nécessitent un enregistrement stocké et finalisé, ainsi qu’une politique de données autorisant leur conservation. Les enregistrements expirent après 30 jours. Avec la politique de non-conservation des données, store est traité comme false, et le téléchargement d’enregistrements ainsi que les forks ne sont pas disponibles. Consultez Contrôles des données de GPT-Live.
Par exemple, ajoutez ce champ à l’objet session dans votre événement WebSocket session.start ou dans votre requête de création WebRTC :
{
"store": true
}
Sauvegardez l’identifiant de la session source fourni par session.started ou par la réponse de création WebRTC. Un fork démarre une nouvelle session avec un nouvel identifiant à partir de l’état stocké de la session. Il ne rouvre pas la connexion d’origine et ne réutilise pas l’identifiant de la session source.
Démarrez le fork via le transport utilisé par votre application :
| Transport | Démarrage du fork |
|---|---|
| WebSocket | Connectez-vous à wss://api.openai.com/v1/live/sessions/{source_session_id}/fork. |
| WebRTC | Envoyez une nouvelle offre SDP à POST /v1/live/sessions/{source_session_id}/fork. Appliquez la réponse transport.sdp renvoyée à la nouvelle connexion pair à pair. |
Un fork hérite de la configuration stockée de la session, sous réserve des règles de transport ci-dessous. Pour un fork WebSocket, envoyez session.start avec un objet session obligatoire ; {} ne remplace aucun paramètre. Ne fournissez pas de nouveau modèle et ne répétez pas les instructions ou les données d’entrée d’origine. Vous pouvez remplacer store, les paramètres de délégation Responses et le format audio de la nouvelle connexion WebSocket. Les forks WebRTC permettent de remplacer store, les paramètres de délégation Responses et les autorisations du client frontend. Si vous omettez store lors de la création d’un fork, celui-ci hérite du paramètre de la session source.
Un fork WebSocket n’hérite pas du format audio source : définissez audio.format explicitement ou utilisez le format par défaut PCM16 à 24 kHz. Il supprime également les autorisations héritées du canal de données du frontend. Les forks WebRTC négocient leur format audio et rejettent audio.format ; ils conservent les paramètres d’autorisation du frontend, sauf si vous les remplacez.
Attendez session.started avant d’envoyer d’autres commandes WebSocket. Avec WebRTC, la session démarre via la requête HTTP et ne doit pas recevoir de second événement session.start sur son canal de données.
Démarrez un fork WebSocket
Définissez OPENAI_API_KEY. Les exemples utilisent l’identifiant de la session source stockée, sauvegardé par votre application. Ils confirment le démarrage, puis ferment le fork. Pour poursuivre la conversation, envoyez et recevez de l’audio après session.started en suivant la procédure de connexion WebSocket. Consultez la référence des forks WebSocket pour connaître les champs et les événements de démarrage.
import OpenAI from "openai";
import { ForksWS } from "openai/resources/live/forks/ws";
async function forkSession(sourceSessionId) {
const ws = new ForksWS(new OpenAI(), { session_id: sourceSessionId });
let finalized = false;
try {
for await (const event of ws) {
if (event.type === "open") {
ws.send({ type: "session.start", session: {} });
} else if (event.type === "error") {
throw event.error;
} else if (event.type === "message") {
if (event.message.type === "session.started") {
console.log("Fork ready:", event.message.session.id);
// This startup example closes the fork after confirming it is ready.
ws.send({ type: "session.close" });
} else if (event.message.type === "session.closed") {
console.log("Final usage:", event.message.usage);
finalized = true;
break;
}
}
}
if (!finalized) throw new Error("Connection closed before session.closed");
} finally {
ws.close();
}
}Démarrez un fork WebRTC
Créez une nouvelle offre SDP dans votre frontend et envoyez-la à votre backend. Les exemples de backend suivants utilisent cette offre et l’identifiant de la session source stockée provenant de votre application :
import OpenAI from "openai";
async function forkSession(sourceSessionId, offerSdp) {
const client = new OpenAI();
const fork = await client.live.sessions.fork(sourceSessionId, {
transport: { type: "webrtc", sdp: offerSdp },
});
console.log(JSON.stringify(fork));
}Renvoyez la réponse à votre frontend, appliquez transport.sdp comme réponse de la nouvelle connexion pair à pair et conservez le nouvel identifiant session.id. Gardez la clé API sur votre backend.
Utilisez le nouvel identifiant de session pour les connexions hors bande et les commandes de session ultérieures. Conservez séparément l’état des tâches de l’application : restaurer l’état de la conversation ne confirme pas qu’une action en attente côté backend a abouti. Vérifiez les résultats incertains avant de réessayer une action. Si vous n’avez pas de session stockée à forker, initialisez une nouvelle session avec l’historique sauvegardé.
Télécharger un enregistrement
Une fois l’enregistrement stocké finalisé, téléchargez son audio avec GET /v1/live/sessions/{session_id}/content. La réponse contient des données binaires au format WAV stéréo, avec l’audio d’entrée sur le canal gauche et l’audio de sortie sur le canal droit. Les exemples utilisent l’identifiant de session stocké par votre application et écrivent la réponse en continu dans recording.wav :
import OpenAI from "openai";
import { createWriteStream } from "node:fs";
import { pipeline } from "node:stream/promises";
async function downloadRecording(sessionId) {
const client = new OpenAI();
const response = await client.live.sessions.downloadRecording(sessionId);
if (!response.body) throw new Error("Recording response has no body");
await pipeline(response.body, createWriteStream("recording.wav"));
}Gérer les erreurs et terminer la session
Continuez à lire les événements de session jusqu’à sa finalisation. Distinguez une commande rejetée, une connexion défaillante et une session terminée afin que votre application puisse réagir de manière appropriée.
Gérer les commandes rejetées
Lisez les événements error en parallèle des accusés de réception. Lorsqu’il est présent, error.client_event_id identifie la commande envoyée qui a échoué :
{
"type": "error",
"event_id": "event_error",
"error": {
"type": "invalid_request_error",
"code": "immutable_field_update",
"message": "The delegation type cannot change after session startup.",
"param": "session.delegation.type",
"client_event_id": "event_update"
}
}
Un code d’erreur peut valoir null, et une erreur peut ne pas comporter d’identifiant d’événement client. Gérez ces cas sans supposer qu’une commande a réussi. En cas d’erreur liée à un champ immuable, conservez la configuration actuelle ou créez une nouvelle session avec les paramètres souhaités.
Gérer la modération
La modération peut affecter la session de deux manières :
- Certains événements de modération mettent fin à la session.
- D’autres coupent l’audio de l’assistant pour le reste de sa prise de parole en cours et émettent un événement
errorsans mettre fin à la session.
Lisez les événements error même pendant la lecture audio. Ne supposez pas que chaque erreur de modération ferme la session, ni qu’une interruption audio signifie que la connexion a échoué. Maintenez l’état de l’application en accord avec le cycle de vie de la session et ne marquez pas un message vocal interrompu comme entièrement diffusé. Les garde-fous de conversation mis en place dans l’application restent distincts de ce mécanisme de modération intégré.
Utilisation et fermeture propre
session.usage.updated indique la durée vocale cumulée en secondes :
{
"type": "session.usage.updated",
"event_id": "event_usage_1",
"usage": { "seconds": 12 },
"context_window": { "usage_ratio": 0.42 }
}
Ces valeurs sont des instantanés, pas des incréments à additionner. La consommation de tokens côté backend est comptabilisée séparément ; conservez les données correspondantes issues des événements de fin de réponse Responses imbriqués. Consultez Optimisation des coûts pour en savoir plus sur la comptabilisation de l’utilisation.
Pour fermer la session proprement :
- Terminez toutes les tâches déléguées à Responses dont votre application a besoin, y compris les résultats de fonction en attente et les continuations de réponse.
- Enregistrez le gestionnaire de l’événement
session.closedavant d’envoyersession.close. - Envoyez
session.closeet cessez de soumettre de nouvelles tâches à la session. Maintenez actifs la connexion WebSocket ou WebRTC, le canal de données et tout récepteur hors bande associé jusqu’à ce que tous les événements de session en attente aient été reçus. - Lisez les valeurs finales de
usage.secondsetreason, ainsi que l’instantané de la session, danssession.closed. Conservez les données d’utilisation des tâches déléguées déjà reçues viaresponse.event. - Après cet événement, libérez les ressources de transport et les périphériques audio. Si la finalisation échoue ou dépasse le délai d’attente défini par votre application, signalez que la finalisation est incomplète et libérez les ressources.
L’envoi de session.close annule les requêtes Responses en file d’attente et entraîne le rejet des commandes suivantes. Une réponse active peut se terminer, mais une réponse en attente d’un résultat de fonction ne peut plus se poursuivre une fois la fermeture commencée. Décidez séparément de terminer ou d’annuler les tâches que votre application exécute par délégation côté client.
L’événement session.closed confirme la finalisation ; la session qu’il contient est un instantané de la configuration. La fermeture du socket ne suffit pas à confirmer la réussite, et un code de fermeture du transport reçu après un événement final valide n’invalide pas la finalisation. Fermer WebRTC immédiatement après l’envoi de la commande peut empêcher la réception de l’événement final.
Le champ reason de l’événement final explique pourquoi la session s’est terminée :
| Motif | Signification |
|---|---|
close_requested | Votre application a envoyé session.close ou appelé le point de terminaison de raccrochage. |
expired | La session a atteint sa durée limite. |
content | Un filtre de sécurité a mis fin à la session. |
remote_hangup | La connexion principale distante s’est fermée proprement. |
connection_lost | La connexion principale ou en amont a été perdue de manière inattendue. |
Un événement session.closed confirme la finalisation même lorsque la session s’est terminée en raison d’une perte de connexion ou pour des raisons de sécurité. Sans cet événement, les données d’utilisation finales restent non confirmées. La finalisation d’une session stockée peut prendre plus de temps pendant la sauvegarde de son enregistrement ; choisissez un délai d’attente qui tient compte du stockage dans votre application.
Reprendre après une défaillance de connexion
Une erreur HTTP lors de la création de la session signifie que celle-ci n’a pas atteint l’étape session.started. Gérez les erreurs de démarrage séparément des erreurs survenant dans une session en cours. Si une connexion active échoue avant session.closed, conservez les dernières données d’utilisation observées et marquez les données d’utilisation finales comme non confirmées.
Si une session stockée est disponible, forkez-la pour démarrer une nouvelle session à partir de son état sauvegardé. Sinon, créez une session de remplacement avec les éléments pertinents de l’historique sauvegardé. Vérifiez l’état des actions en attente auprès de votre backend avant de les réessayer et écartez les résultats obsolètes de la session précédente. Restaurez explicitement l’état de l’application au lieu de supposer qu’une nouvelle connexion reprend la session précédente ou ses tâches en attente.