Vai al contenuto principale

Tutorial sull'API GPT-Realtime-2: tre test, tre verdetti

Scopri le differenze tra gpt-realtime-2, gpt-realtime-translate e gpt-realtime-whisper di OpenAI, poi mettile alla prova con codice Python WebSocket funzionante.
Aggiornato 12 mag 2026  · 10 min leggi

Il nostro articolo introduttivo su GPT-Realtime-2 ha coperto il lancio, le affermazioni sui benchmark e perché OpenAI ha suddiviso la voce in tempo reale in una piccola famiglia di modelli. Questo tutorial riparte da lì: collegarsi all'API, inviare audio e vedere cosa cambia nel codice.

La suddivisione conta nella pratica. Il Test 1 usa gpt-realtime-whisper per la trascrizione, il Test 2 usa gpt-realtime-translate per la traduzione in diretta e il Test 3 usa gpt-realtime-2 per un assistente vocale. Il modello principale funziona anche per attività più semplici come traduzione o trascrizione, ma pagheresti per un livello di ragionamento e modalità di risposta non necessari: sarebbe eccessivo.

Configurare l'API GPT-Realtime-2 in Python

Prima dei test, è utile separare trasporto, autenticazione e formato audio. Questi dettagli restano quasi sempre uguali negli esempi. Quello che cambia, man mano che si passa dall'output testuale al parlato tradotto e poi a un ciclo vocale completo, sono gli endpoint del modello e i nomi degli eventi.

Scegliere tra WebRTC e WebSocket

La documentazione OpenAI dà una regola semplice: usa WebRTC per client browser e mobile, e usa WebSocket per applicazioni lato server. WebRTC gestisce jitter buffering e trasporto audio. I WebSocket hanno senso quando il backend riceve già audio grezzo da un fornitore di telefonia o da una pipeline multimediale.

Diagramma che mostra un client browser connesso all'API Realtime di OpenAI via WebRTC e un server Python connesso via WebSocket, con annotazioni sui requisiti di autenticazione per ciascun percorso.

Due percorsi di trasporto per la Realtime API. Immagine dell'autore.

Per questo motivo, tutti e tre i test in Python usano i WebSocket. Questo percorso mostra direttamente i nomi degli eventi, così le differenze tra modelli sono visibili nel codice. Per una build browser, usa secret effimeri lato client in modo che la tua chiave API non arrivi mai al frontend.

Ambiente e pacchetti Python

Usa Python 3.9 o versioni successive. Il codice completo per tutti e quattro gli script è disponibile su github.com/KhalidAbdelaty/gpt-realtime-api. Clonalo per primo, poi installa le dipendenze:

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

websocket-client gestisce il socket. sounddevice cattura l'audio del microfono, numpy converte il buffer e python-dotenv carica la chiave API. Su macOS, potresti dover eseguire brew install portaudio prima che sounddevice funzioni. Su Linux, installa portaudio19-dev.

Crea un file .env alla radice del progetto:

OPENAI_API_KEY=sk-...

Poi caricalo in ogni script:

import os
from dotenv import load_dotenv

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

Autenticazione e URL del WebSocket

Le connessioni lato server usano un'intestazione Authorization: Bearer durante l'handshake del WebSocket. Aggiungi OpenAI-Safety-Identifier se l'app traccia utenti individuali. Questi sono i percorsi usati più avanti nei test:

# 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

Quel percorso di traduzione è importante più avanti nel Test 2, perché è l'unico endpoint che non usa direttamente /v1/realtime.

Test 1: Trascrizione audio in tempo reale con GPT-Realtime-Whisper

La trascrizione è un'area in cui è facile complicare troppo. Se l'output è solo testo, il modello di trascrizione è sufficiente.

Cosa stiamo testando

gpt-realtime-whisper riceve audio ed emette delta di trascrizione. Non ragiona, non chiama tool e non risponde a voce. Questo compito più ristretto è anche il motivo per cui viene fatturato in base alla durata dell'audio, invece che con lo stesso modello a token usato da gpt-realtime-2. La sezione sui costi torna su queste tariffe.

Guida al codice

Il campo chiave è session.type: "transcription". Dice all'API di saltare le risposte dell'assistente ed emettere solo eventi di trascrizione. Lo script completo gestisce anche la cattura dal microfono e il threading. Questa è la parte che modifica il comportamento della sessione Realtime:

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"}))

Usa audio PCM16 mono a 24 kHz, codificato in base64. A differenza della sessione dell'agente vocale, lo script esegue il commit del buffer di input manualmente a intervalli, invece di usare il rilevamento dei turni server_vad. I commit vuoti generano input_audio_buffer_commit_empty, motivo per cui lo script completo esegue il commit solo dopo aver inviato audio reale.

I delta di trascrizione arrivano parola per parola in tempo reale. Immagine dell'autore.

Comportamento osservato

Nei test locali, i risultati di trascrizione sono apparsi entro la finestra di commit, circa 3-4 secondi dopo l'inizio del parlato. Poiché questa configurazione si basa su commit manuali invece che sul VAD, la latenza è legata all'intervallo di commit. 

Fai anche attenzione all'ordinamento: gli eventi di completamento da turni sovrapposti possono arrivare fuori ordine, quindi riconcilia tramite item_id se costruisci un'interfaccia intorno allo stream.

Timeline degli eventi che mostra l'audio bufferizzato in continuo, un evento di commit manuale inviato a intervalli fissi, l'elaborazione della trascrizione e un evento di trascrizione completata restituito.

La trascrizione è avviata da un commit manuale periodico, non dal rilevamento del silenzio. Immagine dell'autore.

Verdetto: superato. Per la trascrizione live lato server, gpt-realtime-whisper ha fatto ciò che serviva a questo test. Testerei comunque con microfoni reali, accenti e rumore ambientale prima di fissare un obiettivo di latenza.

Test 2: Traduzione in tempo reale con GPT-Realtime-Translate

La traduzione del parlato dal vivo inizialmente somiglia alla trascrizione, ma il ciclo di vita della sessione è diverso. L'endpoint di traduzione rimuove il loop di risposta dell'assistente, rendendo l'esempio più breve.

Cosa stiamo testando

Le sessioni di traduzione non hanno loop di turni dell'assistente e niente response.create. Il modello funziona come un interprete in diretta, non come un agente conversazionale. Per Q&A, strumenti o stato della conversazione, nell'articolo si passa a gpt-realtime-2 nel Test 3.

Confronto affiancato tra una sessione di agente vocale che si connette a /v1/realtime con un ciclo di risposta e una sessione di traduzione che si connette a /v1/realtime/translations con streaming audio continuo e senza lo step response.create.

Le sessioni di traduzione usano un endpoint dedicato e separato. Immagine dell'autore.

Il modello supporta più di 70 lingue in input e 13 in output. Imposti la lingua di destinazione con session.audio.output.language; il rilevamento della lingua sorgente è automatico. I limiti sono chiari: niente prompt personalizzati, nessuna selezione della voce e nessun glossario di dominio.

Guida al codice

Come detto prima, la traduzione usa l'URL WebSocket /translations. Cambiano anche altri due dettagli: il campo di destinazione session.audio.output.language e il nome dell'evento session.input_audio_buffer.append. Nota il prefisso session.. Le sessioni di traduzione lo usano qui.

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
}))

L'audio tradotto arriva su session.output_audio.delta e i byte audio sono in event["delta"], non in event["audio"]. Le trascrizioni sorgente e tradotta arrivano separatamente:

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="")

Un caso limite: se l'audio sorgente è già nella lingua di destinazione, il modello può produrre silenzio anziché passarlo così com'è.

Comportamento osservato

Per frasi brevi dall'inglese allo spagnolo, l'audio tradotto iniziava prima che l'utterance sorgente finisse. Il terminale mostrava righe [EN] e [ES] intercalate mentre i delta arrivavano in streaming. Coppie linguistiche più distanti possono attendere più a lungo per il contesto. Riuscivo a seguire la voce tradotta senza problemi, ma la selezione personalizzata della voce non è disponibile.

Verdetto: superato, con una riserva. gpt-realtime-translate ha funzionato per la traduzione diretta in tempo reale. È meno utile quando contano il controllo della terminologia o il branding della voce.

Test 3: Creare un assistente vocale con turni e interruzioni

Questo è il test di gpt-realtime-2: un agente vocale che ascolta, parla, mantiene il contesto e può chiamare tool. È anche il punto in cui il codice client inizia a contare di più, perché riproduzione e stato dei turni possono andare fuori sincronia.

Cosa stiamo testando

gpt-realtime-2 è un modello speech-to-speech con capacità di ragionamento. Evita una pipeline separata STT-to-LLM-to-TTS e la sua finestra di contesto da 128K offre più spazio a sessioni lunghe. Il ragionamento è controllato con reasoning.effort; parti da low a meno che l'attività non richieda più ragionamento, perché impostazioni più alte aggiungono latenza.

Guida al codice

La configurazione seguente usa semantic_vad, che osserva indizi del parlato invece del solo silenzio. eagerness controlla la rapidità con cui il modello decide che l'utente ha finito. Le parti da notare sono il nome del modello, le impostazioni dell'output audio, il response.create manuale e il nome dell'evento audio dell'assistente:

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"}
    }
}

Quando la trascrizione dell'utente si completa, il client crea la risposta dell'assistente. L'audio dell'assistente arriva quindi come response.output_audio.delta, non come 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"]))

Gestire le interruzioni (barge-in)

La sequenza di interruzione è facile da sbagliare. Quando l'utente parla sopra l'assistente, il server invia input_audio_buffer.speech_started. Il client interrompe la riproduzione, registra quanta parte di audio è stata riprodotta e invia conversation.item.truncate con audio_end_ms per tenere traccia del punto in cui è stato interrotto. Altrimenti, il server continua a trascrivere testo che l'utente non ha mai sentito e il turno successivo può risultare fuori fase.

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
    }))

Un problema pratico con gli altoparlanti del laptop: il microfono può captare l'audio dell'assistente e rimandarlo al modello. Lo script di esempio usa MUTE_MIC_DURING_ASSISTANT = True per silenziare lo stream di input mentre l'assistente parla e per un breve periodo di raffreddamento dopo. Impostalo su False solo se usi le cuffie e vuoi il supporto alle interruzioni.

Diagramma di sequenza che mostra un utente che interrompe la risposta di un assistente, il client che riceve chunk response.output_audio.delta, interrompe la riproduzione audio, invia un evento conversation.item.truncate e il server che rimuove l'audio non riprodotto prima di iniziare una nuova risposta.

Il troncamento mantiene server e client sincronizzati. Immagine dell'autore.

WebRTC e SIP gestiscono più buffering. Con il percorso WebSocket usato in questo tutorial, è il client a farsene carico. Il contatore nello script di esempio basta per una demo; in produzione il codice dovrebbe tracciare i timestamp dallo stream di output audio.

Configurare i preamboli per la latenza di ragionamento

Quando reasoning.effort è sopra low, il silenzio diventa evidente. Si possono aggiungere brevi preamboli parlati nel prompt di sistema:

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

Questo comportamento è documentato per gpt-realtime-2.

Comportamento osservato

La gestione dei turni ha funzionato con le impostazioni predefinite in una stanza silenziosa. Con gli altoparlanti del laptop, ho avuto bisogno di silenziare il microfono; senza, il modello ascoltava il proprio output e iniziava un loop di eco. 

In ambienti più rumorosi, le impostazioni del VAD e il posizionamento del microfono hanno avuto un impatto maggiore. La memoria della conversazione è rimasta coerente per un test di dieci minuti, ma non distribuirei un'app più lunga senza un piano di riconnessione.

Verdetto: superato per il loop vocale di base. gpt-realtime-2 ha gestito un assistente a basso sforzo di ragionamento nel mio test. Il lavoro extra è lato client: riproduzione, gestione delle interruzioni, riconnessioni e chiamate a tool se l'app ne ha bisogno.

Demo Streamlit: tre modelli in un'unica interfaccia

L'app Streamlit mette i test dietro un selettore a schede. Ti permette di registrare audio, scegliere una lingua di destinazione e confrontare i percorsi dei modelli senza modificare gli script. L'ho tenuta come app demo invece che come percorso didattico principale, perché gli script da terminale mostrano gli eventi in modo più diretto.

Tre modelli in un'unica interfaccia a schede. Immagine dell'autore.

Il video demo qui sotto mostra le schede con una chiave API live. Ogni scheda usa vere chiamate Realtime WebSocket.

Esegui l'app dalla stessa cartella degli script:

streamlit run demo_app.py

La tua chiave API va nella sidebar e non viene salvata da nessuna parte. Per un'app pubblica, mettila invece in Streamlit Secrets.

Costi e latenza di GPT-Realtime-2 nella pratica

Come menzionato nel Test 1, i prezzi si dividono in due gruppi: gpt-realtime-2 è fatturato a token, mentre traduzione e trascrizione sono fatturate al minuto.

Tabella che confronta i modelli di fatturazione e i prezzi attuali per gpt-realtime-2, gpt-realtime-translate e gpt-realtime-whisper

Fatturazione a token e al minuto per modello. Immagine dell'autore.

Per trascrizione e traduzione, il costo scala con la durata. Al momento della scrittura, trenta minuti costano circa $0,51 su gpt-realtime-whisper e circa $1,02 su gpt-realtime-translate.

Gli agenti vocali sono più difficili da stimare perché i token audio si accumulano su entrambi i lati della conversazione. Durata della sessione, rapporto di parlato, sforzo di ragionamento e dimensione del contesto contano tutti. Il caching del prompt può ridurre i costi quando i turni precedenti restano stabili.

Una chiamata REST di trascrizione più TTS è un confronto diverso, a meno che non sia richiesta l'interazione live. whisper-1 è più economico per i file, ma non è lo stesso tipo di API.

Limiti dell'API GPT-Realtime-2, requisiti audio e troubleshooting

Questi sono i limiti che hanno influito sui miei primi test. La maggior parte dei fallimenti derivava da errori nel formato audio o nel ciclo di vita della sessione, non dal modello in sé.

Vincoli di trasporto e audio

Come notato nel primo test, l'audio via WebSocket deve essere PCM16 a 24 kHz, mono e codificato in base64. Ogni evento input_audio_buffer.append è limitato a 15 MB, quindi chunk da 50 millisecondi restano ben al di sotto del limite. È supportato anche G.711 per la telefonia.

Le sessioni Realtime terminano dopo 60 minuti su OpenAI e 30 minuti su Azure OpenAI. Le app più lunghe necessitano di un piano di riconnessione e di un modo per ricostruire lo stato. La voce deve anche essere scelta prima del primo output audio; non può essere cambiata a sessione in corso.

Rate limit e quote

I rate limit sono basati su tier e specifici per progetto. Il Tier 1 attualmente elenca 200 richieste al minuto e 40.000 token al minuto per gpt-realtime-2. Il piano Free non è supportato.

Errori comuni e spigolosità

Gli errori che ho incontrato più spesso sono stati commit di buffer vuoti e formattazione audio errata. Per gli agenti vocali, attenzione anche ai loop di feedback in cui il microfono sente l'output degli altoparlanti dell'assistente. Usa cuffie, cancellazione dell'eco o silenziamento del microfono.

Per sessioni lunghe, riconnettiti intorno ai 55 minuti invece di aspettare la scadenza. Una piccola incongruenza nella documentazione: la pagina del modello gpt-realtime-2 ha una riga generica "Streaming: non supportato", mentre le guide Realtime documentano l'uso di /v1/realtime. Quella riga riguarda lo streaming delle Chat Completions, non il comportamento della Realtime API.

Verdetto finale

Lo stesso schema si ripete nei tre test: a ogni compito corrispondono un proprio modello e un proprio endpoint. Questa suddivisione incide su ciò che il modello può fare, su come viene fatturato e su quanta parte del codice client devi gestire.

Come visto sopra, gpt-realtime-whisper copre il testo live, gpt-realtime-translate copre la traduzione diretta del parlato e gpt-realtime-2 copre il comportamento da assistente con voce, ragionamento e contesto.

Il codice non mostra un modello che sostituisce gli altri. Mostra che le app vocali in tempo reale dipendono dal design della sessione. Il mio punto di partenza sarebbe il modello più piccolo che corrisponde al compito, con il tempo di sviluppo restante dedicato a qualità dell'audio, gestione dei turni, riconnessioni e stato del client.

Per approfondire, i nostri tutorial trattano argomenti correlati su audio e API realtime:


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

Sono un data engineer e community builder: lavoro su pipeline dati, cloud e strumenti di AI, e scrivo tutorial pratici e ad alto impatto per DataCamp e per sviluppatori alle prime armi.

Argomenti

Impara l'IA con DataCamp!

Corso

Sviluppare sistemi di AI con l'API di OpenAI

3 h
21.2K
Sfrutta l'API di OpenAI per preparare le tue applicazioni di IA alla produzione.
Vedi dettagliRight Arrow
Inizia il corso
Mostra altroRight Arrow
Correlato

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

Mostra altroMostra altro