← Blog

Featured guide

How to transcribe Russian speech to text via API: a step-by-step guide

Speech-to-text (STT) turns audio into structured text: words, timestamps, and speaker labels. This guide walks the full path – from how STT works and why Russian is harder than English, to a working Python script that returns a second-accurate transcript. We also cover diarization, subtitle export, and the mistakes that trip people up during integration.

Why transcription matters

Manual transcription is slow, expensive, and error-prone. An hour of audio takes a person three to five hours, and on long recordings with several voices, accents, and technical vocabulary mistakes are unavoidable: fatigue, unfamiliar terms, missed lines. An STT API handles the same volume in minutes and returns structured output right away – every word mapped to the second it was spoken.

Typical scenarios: call-center call logging and service quality monitoring; subtitles for video, webinars, and social clips; interview, podcast, and meeting notes; audio labeling for machine learning; pronunciation checking in EdTech. The common thread is the same – you need a text result fast, cheaply, and with timestamps so you can jump to a moment instead of re-listening to the whole recording.

Russian is harder here than English. It has more word forms – cases, declensions, conjugations – free word order, and a huge number of proper names, surnames, and abbreviations. So the first thing to check is real accuracy on Russian speech, not the numbers from marketing tables.

How speech recognition works

A modern STT is a neural network trained on thousands of hours of labeled speech. The input file is split into short windows, each turned into a spectrogram – a picture of how frequencies change over time – and the model predicts a sequence of characters or words from it. The result then passes through a language model that adds punctuation and picks meaningful words instead of random sound combinations.

Quality is measured with WER (word error rate), the share of words recognized incorrectly. A WER of 5% means every twentieth word is wrong. On real calls with noise and multiple speakers, WER is usually higher than on clean studio recordings, which is why honest services state what data their accuracy was measured on and let you test it on your own file.

The second important piece is timestamps and confidence. A good API returns not just text, but time-bounded segments and a confidence score for each word. That lets you highlight uncertain spots instead of proofreading the entire text, and build review UIs around them.

Self-hosted Whisper or a managed API?

You can run the open-source Whisper model on your own server. It's popular when volumes are large and steady and privacy requirements are strict. But the hidden cost is real: you need a GPU or a beefy CPU, plus maintenance, model updates, queues, and monitoring. A spike in load means buying hardware, not just moving to the next plan.

A managed API removes all the infrastructure: you pay per minute of audio rather than for idle servers. That pays off at the start and with variable load, when the exact volume is unknown. And production STT is more than a model – it's also timestamps, diarization, subtitles, and audio cleanup, which you'd otherwise have to assemble yourself.

The rule of thumb: if you have a steady few hundred hours a day and an infrastructure team, self-hosting is worth a look. If volumes fluctuate and time-to-launch matters, an API earns its keep by cutting integration to hours instead of weeks.

How to choose an API

Compare providers on five criteria. Accuracy: WER on Russian, ideally on data similar to yours – calls, interviews, or lectures. Price: count per minute of audio, not per request, and watch the minimum spend. Russian support: the model should be trained on Russian speech, not just "speak a bit of everything". Features: word-level timestamps and diarization – marking who is speaking. Speed: short files need a synchronous answer in seconds, long files need async jobs with status polling.

Voice kit API covers all of these out of the box: Russian with no extra setup, per-word timestamps, speaker diarization, and streaming transcription over WebSocket for live calls. Details and prices – see pricing.

Getting an API key

Sign up in the dashboard – the key is created automatically and shown in the API section. The Free plan includes 150 audio minutes per month – enough to run the integration on real files and measure accuracy before you buy.

Send the key in the X-Api-Key header on every request. Don't hardcode it in source or commit it to a repository – use environment variables or a .env file that never enters git. If the key shows up in logs or leaks, rotate it in the dashboard: the old one stops working immediately.

Python code

Install the SDK with one command – or call the API with plain HTTP requests. The fastest option for short files is the synchronous method, which returns the result immediately:

bash
pip install voicekit-client
Python
from voicekit import VoiceKitClient

client = VoiceKitClient(api_key="rtt_…")

transcript = client.transcribe_sync("meeting.mp3")
print(transcript["transcript"])

for segment in transcript["segments"]:
    print(segment["start"], segment["end"], segment["text"])

For longer recordings – a couple of minutes and up – use the asynchronous mode: upload the file, get a job_id, and poll the status until it becomes completed or failed:

Python
job = client.transcribe("meeting.mp3", language="ru", diarization=True)
result = client.get_transcription_job(job["job_id"])
while result["status"] not in ("completed", "failed"):
    result = client.get_transcription_job(job["job_id"])

print(result["transcript"])

The language parameter hints the model at the recording's language, and diarization turns on speaker labels – more on that below. If you know the language in advance, pass it explicitly: it almost always improves accuracy on short and ambiguous phrases.

Which mode to choose? Synchronous fits files up to three minutes: one request, one response, no status polling. Asynchronous is for long recordings and batches: you send the upload, the service processes in the background, and you fetch the result when it's ready. In async mode you can add a webhook – a URL that receives a notification on completion – so you don't have to poll manually.

What the API returns and how to read it

The response contains transcript – the full text – and segments, a list of time-bounded slices. Each segment contains words – word-level timestamps word, start, end, and confidence:

JSON
{
  "transcript": "Сегодня мы обсудим план запуска.",
  "segments": [
    {
      "start": 0.0,
      "end": 4.2,
      "text": "Сегодня мы обсудим",
      "speaker": "Speaker 1",
      "words": [
        {"word": "Сегодня", "start": 0.0, "end": 0.9, "confidence": 0.98}
      ]
    }
  ]
}

With diarization on, each segment also has a speaker – the model marks who is talking. For calls and interviews this lets you group the text by participant.

Watch the confidence value: highlight low-confidence words in your UI so an operator can quickly double-check the uncertain spots instead of proofreading the whole text.

Diarization: who is speaking

Diarization answers "who was talking at this moment". The model splits the recording into utterances and assigns speaker labels, even without knowing their names – Speaker 1, Speaker 2, and so on. You map names to labels yourself if you know them.

Turn it on with a single parameter, diarization=True. It fits support calls, interviews, negotiations, and meetings: instead of a wall of text you see a dialog with attribution.

Subtitles and export

For video and webinars you don't have to assemble SRT files from timestamps by hand. Call GET /v1/transcribe/{job_id}/subtitles?format=srt – the service returns a ready subtitle file you can attach to a YouTube video or any player.

SRT and VTT are both supported. SRT is the universal format for video editors and hosts; VTT suits web players and supports styling. Both are built from the same timestamps as the regular response, so nothing extra needs configuring.

Errors and limits

Main codes: 401 – wrong or revoked key, 413 – file too large, 429 – plan limit exceeded. Handle them in code: on 429 pause and retry with exponential backoff, on 401 rotate the key.

The full list of codes, limits, and request examples – see the docs.

How to improve accuracy

Audio quality matters more than switching models. Record at 16 kHz and above, without heavy compression or echo: 64 kbps MP3 is noticeably worse than WAV or 192+ kbps. One speaker per channel and minimal background noise help more than any setting.

If you know the language, pass language explicitly – the model skips detection and makes fewer mistakes on short phrases. Turn on diarization only when there are multiple speakers: on a monologue it's unnecessary and can add errors.

For phone recordings use the 8 kHz mono format standard in telephony, and don't upscale it to 16 kHz – that adds no quality, only file size. Long recordings with interruptions and pauses are worth splitting into logical chunks before upload if you want maximum accuracy.

Common integration mistakes

First, forgetting the X-Api-Key header or confusing it with a query parameter. The key goes in the header only; never put it in the URL, or it will end up in proxy logs and browser history.

Second, polling async job status without a pause. Hundreds of requests per second won't speed up processing, but will quickly hit the 429 limit. Sleep between polls or use a webhook to get the result as soon as it's ready.

Third, not checking file size and format before upload. The service accepts wav, mp3, ogg, and flac with a size limit; a gigabyte of video is better converted to audio before upload, otherwise the request fails with 413 before recognition even starts.

Start for free

The Free plan includes 150 audio minutes per month – no card required. Create a key and transcribe your first file in five minutes.

Get free transcription minutes
← All articles