Overview
OpenAI’s new transcription models give existing Whisper users two focused upgrade paths. GPT-Transcribe (gpt-transcribe) is designed for accurate transcription of completed audio via uploaded files. GPT-Live-Transcribe (gpt-live-transcribe) is designed for low-latency, continuously streaming transcription.
At a high level, the API endpoints are the same. File requests continue to use POST /v1/audio/transcriptions. Realtime integrations continue to configure a transcription session and handle transcription events. What’s different are the supported request fields, the output formats, and contextual/multilingual hints.
What stays the same
- File transcription uses the existing Audio API transcription endpoint.
- Realtime transcription uses the existing Realtime transcription session, WebSocket or WebRTC transport, and transcription events.
- Applications still provide audio, receive transcription text, and handle API or connection errors.
What changes
- Use
gpt-transcribefor completed files, streamed file transcripts, or committed Realtime turns. - Use
gpt-live-transcribefor continuously streaming, low-latency live transcription. - Replace the legacy
languagehint with the new-modellanguagesarray. - Use
promptfor free-form context andkeywordsfor literal terms expected in the audio. - Handle detected-language output for GPT-Transcribe, including an empty languages array.
1. Choose your migration path
- Recorded meetings, calls, or uploaded audio: migrate
whisper-1togpt-transcribeon POST /v1/audio/transcriptions. - Live captions or continuously arriving microphone audio: migrate
gpt-realtime-whispertogpt-live-transcribein a Realtime transcription session. - Higher-accuracy transcription after a manually committed audio turn: use
gpt-transcribein a Realtime transcription session over WebSocket. Treat live audio and streaming output as separate decisions. A completed file can produce streamed transcript events, and a Realtime session can wait for an audio turn to be committed before producing deltas.
2. Migrate recorded audio
The smallest file migration preserves the endpoint, SDK call, and file upload. Replace the model identifier, then consume the JSON transcription response.
Prerequisites
- Python 3.11 or later.
- The OpenAI Python SDK:
python -m pip install --upgrade openai. - An
OPENAI_API_KEYenvironment variable. - A completed recording named
meeting.wav, or updateaudio_pathto point to your own file. - Access to the transcription models used in the example.
File examples make live API requests. Realtime examples construct the session payloads. Use WebSocket or WebRTC for gpt-live-transcribe, and use WebSocket for committed-turn gpt-transcribe.
import json
from pathlib import Path
from openai import OpenAI
client = OpenAI()
audio_path = Path("meeting.wav")
Before — Whisper file transcription
with audio_path.open("rb") as audio:
before = client.audio.transcriptions.create(
model="whisper-1",
file=audio,
)
print(before.text)
After — GPT-Transcribe
with audio_path.open("rb") as audio:
after = client.audio.transcriptions.create(
model="gpt-transcribe",
file=audio,
response_format="json",
)
print(after.text)
Do’s and don’ts
- Note that the new model returns JSON. If the existing application requests
text,verbose_json,srt, orvtt, do not assume the same response_format remains valid. Keep Whisper for those formats or explicitly build and test the downstream conversion your application requires.
3. Update language hints and domain context
Legacy Whisper integrations commonly send a single language value and place domain vocabulary in a free-form prompt. The new models accept multiple expected input languages and separate structured keyword hints from the general prompt.
Before — single-language Whisper request
from openai import OpenAI
client = OpenAI()
with open("meeting.wav", "rb") as audio:
result = client.audio.transcriptions.create(
model="whisper-1",
file=audio,
language="en",
prompt="A support call about AC-42.",
)
print(result.text)
After — multilingual GPT-Transcribe request
from openai import OpenAI
client = OpenAI()
with open("meeting.wav", "rb") as audio:
result = client.audio.transcriptions.create(
model="gpt-transcribe",
file=audio,
prompt="A customer support call about billing.",
extra_body={
"keywords": ["AC-42", "Premium Plus"],
"languages": ["en", "fr"],
},
)
print(result.text)
Do’s and don’ts
- Use
promptto describe the recording’s topic or setting. - Use
keywordsfor literal product names, medication names, account identifiers, or other domain-specific terms that may actually be spoken. - Use
languagesto indicate expected spoken languages. - Do not send both
languageandlanguages. - Validate keyword input before making the request: each keyword must be a single-line literal and must not include
<,>, a carriage return, or a line feed. Invalid keyword input rejects the whole request or session update.
4. Stream the transcription of a completed file
Streaming applies to the transcription output, not the audio input. The application first supplies a completed recording; the API then streams text as it transcribes that recording.
Before — blocking Whisper file request
with audio_path.open("rb") as audio:
before = client.audio.transcriptions.create(
model="whisper-1",
file=audio,
)
print(before.text)
# whisper-1 does not provide transcript.text.delta events.
After — streamed GPT-Transcribe file request
with audio_path.open("rb") as audio:
stream = client.audio.transcriptions.create(
model="gpt-transcribe",
file=audio,
stream=True,
)
for event in stream:
if event.type == "transcript.text.delta":
print(event.delta, end="", flush=True)
elif event.type == "transcript.text.done":
print("\nFinal:", event.text)
Do’s and don’ts
- Use transcription events to distinguish in-progress from completed transcripts. Update your transcript or progress UI with
transcript.text.deltaevents, then usetranscript.text.doneto mark the transcript as final. - Do not label file streaming as live audio capture: the file must already exist.
5. Migrate continuous live transcription
For a live captioning workflow, preserve the Realtime connection and transcription-session architecture. Change the transcription model and update the model-specific configuration.
Before — GPT-Realtime-Whisper
legacy_realtime_session = json.loads(
r'''
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"transcription": {
"model": "gpt-realtime-whisper",
"language": "en"
},
"turn_detection": null
}
}
}
}
'''
)
print(json.dumps(legacy_realtime_session, indent=2))
After — GPT-Live-Transcribe
live_transcription_session = json.loads(
r'''
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"transcription": {
"model": "gpt-live-transcribe",
"prompt": "A support call about a plan.",
"keywords": ["AC-42", "Premium Plus"],
"languages": ["en", "fr"],
"delay": "low"
},
"turn_detection": null
}
}
}
}
'''
)
print(json.dumps(live_transcription_session, indent=2))
Do’s and don’ts
- Continue handling
conversation.item.input_audio_transcription.deltaandconversation.item.input_audio_transcription.completed. - Preserve the existing item_id-based reconciliation logic.
- Use the model’s
delaysetting to trade off faster partial transcripts against a more accurate final transcript. - Preserve the existing WebSocket or WebRTC transport; Realtime transcription supports both.
6. Use GPT-Transcribe in a committed-turn Realtime session
GPT-Transcribe is not limited to uploaded files. Use it as the input transcription model in a Realtime session over WebSocket when your application needs higher-accuracy transcription after a manually committed audio turn.
Before — legacy live-transcription session
legacy_live_session = json.loads(
r'''
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"transcription": {
"model": "gpt-realtime-whisper",
"language": "en"
}
}
}
}
}
'''
)
print(json.dumps(legacy_live_session, indent=2))
After — committed-turn GPT-Transcribe session
committed_turn_session = json.loads(
r'''
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"transcription": {
"model": "gpt-transcribe",
"prompt": "A customer support call.",
"keywords": ["AC-42"],
"languages": ["en", "fr"]
},
"turn_detection": null
}
}
}
}
'''
)
print(json.dumps(committed_turn_session, indent=2))
Do’s and don’ts
- Append audio to the input buffer, then send
input_audio_buffer.commit. Transcription happens per committed chunk of audio, not continuous live captioning. GPT-Transcribe may emit transcript delta events before the completed event for that chunk.
7. Update response and event handling
GPT-Transcribe can include detected input languages in completed file and Realtime results. These are predictions returned by the model, not a restatement of the caller’s language hints.
Before — transcript without language predictions
legacy_transcription_response = json.loads(
r'''
{
"text": "Bonjour, pouvez-vous m'entendre ?"
}
'''
)
print(json.dumps(legacy_transcription_response, indent=2))
After — GPT-Transcribe detected-language response
detected_language_response = json.loads(
r'''
{
"text": "Bonjour, pouvez-vous m'entendre ?",
"languages": [
{ "code": "fr" }
]
}
'''
)
print(json.dumps(detected_language_response, indent=2))
language_codes = [
item["code"]
for item in detected_language_response.get("languages", [])
]
print("Detected languages:", language_codes)
Do’s and don’ts
- Handle
languages: []as a valid result when the model cannot make a reliable prediction. - Do not infer that no one spoke, that the request failed, or that a synthetic
unknownlanguage was returned. GPT-Live-Transcribe does not return detected-language predictions in its initial contract. - For Realtime, inspect
conversation.item.input_audio_transcription.completed; GPT-Transcribe may attach the same language metadata to that event.
8. Check compatibility before switching
Some existing transcription features do not have a drop-in replacement in gpt-transcribe or gpt-live-transcribe.
- Subtitles: retain
whisper-1if the integration depends on native SRT or VTT output. - Timestamps: retain a model and response format that explicitly support word or segment timestamps.
- Translation: retain
/v1/audio/translationswith a supported translation model if the application translates audio into English. - Speaker diarization: use
gpt-4o-transcribe-diarizeon/v1/audio/transcriptionswithresponse_format: "diarized_json"when your application requires speaker labels. Setchunking_strategy: "auto"for recordings longer than 30 seconds. This model is not supported in the Realtime API.
9. Evaluate before and after
Use the same representative audio clips across both models. Compare the baseline, a direct model-only replacement, and a version that adds the new context fields. This isolates improvements from the model itself versus improvements caused by prompt, keywords, or language hints.
Evaluate transcription quality
- Overall word error rate on representative recordings.
- Exact-match accuracy for names, product names, medication names, account identifiers, numbers, and email addresses.
- Performance with accents, background noise, telephony audio, and short utterances.
- Accuracy during language switching and mixed-language speech.
- Keyword hallucination: confirm the transcript does not insert hinted words that were not actually spoken.
- Completeness of the final transcript and any expected language metadata.
Evaluate streaming and operational behavior
- Time to first transcript delta, reported separately for file streaming and live audio.
- Time from an explicit committed turn to the final transcript.
- Median and tail latency, including p95 or the team’s existing service-level threshold.
- How frequently partial transcript text changes before completion.
- Event ordering and item_id reconciliation across overlapping turns.
- Reconnect, retry, empty-audio, and interrupted-session behavior.
- Actual request pricing and production rate limits from the released source of truth.
Common migration errors
- Treating
gpt-transcribeas incompatible with Realtime solely because it is optimized for completed audio. - Describing GPT-Transcribe as unable to stream because processing begins after a commit.
- Assuming streamed file output means the endpoint accepts an ongoing microphone stream.
- Sending both legacy
languageand new-modellanguages. - Expecting subtitle formats, timestamps, speaker labels, or detected-language output from a model that does not support them.
- Treating an empty detected-language array as an API error.
- Forcing keywords into the transcript instead of treating them as hints.
- Assuming every Realtime model supports the same voice activity detection and latency controls.