cnAPI Speech APIs: STT & TTS
Complete integration guide for cnAPI speech-to-text and text-to-speech APIs, including deployment status, models, fields, formats, voices, examples, and capability limits.
cnAPI exposes two independent speech capabilities. Choose the endpoint by data direction; STT and TTS models and request formats are not interchangeable.
Current availability (2026-08-11)
STT is available in production. The TTS adapter is deployed and a real WAV request has passed production verification, but the public model price is not configured yet. Until pricing is enabled, regular API keys receive 400 model_price_error; do not put TTS into production yet.
Capability matrix
| Capability | Endpoint | Public models | Status | Input | Output |
|---|---|---|---|---|---|
| Speech to text (STT) | POST /v1/audio/transcriptions | gemini-2.5-stt, gemini-3-stt, gemini-3.5-stt, gemini-3.6-stt | Production available; real requests verified | multipart/form-data audio file | { "text": "..." } |
| Text to speech (TTS) | POST /v1/audio/speech | gemini-3.1-tts | Adapter deployed and WAV verified; public pricing pending | JSON text, voice, and instructions | WAV or raw PCM bytes |
| Audio translation | /v1/audio/translations | None | Not supported | — | — |
Base URL: https://cnapi.vip/v1
Authorization: Bearer $API_KEYSpeech to text (STT)
Recommended request
Upload audio as multipart/form-data. Let cURL or your SDK create the multipart boundary; do not manually set the Content-Type: multipart/form-data header.
curl --fail-with-body https://cnapi.vip/v1/audio/transcriptions \
-H "Authorization: Bearer $API_KEY" \
-F "file=@./meeting.wav;type=audio/wav" \
-F "model=gemini-2.5-stt" \
-F "prompt=Product review meeting; preserve names and technical terms"The successful response is always JSON:
{
"text": "The complete transcript appears here."
}Models
These are cnAPI public model IDs. All four have completed real production request checks. Do not substitute internal upstream model names.
| Model | Guidance |
|---|---|
gemini-2.5-stt | Recommended default for general transcription and compatibility-first integrations |
gemini-3-stt | General transcription on the Gemini 3 route |
gemini-3.5-stt | Newer route; compare with your own recordings before switching |
gemini-3.6-stt | Latest route; compare with your own recordings before switching |
cnAPI does not promise a fixed accuracy ranking across languages, accents, and noise conditions. Benchmark with representative audio before choosing a production model.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | One audio file, up to 15 MB |
model | string | Yes | One public STT model from the table above |
prompt | string | No | Context such as names, brands, terminology, and desired spelling |
Only the basic JSON transcript is guaranteed. Do not rely on language, response_format, temperature, segment or word timestamps, or speaker diarization fields.
Accepted files
| Extension | MIME type |
|---|---|
.mp3 | audio/mp3 |
.wav | audio/wav |
.m4a | audio/aac |
.ogg | audio/ogg |
.flac | audio/flac |
.aiff, .aif | audio/aiff |
The extension must match the actual encoding. WAV has completed an end-to-end production regression; if an unusual codec or container fails, convert it to standard PCM WAV and retry.
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
api_key="YOUR_cnAPI_KEY",
base_url="https://cnapi.vip/v1",
)
with open("meeting.wav", "rb") as audio_file:
result = client.audio.transcriptions.create(
model="gemini-2.5-stt",
file=audio_file,
prompt="Product review meeting; terms include Vertex AI, NewAPI, and cnAPI",
)
print(result.text)STT limits
- One synchronous upload, no larger than 15 MB.
- Automatic language recognition returns text in the source language;
/audio/translationsis not provided. - No WebSocket, bidirectional realtime stream, chunked upload, or asynchronous long-audio job.
- No diarization, word alignment, SRT/VTT, or timestamp output.
- STT and TTS use different backends; an STT model cannot be sent to
/audio/speech.
Text to speech (TTS)
Public pricing pending
The contract below is deployed and has passed a real production WAV regression. Regular API keys remain blocked by 400 model_price_error until gemini-3.1-tts receives its official public price.
Request
curl --fail-with-body https://cnapi.vip/v1/audio/speech \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.1-tts",
"input": "Welcome to the cnAPI speech service.",
"voice": "Kore",
"response_format": "wav",
"instructions": "Speak clearly in a warm, calm, professional tone"
}' \
--output speech.wavA successful response is binary audio, not JSON. Write the response body directly to a file or audio buffer.
Request fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | Yes | — | Current public model: gemini-3.1-tts |
input | string | Yes | — | Text to synthesize; it must not be empty after trimming |
voice | string | Yes | — | Exact Gemini preset voice name; start with Kore |
response_format | string | No | wav | Only wav or pcm |
instructions | string | No | — | Natural-language control for tone, emotion, accent, pace, and pronunciation |
speed | number | No | 1 | 0.25–4; converted to a natural-language instruction, not an exact playback multiplier |
The combined input, instructions, and generated speed instruction must be no more than 8,000 UTF-8 bytes.
Output
response_format | Content-Type | Audio specification | Use |
|---|---|---|---|
wav | audio/wav | 24 kHz, 16-bit, mono, with a WAV header | Recommended default; save and play directly |
pcm | audio/pcm | 24 kHz, 16-bit, mono, raw PCM without a header | Pipelines that explicitly accept raw PCM |
The cnAPI Vertex adapter does not currently expose MP3, Opus, AAC, or FLAC. Formats available through other Google APIs are not automatically supported by this endpoint.
Voices
Use the exact preset spelling below. See the official Gemini-TTS voice list for upstream updates.
| Female | Male |
|---|---|
| Achernar, Aoede, Autonoe, Callirrhoe, Despina, Erinome, Gacrux, Kore, Laomedeia, Leda, Pulcherrima, Sulafat, Vindemiatrix, Zephyr | Achird, Algenib, Algieba, Alnilam, Charon, Enceladus, Fenrir, Iapetus, Orus, Puck, Rasalgethi, Sadachbia, Sadaltager, Schedar, Umbriel, Zubenelgenubi |
Audition two or three voices with a short representative script before fixing one in production. OpenAI voice names such as alloy, nova, and shimmer are not valid here.
Style and speed
Natural-language instructions are the primary control surface:
{
"instructions": "Read like a restrained documentary narrator: warm, precise, and clear on product names"
}speed becomes an instruction similar to “Speak at 1.2x normal speed.” The model will try to follow it, but the result is not a mathematically exact post-processing rate change.
Python (HTTPX)
import httpx
payload = {
"model": "gemini-3.1-tts",
"input": "Welcome to the cnAPI speech service.",
"voice": "Kore",
"response_format": "wav",
"instructions": "Warm, calm, clear professional narration",
}
response = httpx.post(
"https://cnapi.vip/v1/audio/speech",
headers={"Authorization": "Bearer YOUR_cnAPI_KEY"},
json=payload,
timeout=120,
)
response.raise_for_status()
with open("speech.wav", "wb") as audio_file:
audio_file.write(response.content)TTS limits
- Single preset voice only; no multi-speaker dialogue configuration.
- No SSE, WebSocket, or streaming audio response.
- No custom voice cloning, reference audio, or SSML.
- No
mp3,opus,aac, orflacoutput. - Gemini determines language and expressiveness; cnAPI guarantees only the conversion and audio packaging documented here.
Common errors
| Status | Typical cause | Action |
|---|---|---|
400 | Missing fields, unsupported format, oversized text, or invalid voice | Validate against this page |
400 | model_price_error because public pricing is not enabled | Wait for pricing to be enabled; retrying the same request will not help |
401 | Missing or invalid API key | Check the Bearer token; never expose it in browser code |
413 | STT file exceeds 15 MB | Compress, split, or transcode the file |
429 | Rate, quota, or upstream capacity limit | Retry with exponential backoff and check account quota |
500 / 502 / 503 | Upstream or server failure | Retry a limited number of times with backoff, then contact support with the request ID |
Production applications should log HTTP status and the cnAPI request ID, but never log API keys, complete private recordings, or sensitive transcripts.
How is this guide?