Sonex Labs

Developers · Valmiki speech to text

Speech to text API for Python and REST

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.

transcribe.py
1# pip install requests
2import requests
3
4with 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 spoken
16print(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

One endpoint per job, no language settings.

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.

Streaming or from a file

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.

Common formats accepted

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.

Billed by the second

$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

Stream live audio, read text as each sentence ends.

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.

stream.py
1# pip install websockets
2import asyncio, json, wave
3import websockets
4
5async 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 pass
12 with wave.open("call-k.wav", "rb") as w: # 16 kHz mono 16-bit PCM
13 while frame := w.readframes(1600): # 100 ms per frame
14 await ws.send(frame)
15 await asyncio.sleep(0.1) # send in real time
16 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 break
24
25asyncio.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

Or POST the file with cURL.

Send the audio as the request body with its Content-Type, or as a multipart upload under file.

transcribe.sh
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'
5
6# {"text": "...", "duration_seconds": 41.2, "request_id": "...", "seconds_billed": 41.2}

Choosing an API

How to choose a speech to text 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.

Test on your own audio, not a demo clip

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.

Check the script of the output

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.

Check how mixed-language speech is handled

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.

Compare the billing unit, not just the rate

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.

Measure streaming latency yourself

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.

Know what the response contains

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

Speech to text, answered.

$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.

Transcribe your first recording in a minute.

Create a key, send a file, read the transcript. Every language is available from the first request.