Speech and transcription
Both follow OpenAI's Audio API, so client.audio.speech and client.audio.transcriptions in the OpenAI SDKs work with the base URL changed. The two samples below are files we run against the service before publishing.
Text to speech
# pip install openai
# Text to speech. `voice` is required and its names belong to the model:
# af_heart is one of hexgrad/kokoro-82m's voices.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.getenv("OCEANTOKEN_BASE_URL", "https://api.oceantoken.ai/v1"),
api_key=os.environ["OCEANTOKEN_API_KEY"],
)
with client.audio.speech.with_streaming_response.create(
model="hexgrad/kokoro-82m",
voice="af_heart",
input="Welcome aboard. The ferry leaves at nine.",
response_format="mp3",
) as response:
response.stream_to_file("speech.mp3")
print("saved speech.mp3")
POST /v1/audio/speech answers with the audio itself.
| Field | What it does |
|---|---|
model | The ID of a speech model. |
input | The text to read. |
voice | Required. One of the model's own voice names; see Voices. |
response_format | mp3 is the safe choice and works on every model below except where noted. url returns a link instead of the audio (below). |
speed, instructions | Pace (0.25 to 4) and tone notes, such as "calm, slow", on models that support them. |
Speech is charged per character of input (How you are charged). Send an Idempotency-Key so that a retry after a timeout does not make, and charge, the clip twice (Errors).
Voices
Voice names belong to the model. A request without voice is refused with 400, and a name the model does not know fails. The voices in the second column were tested on the live service (2026-09-26):
| Model | A voice that works | Other voices its publisher lists |
|---|---|---|
hexgrad/kokoro-82m | af_heart | af_bella, am_michael, bf_emma, bm_george |
deepgram/aura-2 | aura-2-thalia-en | aura-2-andromeda-en, aura-2-apollo-en, aura-2-asteria-en, aura-2-helena-en, aura-2-orion-en, aura-2-zeus-en |
canopylabs/orpheus-3b-0.1-ft | tara | leah, jess, leo, dan, mia, zac, zoe |
sesame/csm-1b | conversational_a | conversational_b |
x-ai/grok-voice-tts-1.0 | Ara | Rex, Sal, Eve, Leo |
microsoft/mai-voice-2 | en-US-Jasper:MAI-Voice-1 | |
fish-audio/s1, fish-audio/s2-pro, fish-audio/s2.1-pro, fish-audio/s2.1-pro-free:free | alloy | |
google/gemini-3.1-flash-tts-preview | Kore (send no response_format; it answers in WAV) | Puck, Charon, Fenrir, Aoede, Leda, Orus, Zephyr |
For any other speech model, use the voice names its publisher documents.
Get a link instead of the audio
With "response_format": "url", the answer is JSON with a link to an MP3 instead of the audio bytes, which is easier to pass on to a browser or another request:
{"url": "https://...", "content_type": "audio/mpeg", "bytes": 48213, "usage": {"input_characters": 41}}
Download it within 24 hours. The clip is also in the console under Media.
Transcription
# pip install openai
# Audio file to text. This transcribes speech.mp3, the file the text-to-speech
# sample writes; use any mp3, m4a, wav or webm of your own.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.getenv("OCEANTOKEN_BASE_URL", "https://api.oceantoken.ai/v1"),
api_key=os.environ["OCEANTOKEN_API_KEY"],
)
with open("speech.mp3", "rb") as audio:
transcript = client.audio.transcriptions.create(model="openai/gpt-4o-mini-transcribe", file=audio)
print(transcript.text)
POST /v1/audio/transcriptions takes a multipart upload:
| Field | What it does |
|---|---|
file | The audio: mp3, m4a, wav, webm and other common formats. |
model | The ID of a transcription model. |
language | The spoken language as an ISO-639-1 code, such as en or zh. Optional, and improves accuracy when you know it. |
prompt | Names and spellings to expect. Optional. |
response_format | json (default) returns {"text": "..."}; text the plain text; verbose_json adds segments with timestamps; srt and vtt return subtitles. Models differ in which they offer. |
The same with curl:
curl https://api.oceantoken.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $OCEANTOKEN_API_KEY" \
-F model="openai/gpt-4o-mini-transcribe" \
-F file=@meeting.mp3
- The request is at most 10 MB (Limits). Split longer recordings, or compress them: a 10 MB MP3 at 64 kbit/s holds about 20 minutes.
- Transcription is charged per minute of audio (How you are charged).
- The file must be uploaded; a URL in place of the file is not fetched.
Next
- Video: put the voice-over on a clip.
- Prices for every speech and transcription model are on oceantoken.ai.