Ga naar hoofdinhoud

GPT-Realtime-2 API-tutorial: drie tests, drie oordelen

Leer hoe OpenAI's gpt-realtime-2, gpt-realtime-translate en gpt-realtime-whisper van elkaar verschillen en test elk model met werkende Python WebSocket-code.
Bijgewerkt 12 mei 2026  · 10 min lezen

Ons overzichtsartikel over GPT-Realtime-2 besprak de lancering, de benchmark-claims en waarom OpenAI realtime spraak heeft opgesplitst in een kleine modelfamilie. Deze tutorial pakt de draad op waar dat artikel stopte: verbinden met de API, audio versturen en zien wat er in de code verandert.

De splitsing is in de praktijk belangrijk. Test 1 gebruikt gpt-realtime-whisper voor transcriptie, Test 2 gebruikt gpt-realtime-translate voor livevertaling en Test 3 gebruikt gpt-realtime-2 voor een stemassistent. Het hoofdmodel werkt ook voor eenvoudigere taken zoals vertalen of transcriberen, maar je betaalt dan voor een niveau van redeneren en antwoorden dat niet nodig is, dus dat is overkill.

De GPT-Realtime-2 API instellen in Python

Voor de tests is het handig om transport, authenticatie en audioformaat te scheiden. Die details blijven grotendeels gelijk in de voorbeelden. De model-endpoints en eventnamen zijn wat verandert wanneer het artikel van tekstoutput naar vertaalde spraak en vervolgens naar een volledige spraaklus gaat.

Kiezen tussen WebRTC en WebSocket

De OpenAI-docs geven één simpele regel: gebruik WebRTC voor browser- en mobiele clients, en gebruik WebSockets voor server-side applicaties. WebRTC handelt jitterbuffering en audiotransport af. WebSockets zijn logisch wanneer de backend al ruwe audio ontvangt van een telefonieprovider of mediapipeline.

Diagram waarin een browserclient via WebRTC verbinding maakt met de OpenAI Realtime API en een Python-server via WebSocket, met annotaties over authenticatievereisten voor elk pad.

Twee transportpaden voor de Realtime API. Afbeelding door de auteur.

Om die reden gebruiken alle drie de Python-tests WebSockets. Dat pad laat de eventnamen direct zien, zodat de modelverschillen zichtbaar zijn in de code. Voor een browserbuild gebruik je tijdelijke client secrets zodat je API-sleutel nooit de frontend bereikt.

Python-omgeving en -packages

Gebruik Python 3.9 of nieuwer. De volledige code voor alle vier de scripts is beschikbaar op github.com/KhalidAbdelaty/gpt-realtime-api. Clone het eerst en installeer daarna de dependencies:

git clone https://github.com/KhalidAbdelaty/gpt-realtime-api.git
cd gpt-realtime-api
pip install websocket-client sounddevice numpy python-dotenv

websocket-client verzorgt de socket. sounddevice neemt microfoonaudio op, numpy converteert de buffer en python-dotenv laadt de API-sleutel. Op macOS heb je mogelijk brew install portaudio nodig voordat sounddevice werkt. Op Linux installeer je portaudio19-dev.

Maak een .env-bestand in de root van je project:

OPENAI_API_KEY=sk-...

Laad het vervolgens in elk script:

import os
from dotenv import load_dotenv

load_dotenv()
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")

Authenticatie en de WebSocket-URL

Server-side verbindingen gebruiken een Authorization: Bearer-header bij de WebSocket-handshake. Voeg OpenAI-Safety-Identifier toe als de app individuele gebruikers volgt. Dit zijn de paden die later in de tests worden gebruikt:

# Voice agent
wss://api.openai.com/v1/realtime?model=gpt-realtime-2

# Translation
wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate

# Transcription
wss://api.openai.com/v1/realtime?intent=transcription

Dat vertaalpad is later in Test 2 belangrijk, omdat het het enige endpoint is dat niet direct /v1/realtime gebruikt.

Test 1: Realtime audiotranscriptie met GPT-Realtime-Whisper

Transcriptie is een veelvoorkomende plek om te over-engineeren. Als de output alleen tekst is, is het transcriptiemodel voldoende.

Wat we testen

gpt-realtime-whisper neemt audio aan en geeft transcript-delta’s uit. Het redeneert niet, roept geen tools aan en spreekt niet terug. Die kleinere taak is de reden dat het wordt afgerekend op audioduur in plaats van met hetzelfde tokenmodel dat door gpt-realtime-2 wordt gebruikt. De kosten komen later terug in beeld.

Code-uitleg

Het sleutelveld is session.type: "transcription". Dat vertelt de API om assistent-antwoorden over te slaan en alleen transcript-events uit te sturen. Het volledige script handelt ook microfoonopname en threading af. Dit is het deel dat het Realtime-sessiegedrag verandert:

session_config = {
    "type": "session.update",
    "session": {
        "type": "transcription",
        "audio": {
            "input": {
                "format": {"type": "audio/pcm", "rate": 24000},
                "transcription": {
                    "model": "gpt-realtime-whisper",
                    "language": "en"
                },
                "turn_detection": None
            }
        }
    }
}

ws.send(json.dumps(session_config))
ws.send(json.dumps({
    "type": "input_audio_buffer.append",
    "audio": audio_b64
}))
ws.send(json.dumps({"type": "input_audio_buffer.commit"}))

Gebruik 24 kHz PCM16 mono-audio, gecodeerd als base64. Anders dan bij de voice-agent-sessie commit het script de inputbuffer handmatig op een timer in plaats van server_vad turndetectie te gebruiken. Lege commits geven input_audio_buffer_commit_empty, daarom commit het volledige script pas nadat er echte audio is verstuurd.

Transcript-delta’s komen woord voor woord in realtime binnen. Afbeelding door de auteur.

Waargenomen gedrag

In mijn lokale tests verschenen transcriptresultaten binnen het commitvenster, ruwweg 3 tot 4 seconden nadat de spraak begon. Omdat deze setup op handmatige commits vertrouwt in plaats van VAD, is de latentie gekoppeld aan het commit-interval. 

Let ook op de volgorde: completion-events van overlappende beurten kunnen buiten volgorde aankomen, dus reconcile op item_id als je een UI rond de stream bouwt.

Eventtijdlijn met continu bufferen van audio, een handmatige commit op een vast interval, transcriptieverwerking en een voltooid transcriptevent.

Transcriptie wordt getriggerd door een periodieke handmatige commit, niet door stilte-detectie. Afbeelding door de auteur.

Oordeel: geslaagd. Voor server-side live transcriptie deed gpt-realtime-whisper wat deze test nodig had. Ik zou nog steeds testen met echte microfoons, accenten en kamerruis voordat ik een latentiedoel stel.

Test 2: Realtime vertaling met GPT-Realtime-Translate

Live spraakvertaling lijkt in eerste instantie op transcriptie, maar de sessielevenstijd is anders. Het vertaal-endpoint haalt de assistent-antwoordlus weg, waardoor het voorbeeld korter is.

Wat we testen

Vertaalsessies hebben geen assistent-beurtlus en geen response.create. Het model werkt als een live tolk, niet als een conversational agent. Voor Q&A, tools of conversatiestatus schakelt het artikel in Test 3 over naar gpt-realtime-2.

Vergelijking naast elkaar van een voice-agent-sessie die verbinding maakt met /v1/realtime met een responslevenscyclus, en een vertaalsessie die verbinding maakt met /v1/realtime/translations met continue audiostreaming en geen response.create-stap.

Vertaalsessies gebruiken een eigen, apart endpoint. Afbeelding door de auteur.

Het model ondersteunt meer dan 70 invoertalen en 13 uitvoertalen. Je stelt het doel in met session.audio.output.language; brontaal-detectie is automatisch. De beperkingen zijn duidelijk: geen aangepaste prompting, geen stemkeuze en geen domeinglossaria.

Code-uitleg

Zoals eerder genoemd gebruikt vertaling de /translations WebSocket-URL. Twee andere details veranderen ook: het doelveld session.audio.output.language en de eventnaam session.input_audio_buffer.append. Let op het voorvoegsel session.. Vertaalsessies gebruiken dat hier.

url = "wss://api.openai.com/v1/realtime/translations?model=gpt-realtime-translate"

session_config = {
    "type": "session.update",
    "session": {
        "audio": {
            "output": {"language": "es"},
            "input": {
                "transcription": {"model": "gpt-realtime-whisper"},
                "noise_reduction": {"type": "near_field"}
            }
        }
    }
}

ws.send(json.dumps(session_config))
ws.send(json.dumps({
    "type": "session.input_audio_buffer.append",
    "audio": audio_b64
}))

Vertaalde audio komt binnen op session.output_audio.delta, en de audiobytes staan in event["delta"], niet in event["audio"]. Het bron- en vertaalde transcript komen apart binnen:

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

Eén randgeval: als de bronaudio al in de doeltaal is, kan het model stilte produceren in plaats van het door te geven.

Waargenomen gedrag

Bij korte Engelse-naar-Spaanse zinnen begon de vertaalde audio voordat de bronuiting klaar was. De terminal liet afwisselende [EN]- en [ES]-regels zien terwijl delta’s binnenstroomden. Meer uiteenlopende taalkoppels kunnen langer wachten op context. Ik kon de vertaalde stem zonder moeite volgen, maar aangepaste stemselectie is niet beschikbaar.

Oordeel: geslaagd, met een kanttekening. gpt-realtime-translate werkte voor directe livevertaling. Het is minder geschikt wanneer terminologiecontrole of stembranding belangrijk is.

Test 3: Een stemassistent bouwen met beurtwisseling en barge-in

Dit is de gpt-realtime-2-test: een stemagent die luistert, spreekt, context behoudt en tools kan aanroepen. Dit is ook het punt waarop de clientcode belangrijker wordt, omdat weergave en beurtstatus uit sync kunnen raken.

Wat we testen

gpt-realtime-2 is een spraak-naar-spraak redeneermodel. Het vermijdt een aparte STT-naar-LLM-naar-TTS-pijplijn, en het 128K-contextvenster geeft langere sessies meer ruimte. Redeneren wordt gestuurd met reasoning.effort; begin bij low tenzij de taak meer redeneren vereist, want hogere instellingen voegen latentie toe.

Code-uitleg

De setup hieronder gebruikt semantic_vad, dat naar spraaksignalen kijkt in plaats van alleen stilte. eagerness bepaalt hoe snel het model besluit dat de gebruiker klaar is. De onderdelen om op te letten zijn de modelnaam, audio-uitvoerinstellingen, handmatige response.create en de eventnaam voor assistentaudio:

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

Wanneer het transcript van de gebruiker is voltooid, creëert de client de assistentrespons. Assistent-audio komt vervolgens binnen als response.output_audio.delta, niet als response.audio.delta.

if event_type == "conversation.item.input_audio_transcription.completed":
    ws.send(json.dumps({"type": "response.create"}))

elif event_type == "response.output_audio.delta":
    audio_out_queue.put(base64.b64decode(event["delta"]))

Barge-in afhandelen

De onderbrekingsvolgorde is makkelijk om fout te doen. Wanneer de gebruiker over de assistent heen praat, stuurt de server input_audio_buffer.speech_started. De client stopt de weergave, registreert hoeveel audio is afgespeeld en stuurt conversation.item.truncate met audio_end_ms om bij te houden waar het werd afgekapt. Anders blijft de server tekst transcriberen die de gebruiker nooit heeft gehoord, en kan de volgende beurt vreemd aanvoelen.

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

Een praktisch probleem met laptopspeakers: de microfoon kan de audio-uitvoer van de assistent oppikken en terugsturen naar het model. Het voorbeeldscript gebruikt MUTE_MIC_DURING_ASSISTANT = True om de invoerstroom te dempen terwijl de assistent spreekt en voor een korte afkoelperiode erna. Zet dit alleen op False als je een koptelefoon gebruikt en onderbrekingsondersteuning wilt.

Sequentiediagram waarin een gebruiker een assistentrespons onderbreekt, de client response.output_audio.delta-chunks ontvangt, de audioweergave stopt, een conversation.item.truncate-event verzendt en de server niet-afgespeelde audio verwijdert voordat een nieuwe respons start.

Truncatie houdt server en client in sync. Afbeelding door de auteur.

WebRTC en SIP handelen meer van deze buffering af. Met het WebSocket-pad dat in deze tutorial wordt gebruikt, ligt die verantwoordelijkheid bij de client. De teller in het voorbeeldscript is genoeg voor een demo; productiecode zou timestamps van de audio-uitvoerstream moeten bijhouden.

Preambles configureren voor redeneerlatentie

Wanneer reasoning.effort boven low staat, valt stilte op. Korte gesproken preambles kun je toevoegen in de systeemprompt:

# Preambles
Use a short spoken update before longer tasks.
Keep preambles under five seconds.
Skip preambles for short factual questions.

Dit gedrag is gedocumenteerd voor gpt-realtime-2.

Waargenomen gedrag

Beurtwisseling werkte met de standaardinstellingen in een stille kamer. Met laptopspeakers had ik mic-demping nodig; zonder dat hoorde het model zijn eigen output en begon een echolus. 

In drukkere ruimtes waren VAD-instellingen en microfoonplaatsing belangrijker. Gespreksgeheugen bleef consistent tijdens een test van tien minuten, maar ik zou geen langere app uitbrengen zonder een herverbindingsplan.

Oordeel: geslaagd voor de kern van de spraaklus. gpt-realtime-2 kon in mijn test een assistent met lage redeneerinspanning aan. Het extra werk ligt bij de client: weergave, onderbrekingsafhandeling, herverbinden en tool-calls als de app die nodig heeft.

Streamlit-demo: alle drie de modellen in één interface

De Streamlit-app zet de tests achter een tabselector. Je kunt audio opnemen, een doeltaal kiezen en modelpaden vergelijken zonder scripts te bewerken. Ik heb dit als demo-app gehouden en niet als het hoofdleerspoor, aangezien de terminalscripts de events directer laten zien.

Drie modellen in één getabde interface. Afbeelding door de auteur.

De demovideo hieronder laat de tabs zien met een live API-sleutel. Elke tab gebruikt echte Realtime WebSocket-calls.

Voer de app uit vanuit dezelfde map als de scripts:

streamlit run demo_app.py

Je API-sleutel gaat in de zijbalk en wordt nergens opgeslagen. Voor een publieke app zet je hem in Streamlit Secrets.

GPT-Realtime-2: kosten en latentie in de praktijk

Zoals genoemd in Test 1, splitst de prijs in twee groepen: gpt-realtime-2 wordt afgerekend per token, terwijl vertaling en transcriptie per minuut worden afgerekend.

Tabel met een vergelijking van afrekenmodellen en huidige prijzen voor gpt-realtime-2, gpt-realtime-translate en gpt-realtime-whisper

Token- en minutenaftrek per model. Afbeelding door de auteur.

Voor transcriptie en vertaling schalen de kosten met de duur. Op het moment van schrijven kost dertig minuten ongeveer $0,51 op gpt-realtime-whisper en ongeveer $1,02 op gpt-realtime-translate.

Stemassistenten zijn lastiger te schatten omdat audiotokens aan beide kanten van het gesprek oplopen. Sessielengte, spreekverhouding, redeneerinspanning en contextgrootte zijn allemaal van belang. Promptcaching kan kosten verlagen wanneer eerdere gespreksslagen stabiel blijven.

Een REST-transcriptiecall plus TTS is een andere vergelijking, tenzij live interactie vereist is. whisper-1 is goedkoper voor bestanden, maar het is niet hetzelfde type API.

GPT-Realtime-2 API-limieten, audiovereisten en troubleshooting

Dit zijn de limieten die mijn eerste testruns beïnvloedden. De meeste fouten kwamen door audio-opmaak of fouten in de sessielevenstijd, niet door het model zelf.

Transport- en audiobeperkingen

Zoals in de eerste test opgemerkt, moet WebSocket-audio PCM16 op 24 kHz, mono en base64-gecodeerd zijn. Elk input_audio_buffer.append-event is begrensd op 15 MB, dus chunks van 50 milliseconden blijven ruim onder de limiet. G.711 wordt ook ondersteund voor telefonie.

Realtime-sessies eindigen na 60 minuten op OpenAI en 30 minuten op Azure OpenAI. Langere apps hebben een herverbindingsplan nodig en een manier om state opnieuw op te bouwen. De stem moet ook vóór de eerste audio-uitvoer worden gekozen; je kunt niet midden in een sessie wisselen.

Ratelimieten en quota

Ratelimieten zijn tier-gebaseerd en project-specifiek. Tier 1 vermeldt momenteel 200 requests per minuut en 40.000 tokens per minuut voor gpt-realtime-2. De gratis tier wordt niet ondersteund.

Veelvoorkomende fouten en scherpe randjes

De fouten die ik het vaakst tegenkwam waren lege buffer-commits en onjuiste audio-opmaak. Let bij stemassistenten ook op feedbacklussen waarbij de microfoon de speakeroutput van de assistent hoort. Gebruik een koptelefoon, echo-onderdrukking of mic-demping.

Voor lange sessies: herverbind rond 55 minuten in plaats van te wachten op verlopen. Een documentatie-rimpel: de modelpagina van gpt-realtime-2 heeft een generieke rij "Streaming: Not supported", terwijl de Realtime-gidsen het gebruik van /v1/realtime documenteren. Die rij gaat over Chat Completions-streaming, niet over het gedrag van de Realtime API.

Eindoordeel

Hetzelfde patroon komt terug in de drie tests: elke taak heeft zijn eigen model en endpoint. Die splitsing beïnvloedt wat het model kan, hoe er wordt afgerekend en hoeveel clientcode je zelf moet beheren.

Zoals hierboven getoond dekt gpt-realtime-whisper live tekst, gpt-realtime-translate directe spraakvertaling en gpt-realtime-2 assistentgedrag met spraak, redeneren en context.

De code laat niet zien dat één model de andere vervangt. Het laat zien dat realtime spraakapps afhangen van sessieontwerp. Mijn startpunt zou het kleinste model zijn dat bij de taak past, met de resterende engineeringsinspanning op audiokwaliteit, beurtwisseling, herverbindingen en clientstate.

Voor meer achtergrond behandelen onze tutorials verwante audio- en realtime API-onderwerpen:


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

Ik ben een data-engineer en communitybouwer die werkt aan datapijplijnen, cloud en AI-tools, en tegelijkertijd praktische, impactvolle tutorials schrijft voor DataCamp en beginnende developers.

Onderwerpen

Leer AI met DataCamp!

Cursus

AI-systemen ontwikkelen met de OpenAI API

3 Hr
21.2K
Maak gebruik van de OpenAI API om je AI-toepassingen klaar te maken voor productie.
Bekijk detailsRight Arrow
Begin met de cursus
Meer zienRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer zienMeer zien