Skip to main content
Core.Today
Model APIs

Speech-to-Text (STT)

Turn recorded files or live microphone audio into text. Whisper (OpenAI, Replicate) and Meta Muse Voice Transcribe cover transcription, speaker diarization, timestamps and realtime partial transcripts.

Text-to-Speech (TTS)Go to these docs →

Text → 🔊 Audio

Input
The sentence to speak (text) + a voice (voice_id / speaker)
Output
Audio file URL (mp3, wav, …)
Use
Announcements, narration, audiobooks, voice replies for chatbots
Speech-to-Text (STT)You are here

🎙 Audio → Text

Input
Audio file URL (audio), or a realtime PCM stream
Output
Transcript + segments, timestamps, speakers (JSON)
Use
Meeting notes, subtitles, call recordings, voice commands

Want to read text out loud? This is the wrong page — see the Text-to-Speech (TTS) docs. The two directions use different models and input parameters; sending one direction's parameters (text↔audio) to the other's model is rejected or fails.

Give this page to your AI — all model specs as LLM-friendly text
llms.txt ↗

Pick a calling style

STT can be called three ways. Pick the style before the model — the endpoint, input format and how you get the result all differ.

StyleEndpointAudio inputResultModels
① File transcription
Most use cases
POST /v1/predictionsAudio file URL (audio; file_url for whisper-diarization)Get a job_id, then poll GET /v1/predictions/{id}openai/gpt-transcribe, openai/whisper-1, openai/whisper, incredibly-fast-whisper, whisper-diarization, meta/muse-voice-transcribe-1.0
② Realtime streaming
Captions while speaking
wss://api.core.today/v1/realtime/asrRaw 16-bit mono PCM binary frames (sent at 1x)Partial and final transcript events on the same socketmeta/muse-voice-transcribe-1.0/realtime
③ OpenAI SDK compatible
Move existing OpenAI code
POST /llm/openai/v1/audio/transcriptionsUpload the file directly (multipart file, not a URL)Right in the response body (no polling)gpt-transcribe, whisper-1

Model comparison

ModelPriceStyleProvider
openai/gpt-transcribe11 credits per minute of audio (0.174375/s, settled on measured length)File transcription (async)OpenAI
vaibhavs10/incredibly-fast-whisper10 credits per runFile transcription (async)Whisper
meta/muse-voice-transcribe-1.07 credits per minute of audio (0.11625/s, settled on measured length)File transcription (async)Meta
meta/muse-voice-transcribe-1.0/realtime35 credits per 5-minute block (0.11625 credits/s)Realtime (WebSocket)Meta
openai/whisper-114 credits per minute of audio (0.2325/s, settled on measured length)File transcription (async)OpenAI
openai/whisper14 credits per minute of audio (0.2325/s, minimum 10 credits, settled on measured length)File transcription (async)OpenAI
thomasmol/whisper-diarization14 credits per runFile transcription (async)Whisper

For local files, upload first with POST /v1/files/upload-url and pass that URL as audio. Per-run models take longer as audio gets longer; per-minute models settle on the measured length and refund the difference.

Model details

Each model's page has its full parameters, output format and examples.

7 models

GPT Transcribe (OpenAI API)

OpenAI

11 credits

OpenAI's gpt-transcribe speech recognition, the successor to whisper-1 - plain transcript text with detected languages, optional language hints and keyword spelling. No timestamps. Billed per second of audio (0.174375 credits/s, about 10.5 credits per minute), up to 1 hour / 25MB per request.

FastHigh
View details

Incredibly Fast Whisper

Whisper

10 credits

Whisper large-v3 optimized for speed (38M+ runs) — transcribes roughly 150 minutes of audio in under 100 seconds using batched inference. Chunk-level or word-level timestamps.

FastUltra
View details

Muse Voice Transcribe 1.0

Meta

7 credits

Meta's Muse Voice Transcribe speech-to-text over the Meta developer API - 25 languages with code-switching (Korean included), speaker diarization, endpointing, keyword and language biasing. Billed per second of audio (0.11625 credits/s, about 7 credits per minute), up to 10 minutes per request.

FastHigh
View details

Muse Voice Transcribe 1.0 (Realtime)

Meta

35 credits

Meta's Muse Voice Transcribe over a WebSocket - stream 16-bit PCM (24 kHz or 16 kHz mono) and receive partial and final transcripts while you speak, with endpointing and diarization. Billed per second of audio Meta processed (0.11625 credits/s, 35 credits per 5-minute block), sessions up to 20 minutes.

FastHigh
View details

Whisper-1 (OpenAI API)

OpenAI

14 credits

OpenAI's hosted whisper-1 speech recognition with the OpenAI API parameters - json or verbose_json output, segment and word timestamps (timestamp_granularities), language hint and prompt. Billed per second of audio (0.2325 credits/s, about 14 credits per minute), up to 1 hour / 25MB per request.

FastHigh
View details

Whisper

OpenAI

14 credits

OpenAI's Whisper large-v3 speech recognition (144M+ runs) — the standard for transcription. Automatic language detection across ~100 languages, English translation, and plain text / SRT / VTT output formats.

MediumUltra
View details

Whisper Diarization

Whisper

14 credits

Whisper transcription with speaker diarization (8M+ runs) — returns who said what, with per-segment speaker labels and timestamps. The go-to for meetings and interviews.

FastHigh
View details

① File transcription (async)

Create a job with an audio URL, then poll with the job_id until it completes. For JSON with timestamps, use openai/whisper-1 with verbose_json (OpenAI shuts it down on 2027-02-26 — for plain text without timestamps, the cheaper openai/gpt-transcribe):

curl -X POST https://api.core.today/v1/predictions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cdt_your_api_key" \
  -d '{
    "model": "openai/whisper-1",
    "input": {
      "audio": "https://example.com/meeting.mp3",
      "response_format": "verbose_json",
      "timestamp_granularities": ["segment"]
    }
  }'

# → {"job_id": "...", "status": "processing", ...}
curl https://api.core.today/v1/predictions/{job_id} -H "X-API-Key: cdt_your_api_key"

When it completes, result holds OpenAI's response body as-is. usage.seconds is the billed audio length:

{
  "job_id": "91bGtKlfdpgiXxOKVQV6W9pb6r0oYwrD",
  "status": "completed",
  "result": {
    "task": "transcribe",
    "language": "english",
    "duration": 52.41,
    "text": "The little tales they tell are false. ...",
    "segments": [
      { "id": 0, "start": 0.0, "end": 5.04, "text": " The little tales they tell are false." }
    ],
    "usage": { "type": "duration", "seconds": 53 }
  },
  "credits_used": 13
}

To get SRT or VTT subtitles directly, use openai/whisper on Replicate (auto-detects 100 languages):

curl -X POST https://api.core.today/v1/predictions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cdt_your_api_key" \
  -d '{
    "model": "openai/whisper",
    "input": {
      "audio": "https://example.com/meeting.mp3",
      "transcription": "srt",
      "language": "auto"
    }
  }'

For speaker diarization and speech turns, use Meta Muse Voice Transcribe (25 languages including Korean, up to 10 minutes per request). The result is JSON with transcript, audioDurationMs and turns[]:

curl -X POST https://api.core.today/v1/predictions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: cdt_your_api_key" \
  -d '{
    "model": "meta/muse-voice-transcribe-1.0",
    "input": {
      "audio": "https://example.com/meeting.m4a",
      "mode": "DIARIZATION",
      "language_bias": ["Korean", "English"]
    }
  }'

② Realtime streaming (WebSocket)

If you need partial and final transcripts while someone is speaking, connect over WebSocket instead of POST /predictions. Only Meta Muse Voice Transcribe 1.0 (Realtime) supports this, and that model rejects POST /predictions with 400 realtime_only. The endpoint is wss://api.core.today/v1/realtime/asr.

Authenticate with the X-API-Key header (checked before the upgrade), or — for runtimes that can't set headers — the apiKey field of the handshake JSON. Reseller teams must also send X-Customer-Id (or handshake customerId) from the same source as the key (header with header, JSON with JSON). Never put a real API key in a browser — connect from your own server and relay the browser's audio to it over a separate channel.

Right after connecting, send the handshake as the first text frame (if it doesn't arrive within 10 seconds: 4400 handshake_timeout):

{
  "model": "meta/muse-voice-transcribe-1.0/realtime",
  "audioEncoding": "PCM_24KHZ",
  "mode": "ENDPOINTING",
  "partialMode": "CUMULATIVE",
  "emitAudioProgress": false,
  "keywords": ["Core.Today"],
  "languageBias": ["Korean"],
  "apiKey": "cdt_your_api_key",
  "customerId": "member-123"
}

Then send raw 16-bit mono PCM audio as binary frames (up to 64 KiB each). Send at real-time speed (1x) and pad with silence when you have no audio — 10 seconds without audio closes with 4408 idle_timeout, and getting more than 5 seconds ahead of real time closes with 4400 pacing_violation. To finish, send the text frame {"type":"endStream"}.

Events we send: session once connected; Meta's transcript, speechStart, speechEnd, speechComplete and speaker passed through as-is (plus audioProgress with emitAudioProgress: true); and finally usage after billing settles:

{"type":"session","sessionId":"rt_..."}
{"type":"transcript","transcript":"...","final":false}
{"type":"usage","sessionId":"rt_...","audioSeconds":73,"credits":9,"reason":"client_end"}

Python example — streams a 24kHz WAV in 80ms frames at 1x and prints the events:

import asyncio, json, os, wave, websockets

API_KEY = os.environ["AIAPI_API_KEY"]
ENDPOINT = "wss://api.core.today/v1/realtime/asr"

async def main():
    async with websockets.connect(
        ENDPOINT, additional_headers={"X-API-Key": API_KEY}
    ) as ws:
        await ws.send(json.dumps({
            "model": "meta/muse-voice-transcribe-1.0/realtime",
            "audioEncoding": "PCM_24KHZ",
            "mode": "ENDPOINTING",
            "languageBias": ["Korean"],
        }))

        async def send_audio():
            with wave.open("meeting-24khz-mono.wav", "rb") as wav:
                frame_bytes = int(24000 * 2 * 0.08)  # 80ms of 16-bit mono PCM
                while chunk := wav.readframes(frame_bytes // 2):
                    await ws.send(chunk)
                    await asyncio.sleep(0.08)  # pace at 1x — never send ahead
            await ws.send(json.dumps({"type": "endStream"}))

        async def recv_events():
            async for msg in ws:
                if isinstance(msg, str):
                    print(json.loads(msg))

        await asyncio.gather(send_audio(), recv_events())

asyncio.run(main())

Close codes:

CodeMeaning
1000Normal close (client ended, 20-minute cap, feature disabled)
1011Meta session error
1012Server redeploy — the session closes immediately without the final transcript or usage event. Reconnect with exponential backoff
4400Handshake or frame error, or pacing violation (invalid_handshake / model_not_found / ambiguous_auth / handshake_timeout / invalid_frame / pacing_violation)
4401Missing or invalid API key (unauthorized)
4402Insufficient credits or customer budget (insufficient_credits / reseller_account_insufficient / customer_wallet_insufficient)
4403Reseller scope, allowed models or disabled key (invalid_customer_id / customer_suspended / customer_not_found / model_not_allowed / api_key_disabled)
4408No audio for 10+ seconds, or a client too slow to read events (idle_timeout / client_slow)
4413Binary frame larger than 64 KiB (frame_too_large)
4429Concurrency or rate limit (customer_concurrency_exceeded / team_concurrency_exceeded / rate_limit_exceeded / customer_rate_limited / server_busy)
4503Feature disabled or upstream/gateway outage (feature_disabled / provider_unavailable / provider_rejected / provider_rate_limited / admission_unavailable)

Billing: 0.11625 credits per second. 35 credits are reserved per 5-minute (300-second) block and settled as the session runs. The final charge is based on the audio seconds Meta reports it processed (not connection time), and the last partial block is charged only for its seconds (e.g. 73 s = 9 credits, 300 s = 35 credits). Sessions last at most 20 minutes (1,200 s); reconnect for longer. If the server restarts during a deploy, live sessions close immediately with 1012 (no final transcript or usage event); billing is settled server-side, so just reconnect with exponential backoff.

③ OpenAI SDK compatible

Already using OpenAI speech-to-text through the SDK? Change only the base_url and API key. The file is uploaded directly as multipart (not a URL), the result comes back in the response body, and billing is per second on the audio length OpenAI reports (LLM gateway rate). Models: gpt-transcribe (about 8.4 credits per minute, text only) and whisper-1 (about 11 credits per minute, timestamps).

whisper-1 is retiring: OpenAI shuts down whisper-1 and /audio/translations on 2027-02-26. Move plain transcription to gpt-transcribe (only the model name changes). gpt-transcribe answers json only, without timestamps — if you need segment or word timestamps, keep whisper-1 until then and move to openai/whisper (with segments) under ① File transcription.
from openai import OpenAI

client = OpenAI(
    base_url="https://api.core.today/llm/openai/v1",
    api_key="cdt_your_api_key",
)

# gpt-transcribe: text + detected languages (no timestamps)
with open("meeting.mp3", "rb") as f:
    result = client.audio.transcriptions.create(
        model="gpt-transcribe",
        file=f,
        languages=["ko"],  # openai>=3.x; older SDKs: extra_body={"languages": ["ko"]}
        keywords=["Core.Today"],
    )
print(result.text)

For timestamps, whisper-1 with verbose_json (until 2027-02-26):

from openai import OpenAI

client = OpenAI(
    base_url="https://api.core.today/llm/openai/v1",
    api_key="cdt_your_api_key",
)

with open("meeting.mp3", "rb") as f:
    result = client.audio.transcriptions.create(
        model="whisper-1",
        file=f,
        response_format="verbose_json",
        timestamp_granularities=["segment"],
    )

print(result.text)
for seg in result.segments:
    print(seg.start, seg.end, seg.text)

Without the SDK, with curl (same multipart format as OpenAI, key in Authorization: Bearer):

curl https://api.core.today/llm/openai/v1/audio/transcriptions \
  -H "Authorization: Bearer cdt_your_api_key" \
  -F file=@meeting.mp3 \
  -F model=gpt-transcribe \
  -F "languages[]=ko"
  • Files: mp3, mp4, mpeg, mpga, m4a, wav, webm (whisper-1 also flac, ogg) · up to 25MB (OpenAI's limit). Translation to English is whisper-1 only, same format at POST /llm/openai/v1/audio/translations (shuts down 2027-02-26)
  • gpt-transcribe: languages[] (e.g. ko), keywords[] (spelling of names and terms) and prompt; the reply is {text, languages, usage}. whisper-1: timestamp_granularities (segment, word) works only with verbose_json; language, prompt and temperature are passed through as-is
  • Rejected with 400 (no credits charged): an unsupported response_format (gpt-transcribe json only, whisper-1 json and verbose_json) → response_format_unsupported; stream=true → stream_not_supported; any other model (e.g. gpt-4o-transcribe), or gpt-transcribe on translations → audio_model_unsupported
  • Billing: response usage.seconds (duration for verbose_json) × 0.13935 (gpt-transcribe) or 0.1858 (whisper-1) credits per second. Credits are reserved from an estimate based on file size and settled on the actual length

If you'd rather send a file URL, or want per-job credit reservation and refunds, use openai/gpt-transcribe or openai/whisper-1 under ① File transcription — the same OpenAI models with the same parameter names.

Which model?

  • Timestamped JSON (subtitles, search indexing) — openai/whisper-1 (14 credits per minute of audio (0.2325/s, settled on measured length)). Segment- and word-level verbose_json (retires 2027-02-26 — then openai/whisper segments)
  • Text only, cheapest (OpenAI) — openai/gpt-transcribe (11 credits per minute of audio (0.174375/s, settled on measured length)). whisper-1's successor, with languages and keywords hints
  • SRT / VTT subtitle files directly — openai/whisper (14 credits per minute of audio (0.2325/s, minimum 10 credits, settled on measured length)). For long audio, faster: incredibly-fast-whisper (10 credits per run)
  • Meeting notes (who said what) — mixed Korean/English and keyword biasing: meta/muse-voice-transcribe-1.0 (7 credits per minute of audio (0.11625/s, settled on measured length), up to 10 min per request), Whisper-based diarization: whisper-diarization (14 credits per run)
  • Live captions, voice commands — meta/muse-voice-transcribe-1.0/realtime (35 credits per 5-minute block (0.11625 credits/s), WebSocket)
  • Moving existing OpenAI SDK code — gpt-transcribe / whisper-1 (OpenAI SDK compatible path; only the base_url and key change)