Accéder au contenu principal

Tutoriel API GPT-Realtime-2 : trois tests, trois verdicts

Découvrez les différences entre gpt-realtime-2, gpt-realtime-translate et gpt-realtime-whisper d’OpenAI, puis testez chaque modèle avec du code Python WebSocket prêt à l’emploi.
Actualisé 12 mai 2026  · 10 min lire

Notre article d’introduction à GPT-Realtime-2 présentait le lancement, les benchmarks annoncés et la raison pour laquelle OpenAI a scindé la voix temps réel en une petite famille de modèles. Ce tutoriel reprend là où l’article s’arrêtait : se connecter à l’API, envoyer de l’audio et voir ce qui change côté code.

\n

Cette séparation a un vrai impact pratique. Le test 1 utilise gpt-realtime-whisper pour la transcription, le test 2 utilise gpt-realtime-translate pour la traduction en direct, et le test 3 utilise gpt-realtime-2 pour un assistant vocal. Le modèle principal peut aussi gérer des tâches plus simples comme la traduction ou la transcription, mais vous paieriez pour un niveau de raisonnement et des modes de réponse non nécessaires : ce serait disproportionné.

\n

Configuration de l’API GPT-Realtime-2 en Python

\n

Avant les tests, il est utile de séparer le transport, l’authentification et le format audio. Ces détails restent globalement identiques d’un exemple à l’autre. Les différences portent sur les endpoints de modèle et les noms d’événements, au fil du passage d’une sortie texte à une parole traduite, puis à une boucle vocale complète.

\n

Choisir entre WebRTC et WebSocket

\n

La documentation OpenAI donne une règle simple : utilisez WebRTC pour les clients navigateur et mobile, et WebSockets pour les applications côté serveur. WebRTC gère le jitter buffering et le transport audio. Les WebSockets sont pertinents quand le back-end reçoit déjà de l’audio brut d’un fournisseur de téléphonie ou d’une chaîne média.

\n

\"Diagramme

\n

Deux chemins de transport pour l’API Realtime. Image par l’auteur.

\n

Pour cette raison, les trois tests Python utilisent des WebSockets. Ce chemin expose directement les noms d’événements, ce qui rend les différences de modèle visibles dans le code. Pour un build navigateur, utilisez des secrets clients éphémères afin que votre clé API n’atteigne jamais le frontend.

\n

Environnement Python et packages

\n

Utilisez Python 3.9 ou plus récent. Le code complet des quatre scripts est disponible sur github.com/KhalidAbdelaty/gpt-realtime-api. Clonez-le d’abord, puis installez les dépendances :

\n
git clone https://github.com/KhalidAbdelaty/gpt-realtime-api.git\ncd gpt-realtime-api\npip install websocket-client sounddevice numpy python-dotenv
\n

websocket-client gère le socket. sounddevice capture l’audio du micro, numpy convertit le buffer, et python-dotenv charge la clé API. Sur macOS, vous devrez peut-être exécuter brew install portaudio avant que sounddevice ne fonctionne. Sous Linux, installez portaudio19-dev.

\n

Créez un fichier .env à la racine de votre projet :

\n
OPENAI_API_KEY=sk-...
\n

Puis chargez-la dans chaque script :

\n
import os\nfrom dotenv import load_dotenv\n\nload_dotenv()\nOPENAI_API_KEY = os.environ.get(\"OPENAI_API_KEY\")
\n

Authentification et URL WebSocket

\n

Les connexions côté serveur utilisent un en-tête Authorization: Bearer lors du handshake WebSocket. Ajoutez OpenAI-Safety-Identifier si votre application suit des utilisateurs individuels. Voici les chemins utilisés plus loin dans les tests :

\n
# Agent vocal\nwss://api.openai.com/v1/realtime?model=gpt-realtime-2\n\n# Traduction\nwss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate\n\n# Transcription\nwss://api.openai.com/v1/realtime?intent=transcription
\n

Ce chemin de traduction est important dans le test 2, car c’est le seul endpoint qui n’utilise pas directement /v1/realtime.

\n

Test 1 : transcription audio en temps réel avec GPT-Realtime-Whisper

\n

La transcription est un cas classique de surconception. Si la sortie attendue est uniquement du texte, le modèle de transcription suffit.

\n

Ce que nous testons

\n

gpt-realtime-whisper prend de l’audio en entrée et émet des deltas de transcription. Il ne raisonne pas, n’appelle pas d’outils et ne parle pas en retour. Ce périmètre plus restreint explique la facturation à la durée audio, plutôt que le modèle de jetons utilisé par gpt-realtime-2. Nous revenons sur ces tarifs plus loin.

\n

Parcours du code

\n

Le champ clé est session.type: \"transcription\". Il indique à l’API d’ignorer les réponses de l’assistant et d’émettre uniquement des événements de transcription. Le script complet gère aussi la capture micro et le threading. Voici la partie qui modifie le comportement de session Realtime :

\n
session_config = {\n    \"type\": \"session.update\",\n    \"session\": {\n        \"type\": \"transcription\",\n        \"audio\": {\n            \"input\": {\n                \"format\": {\"type\": \"audio/pcm\", \"rate\": 24000},\n                \"transcription\": {\n                    \"model\": \"gpt-realtime-whisper\",\n                    \"language\": \"en\"\n                },\n                \"turn_detection\": None\n            }\n        }\n    }\n}\n\nws.send(json.dumps(session_config))\nws.send(json.dumps({\n    \"type\": \"input_audio_buffer.append\",\n    \"audio\": audio_b64\n}))\nws.send(json.dumps({\"type\": \"input_audio_buffer.commit\"}))
\n

Utilisez de l’audio PCM16 mono à 24 kHz, encodé en base64. Contrairement à la session d’agent vocal, le script valide le buffer d’entrée manuellement à intervalles réguliers au lieu d’utiliser la détection de tours server_vad. Les validations vides lèvent input_audio_buffer_commit_empty, c’est pourquoi le script complet ne valide qu’après l’envoi d’audio réel.

\n

\n

Les deltas de transcription arrivent mot à mot en temps réel. Image par l’auteur.

\n

Comportement observé

\n

Sur mes tests locaux, les résultats de transcription apparaissaient dans la fenêtre de commit, environ 3 à 4 secondes après le début de la prise de parole. Comme cette configuration repose sur des commits manuels plutôt que sur la VAD, la latence dépend de l’intervalle de commit. 

\n

Attention aussi à l’ordre : les événements de complétion issus de tours qui se chevauchent peuvent arriver dans le désordre ; si vous construisez une interface autour du flux, réconciliez-les avec item_id.

\n

\"Chronologie

\n

La transcription est déclenchée par un commit manuel périodique, pas par détection de silence. Image par l’auteur.

\n

Verdict : validé. Pour de la transcription en direct côté serveur, gpt-realtime-whisper a rempli le cahier des charges. Je testerais néanmoins avec de vrais micros, des accents et du bruit ambiant avant de fixer une cible de latence.

\n

Test 2 : traduction en temps réel avec GPT-Realtime-Translate

\n

La traduction vocale en direct ressemble d’abord à la transcription, mais le cycle de session est différent. L’endpoint de traduction supprime la boucle de réponse de l’assistant, ce qui raccourcit l’exemple.

\n

Ce que nous testons

\n

Les sessions de traduction n’ont pas de boucle de tours avec assistant et pas de response.create. Le modèle agit comme un interprète en direct, pas comme un agent conversationnel. Pour du questions-réponses, des outils ou un état de conversation, l’article bascule sur gpt-realtime-2 au test 3.

\n

\"Comparaison

\n

Les sessions de traduction utilisent un endpoint dédié et séparé. Image par l’auteur.

\n

Le modèle prend en charge plus de 70 langues en entrée et 13 langues en sortie. Vous définissez la cible via session.audio.output.language ; la détection de la langue source est automatique. Les limites sont claires : pas de prompt personnalisé, pas de sélection de voix, pas de glossaires métier.

\n

Parcours du code

\n

Comme indiqué plus haut, la traduction utilise l’URL WebSocket /translations. Deux autres détails changent aussi : le champ cible session.audio.output.language et le nom d’événement session.input_audio_buffer.append. Notez le préfixe session.. Les sessions de traduction l’emploient ici.

\n
url = \"wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate\"\n\nsession_config = {\n    \"type\": \"session.update\",\n    \"session\": {\n        \"audio\": {\n            \"output\": {\"language\": \"es\"},\n            \"input\": {\n                \"transcription\": {\"model\": \"gpt-realtime-whisper\"},\n                \"noise_reduction\": {\"type\": \"near_field\"}\n            }\n        }\n    }\n}\n\nws.send(json.dumps(session_config))\nws.send(json.dumps({\n    \"type\": \"session.input_audio_buffer.append\",\n    \"audio\": audio_b64\n}))
\n

L’audio traduit arrive via session.output_audio.delta, et les octets audio se trouvent dans event[\"delta\"], pas event[\"audio\"]. Les transcriptions source et traduite arrivent séparément :

\n
if event_type == \"session.output_audio.delta\":\n    audio_out_queue.put(base64.b64decode(event[\"delta\"]))\nelif event_type == \"session.input_transcript.delta\":\n    print(\"[EN]\", event.get(\"delta\", \"\"), end=\"\")\nelif event_type == \"session.output_transcript.delta\":\n    print(\"[ES]\", event.get(\"delta\", \"\"), end=\"\")
\n

Un cas limite : si l’audio source est déjà dans la langue cible, le modèle peut produire du silence plutôt que de le laisser passer tel quel.

\n

Comportement observé

\n

Pour de courtes phrases anglais → espagnol, l’audio traduit commençait avant la fin de l’énoncé source. Le terminal affichait des lignes [EN] et [ES] entrelacées au fil des deltas. Des paires de langues plus éloignées peuvent attendre davantage de contexte. Je pouvais suivre la voix traduite sans difficulté, mais la sélection de voix personnalisée n’est pas disponible.

\n

Verdict : validé, avec réserve. gpt-realtime-translate fonctionne pour la traduction directe en live. Il est moins indiqué quand le contrôle terminologique ou l’identité vocale sont essentiels.

\n

Test 3 : construire un assistant vocal avec tours de parole et interruption

\n

C’est le test gpt-realtime-2 : un agent vocal qui écoute, parle, conserve le contexte et peut appeler des outils. C’est aussi le point où le code client compte davantage, car la lecture et l’état des tours peuvent se désynchroniser.

\n

Ce que nous testons

\n

gpt-realtime-2 est un modèle de raisonnement de parole à parole. Il évite une chaîne STT → LLM → TTS séparée, et sa fenêtre de contexte de 128K offre plus d’aisance aux longues sessions. Le raisonnement se règle via reasoning.effort ; commencez à low sauf si la tâche exige plus, car des réglages plus élevés ajoutent de la latence.

\n

Parcours du code

\n

La configuration ci-dessous utilise semantic_vad, qui s’appuie sur des indices de parole plutôt que sur le simple silence. eagerness contrôle la vitesse à laquelle le modèle décide que l’utilisateur a fini. À noter : le nom du modèle, les paramètres de sortie audio, le response.create manuel et le nom de l’événement audio de l’assistant :

\n
session_config = {\n    \"type\": \"session.update\",\n    \"session\": {\n        \"type\": \"realtime\",\n        \"model\": \"gpt-realtime-2\",\n        \"output_modalities\": [\"audio\"],\n        \"audio\": {\n            \"input\": {\n                \"format\": {\"type\": \"audio/pcm\", \"rate\": 24000},\n                \"transcription\": {\"model\": \"gpt-realtime-whisper\", \"language\": \"en\"},\n                \"turn_detection\": {\n                    \"type\": \"semantic_vad\",\n                    \"eagerness\": \"medium\",\n                    \"create_response\": False,\n                    \"interrupt_response\": True\n                }\n            },\n            \"output\": {\n                \"format\": {\"type\": \"audio/pcm\", \"rate\": 24000},\n                \"voice\": \"marin\"\n            }\n        },\n        \"instructions\": \"You are a helpful voice assistant. Keep answers short.\",\n        \"reasoning\": {\"effort\": \"low\"}\n    }\n}
\n

Quand la transcription de l’utilisateur se termine, le client crée la réponse de l’assistant. L’audio de l’assistant arrive ensuite via response.output_audio.delta, et non response.audio.delta.

\n
if event_type == \"conversation.item.input_audio_transcription.completed\":\n    ws.send(json.dumps({\"type\": \"response.create\"}))\n\nelif event_type == \"response.output_audio.delta\":\n    audio_out_queue.put(base64.b64decode(event[\"delta\"]))
\n

Gérer l’interruption (barge-in)

\n

La séquence d’interruption est facile à rater. Quand l’utilisateur parle par-dessus l’assistant, le serveur envoie input_audio_buffer.speech_started. Le client stoppe la lecture, enregistre la portion déjà jouée, puis envoie conversation.item.truncate avec audio_end_ms pour indiquer où la coupure a eu lieu. Sinon, le serveur continue à transcrire du texte que l’utilisateur n’a jamais entendu, et le tour suivant peut être décalé.

\n
if current_response_item_id and playback_position_ms > 0:\n    ws.send(json.dumps({\n        \"type\": \"conversation.item.truncate\",\n        \"item_id\": current_response_item_id,\n        \"content_index\": 0,\n        \"audio_end_ms\": playback_position_ms\n    }))
\n

Un point pratique avec les haut-parleurs d’ordinateur portable : le micro peut reprendre l’audio de l’assistant et le renvoyer au modèle. Le script d’exemple utilise MUTE_MIC_DURING_ASSISTANT = True pour couper le flux d’entrée pendant que l’assistant parle et un court délai après. Passez-le à False uniquement si vous portez un casque et souhaitez la prise en charge de l’interruption.

\n

\"Diagramme

\n

La troncature maintient la synchronisation serveur-client. Image par l’auteur.

\n

WebRTC et SIP gèrent davantage de buffering. Avec la voie WebSocket utilisée ici, c’est au client de le faire. Le compteur du script suffit pour une démo ; en production, suivez les horodatages du flux de sortie audio.

\n

Configurer des préambules pour la latence de raisonnement

\n

Quand reasoning.effort dépasse low, le silence devient perceptible. Vous pouvez ajouter de courts préambules parlés dans le prompt système :

\n
# Preambles\nUse a short spoken update before longer tasks.\nKeep preambles under five seconds.\nSkip preambles for short factual questions.
\n

Ce comportement est documenté pour gpt-realtime-2.

\n

Comportement observé

\n

La prise de tours a fonctionné avec les réglages par défaut dans une pièce calme. Avec les haut-parleurs du portable, j’ai dû couper le micro ; sans cela, le modèle entendait sa propre sortie et créait une boucle d’écho. 

\n

Dans des pièces plus bruyantes, les réglages VAD et le placement du micro comptaient davantage. La mémoire de conversation est restée cohérente sur un test de dix minutes, mais je ne publierais pas une application plus longue sans plan de reconnexion.

\n

Verdict : validé pour la boucle vocale principale. gpt-realtime-2 a géré un assistant à faible effort de raisonnement dans mon test. Le travail supplémentaire se situe côté client : lecture, gestion des interruptions, reconnexions et appels d’outils si nécessaire.

\n

Démo Streamlit : trois modèles dans une même interface

\n

L’application Streamlit place les tests derrière un sélecteur d’onglets. Elle permet d’enregistrer de l’audio, de choisir une langue cible et de comparer les chemins des modèles sans modifier les scripts. Je l’ai gardée comme application de démo plutôt que fil conducteur principal, car les scripts en terminal montrent plus directement les événements.

\n

\n

Trois modèles dans une interface à onglets. Image par l’auteur.

\n

La vidéo de démonstration ci-dessous montre les onglets avec une clé API active. Chaque onglet utilise de vrais appels Realtime via WebSocket.

Lancez l’application depuis le même dossier que les scripts :

\n
streamlit run demo_app.py
\n

Votre clé API se renseigne dans la barre latérale et n’est stockée nulle part. Pour une application publique, placez-la plutôt dans Streamlit Secrets.

\n

Coût et latence de GPT-Realtime-2 en pratique

\n

Comme mentionné au test 1, la tarification se scinde en deux groupes : gpt-realtime-2 est facturé aux jetons, tandis que traduction et transcription sont facturées à la minute.

\n

\"Tableau

\n

Facturation aux jetons et à la minute selon le modèle. Image par l’auteur.

\n

Pour la transcription et la traduction, le coût évolue avec la durée. Au moment d’écrire ces lignes, trente minutes coûtent environ 0,51 $ sur gpt-realtime-whisper et environ 1,02 $ sur gpt-realtime-translate.

\n

Les agents vocaux sont plus difficiles à estimer car les jetons audio s’accumulent des deux côtés de la conversation. La durée de session, le ratio de parole, l’effort de raisonnement et la taille du contexte comptent tous. Le cache de prompts peut réduire le coût quand les tours précédents restent stables.

\n

Un appel REST de transcription suivi d’un TTS est une autre comparaison, sauf si l’interaction en direct est requise. whisper-1 est moins cher pour les fichiers, mais ce n’est pas le même type d’API.

\n

Limites de l’API GPT-Realtime-2, exigences audio et dépannage

\n

Voici les limites qui ont affecté mes premiers essais. La plupart des échecs venaient du formatage audio ou d’erreurs de cycle de session, pas du modèle lui-même.

\n

Contraintes de transport et d’audio

\n

Comme noté au premier test, l’audio WebSocket doit être en PCM16 à 24 kHz, mono et encodé en base64. Chaque événement input_audio_buffer.append est plafonné à 15 Mo, donc des segments de 50 ms restent largement sous la limite. G.711 est également pris en charge pour la téléphonie.

\n

Les sessions Realtime se terminent après 60 minutes sur OpenAI et 30 minutes sur Azure OpenAI. Les applications plus longues ont besoin d’un plan de reconnexion et d’un moyen de reconstruire l’état. La voix doit aussi être choisie avant la première sortie audio ; elle ne peut pas changer en cours de session.

\n

Limites de débit et quotas

\n

Les limites de débit dépendent du palier et du projet. Le palier 1 indique actuellement 200 requêtes par minute et 40 000 jetons par minute pour gpt-realtime-2. L’offre gratuite n’est pas prise en charge.

\n

Erreurs fréquentes et aspérités

\n

Les erreurs les plus courantes ont été des commits de buffer vides et un mauvais formatage audio. Pour les agents vocaux, surveillez aussi les boucles de rétroaction où le micro capte la sortie des haut-parleurs de l’assistant. Utilisez un casque, l’annulation d’écho ou la coupure du micro.

\n

Pour les longues sessions, reconnectez-vous autour de 55 minutes plutôt que d’attendre l’expiration. Petite ambiguïté de docs : la page modèle gpt-realtime-2 affiche une ligne générique \"Streaming : non pris en charge\", alors que les guides Realtime documentent l’usage de /v1/realtime. Cette ligne concerne le streaming des Chat Completions, pas le comportement de l’API Realtime.

\n

Verdict final

\n

Le même schéma se retrouve dans les trois tests : chaque tâche a son modèle et son endpoint. Cette séparation affecte ce que le modèle peut faire, la facturation et la part de code client à gérer.

\n

Comme montré ci-dessus, gpt-realtime-whisper couvre le texte en direct, gpt-realtime-translate couvre la traduction vocale directe, et gpt-realtime-2 couvre le comportement d’assistant avec parole, raisonnement et contexte.

\n

Le code ne montre pas qu’un modèle remplace les autres. Il montre que les apps vocales temps réel dépendent de la conception de session. Mon point de départ serait le plus petit modèle adapté à la tâche, et je consacrerais le reste du temps d’ingénierie à la qualité audio, la prise de tours, les reconnexions et l’état côté client.

\n

Pour aller plus loin, nos tutoriels couvrent des sujets audio et Realtime connexes :

\n

Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

Je suis ingénieur de données et créateur de communautés. Je travaille sur les pipelines de données, le cloud et les outils d'IA, tout en rédigeant des tutoriels pratiques et percutants pour DataCamp et les développeurs émergents.

Sujets

Apprenez l’IA avec DataCamp !

Cours

Concevoir des systèmes d’IA avec l’API OpenAI

3 h
20.8K
Tirez parti de l'API OpenAI pour préparer vos applications d'IA à la production.
Afficher les détailsRight Arrow
Commencer le cours
Voir plusRight Arrow
Contenus associés

blog

Comprendre les TPU et les GPU dans l'IA : Un guide complet

L'essor du développement de l'intelligence artificielle (IA) a entraîné une augmentation notable de la demande en matière de calcul, d'où la nécessité de disposer de solutions matérielles robustes. Les unités de traitement graphique (GPU) et les unités de traitement tensoriel (TPU) sont devenues des technologies essentielles pour répondre à ces demandes.
Kurtis Pykes 's photo

Kurtis Pykes

9 min

cursor ai code editor

Tutoriel

Cursor AI : Un guide avec 10 exemples pratiques

Apprenez à installer Cursor AI sur Windows, macOS et Linux, et découvrez comment l'utiliser à travers 10 cas d'utilisation différents.

Tutoriel

Données JSON Python : Un guide illustré d'exemples

Apprenez à utiliser JSON en Python, notamment la sérialisation, la désérialisation, le formatage, l'optimisation des performances, la gestion des API, ainsi que les limites et les alternatives de JSON.
Moez Ali's photo

Moez Ali

Tutoriel

Tutoriel Python sur les structures de données

Initiez-vous aux structures de données de Python : apprenez-en plus sur les types de données et les structures de données primitives et non primitives, telles que les chaînes de caractères, les listes, les piles, etc.
Sejal Jaiswal's photo

Sejal Jaiswal

Tutoriel

Tutoriel sur les boucles Python

Tutoriel complet d'introduction aux boucles Python. Apprenez et pratiquez les boucles while et for, les boucles imbriquées, les mots-clés break et continue, la fonction range et bien plus encore.
Satyabrata Pal's photo

Satyabrata Pal

Voir plusVoir plus