Language is detected for you
There is no language parameter. Valmiki STT works out which language is being spoken, including recordings that switch languages mid-sentence, such as Hindi and English.
Developers · Valmiki speech to text
Valmiki STT turns speech into text, from a recording or a live stream, and detects the language for you. Paste the Python on the right, add your key and run it.
Price: $0.00525 per minute of audio, billed by the second.
Free API tier: 10,000 free text-to-speech characters and one free voice clone that speaks every language, no card required.
1# pip install requests2import requests34with open("recording.wav", "rb") as audio:5 r = requests.post(6 "https://api.sonexlabs.com/v1/transcribe",7 headers={8 "Authorization": "Bearer YOUR_API_KEY",9 "Content-Type": "audio/wav", # audio/mpeg, audio/ogg (WhatsApp notes), audio/mp4 ...10 },11 data=audio,12 )13r.raise_for_status()14result = r.json()15print(result["text"]) # the transcript, in the language that was spoken16print(result["duration_seconds"], "seconds of audio")Reply: text, duration_seconds, request_id and seconds_billed. Keys start with vsk_; keep them in an environment variable.
What it does
There is no language parameter. Valmiki STT works out which language is being spoken, including recordings that switch languages mid-sentence, such as Hindi and English.
Stream live audio over a WebSocket and get partial transcripts as words form and final ones as each utterance ends, or send a finished recording and get the whole transcript back.
WAV, MP3, FLAC, OGG, Opus, WebM, AAC and M4A, up to 10 MB and 10 minutes per recording. Live streams take 16 kHz mono 16-bit PCM.
$0.00525 per minute of audio, billed by the second. A recording is billed for its own length; a stream for as long as it stays open. Audio we reject is never billed.
Speech to text in Python
Wait for the ready event, send 100 ms frames of 16 kHz mono PCM in real time, then send end. Partial events arrive as words form and final events as each utterance completes.
1# pip install websockets2import asyncio, json, wave3import websockets45async def main():6 async with websockets.connect(7 "wss://api.sonexlabs.com/v1/transcribe/stream",8 additional_headers={"Authorization": "Bearer YOUR_API_KEY"},9 ) as ws:10 while json.loads(await ws.recv())["type"] != "ready":11 pass12 with wave.open("call-k.wav", "rb") as w: # 16 kHz mono 16-bit PCM13 while frame := w.readframes(1600): # 100 ms per frame14 await ws.send(frame)15 await asyncio.sleep(0.1) # send in real time16 await ws.send(json.dumps({"type": "end"}))17 async for message in ws:18 event = json.loads(message)19 if event["type"] == "final":20 print(event["text"])21 elif event["type"] == "done":22 print("billed", event["seconds_billed"], "seconds")23 break2425asyncio.run(main())A stream is billed per second while it is open, whether or not anyone is speaking, so close it as soon as the speaker stops. It closes for you after 10 minutes, or after 30 seconds with no recognised speech. A browser cannot set headers on a WebSocket, so mint a short-lived key on your server and pass it as ?api_key= rather than shipping your main key.
REST
Send the audio as the request body with its Content-Type, or as a multipart upload under file.
1curl https://api.sonexlabs.com/v1/transcribe \2 --header 'Authorization: Bearer YOUR_API_KEY' \3 --header 'Content-Type: audio/wav' \4 --data-binary '@recording.wav'56# {"text": "...", "duration_seconds": 41.2, "request_id": "...", "seconds_billed": 41.2}Languages
Each page shows what Valmiki STT returned for that language in our tests, unedited, with a demo you can try without an account.
Choosing an API
We sell one, so read this as a checklist to apply to every option, us included. The right choice depends on your audio and your languages, not on a ranking.
Accuracy on studio audio says little about 8 kHz phone calls, voice notes or a noisy shop floor. Send 20 to 50 real clips to each API you are considering and compare the transcripts with what was actually said.
For Indian languages, the same words can come back in the native script or in Latin letters. Decide which one your system needs, and check each API returns it consistently. Our own language pages show where Valmiki varies.
If callers mix Hindi and English, find out whether you must pick one language per request or whether the API detects switches. A fixed-language setting often drops or mangles the other language's words.
Per second, per 15-second block and per minute rounding give different bills for short clips. For streams, ask whether you pay while the connection is open and silent.
For voice agents, time from the end of speech to the final transcript matters more than file throughput. Measure it from the region your servers run in.
Some APIs return word timestamps, speaker labels or confidence scores, others text only. Valmiki STT returns the text, the audio duration and the seconds billed; it does not return word timestamps or speaker labels.
Need speech the other way? Pāṇini text to speech reads text aloud, and Vyas LLM handles the reasoning in between. All three are on the pricing page.
FAQ
$0.00525 per minute of audio, billed per second. A 30-second recording costs half a minute. Rejected audio (wrong format, too long, unreadable) is not billed.
10,000 free text-to-speech characters and one free voice clone that speaks every language, no card required. Transcription is billed at $0.00525 a minute, by the second. You can also try Valmiki STT without an account on any speech to text language page.
Use requests to POST a file to /v1/transcribe and read text from the JSON reply, or websockets to stream 16 kHz PCM to /v1/transcribe/stream and read final events. Both snippets are on this page and run as they are once you add your key.
Yes. The language is detected automatically, including audio that switches between languages, so there is nothing to configure for Hindi-English or other code-mixed speech.
Yes, inside your own app. The streaming endpoint returns text as the person speaks. Sonex Labs does not offer a voice-typing keyboard or consumer app.
Yes. Send an Idempotency-Key header; a retry within 10 minutes returns the same transcript with seconds_billed of 0.
Create a key, send a file, read the transcript. Every language is available from the first request.