Skip to content
megapromotingLet's talk

Expertise · Transcription and translation

Speech to text, in Romanian and Russian, with consent recorded before the first second of audio.

We transcribe audio in real time or from file, translate between Romanian and Russian in customer conversations, and deliver the text with timestamps, audio export and a consent trail. We run speech recognition through providers, via our gateway; our own Romanian model is research, not a product.

Already builtTwo in-house implementations, both open and cited. The first is a streaming transcription application, with a 3,378-line Express backend in 25 files and 37 tests we ran today — all pass; it contains the part no one builds out of enthusiasm: a consent gate that refuses capture when there is no recorded consent. The second is running in production, with real clients: voice messages received on messaging channels are transcribed, and the written reply by an operator in Romanian is rewritten into the client’s language before it is sent. What does NOT count as “delivered” and is written as such on the page: our own speech recognition and synthesis model in Romanian is research — it has no public demonstration, no application programming interface, and in Romanian accuracy it loses to large commercial systems. The service is sold on what runs, not on what we study.

Transcription seems like a solved problem until you put it into Romanian, with two speakers interrupting each other, numbers spoken quickly, and a client who switches to Russian halfway through the sentence. Then the three real problems appear: which model you choose for the language in front of you, how you know where one turn of speech ends, and who gave you permission to record. We handle all three, and the last one we treat as a code problem, not as a paragraph of policy.

In our streaming transcription application, the browser never receives the provider key. It asks the backend for a one-time token, valid by default for a quarter of an hour, with which it opens the transcription connection; the route that issues the token is closed by default and can be opened only through an explicit setting outside production, precisely because it is the route through which money is spent. On top of the raw transcription runs an analysis based on a language model, with a fallback list of models in order, so that the unavailability of one does not stop the session.

The consent gate is the part we pay particular attention to. Before accepting an audio segment, the server requests one row of unrevoked consent for that session. If none exists, it responds with 451 and a message in Romanian. If the database does not respond, it refuses everything — 503, not “let it pass”. Sessions already verified pass through a ten-minute cache, so a brief outage does not interrupt an ongoing recording. It is written so it cannot be bypassed by a configuration mistake.

The part that is already with clients is different and less spectacular: on messaging channels, a received voice message becomes text, and the language is chosen by voting on the last eight messages in the conversation, not by guessing from the audio. In the other direction, when a colleague replies in Romanian, their text is rewritten in the client's language with strict instructions — it does not add information, does not invent prices or deadlines, does not contradict the operator, and treats the operator's text strictly as data to be transmitted, never as instructions for the model.

What it covers

The work, by component

Consent, checked before audio

The consent gate requires an unretracted row in the agreements register for the current session. Without it: 451, with a message in Romanian. With the database down: 503, that is, refusal, not passage. Sessions already verified pass through a 10-minute cache, so verification does not hit the database for every piece of audio.

One-time token, the key stays on the server

The page asks the backend for a token for real-time transcription, valid by default for 900 seconds, and with it opens the connection to the provider. The account key never reaches the browser. The request to the provider has a timeout of 30 seconds, and exceeding it returns an explicit error, not an infinite wait.

Streaming transcription, with the language chosen from context

In production, on messaging channels, the language of the voice message is decided by vote on the last eight messages of the conversation — Russian if it dominates, otherwise Romanian — and only then is recognition called, with the language hint sent explicitly. The file format is recognised from the first 12 bytes, not from the extension, because voice messages on Meta channels come as `ogg` whatever they are named.

Operator → client translation, with the boundaries written in the prompt

When a colleague replies in Romanian in an internal thread, the message to the client is rewritten in the client's language. The rules are explicit in the code: it does not add information, does not invent details, prices, times or promises, does not contradict the operator, and the operator's text is treated strictly as data to be transmitted, never as instructions for the model — a measure against prompt injection, not a style formulation.

Analysis over the transcript, with fallback models in order

A language model analysis runs over the resulting text, with an ordered list of alternative models in code, so that unavailability degrades quality, not stops the session. The analysis model can be changed from configuration, without redeployment.

Audio export in three formats, with explicit failure

WAV is produced without external tools. FLAC and MP3 require `ffmpeg`; if it is missing, the server responds 501 with the reason, and if the process hangs it is stopped after 60 seconds and returns 504 with the first two thousand characters of the error. A failed export says why.

Separate counting for quota and cost

Consumed minutes are deducted atomically through a procedure in the database, and the cost is written in a separate register, by provider. They are two different things and break differently: if the cost row cannot be linked to the session, it is saved unlinked, so the cost information is not lost.

Three traffic thresholds, per user and not per address

Token issuance, analysis and export have separate limits, and the counting key is the authenticated user when there is one, not the IP address — otherwise a single aggressive user behind a shared network would exhaust the quota of all their colleagues.

Transcription on messaging channels, in the existing flow

The voice message received from a client becomes text in the same conversation, without anyone opening another tool. Recognition and synthesis go through our gateway, not directly to the provider, so consumption appears in the same place as the rest.

What it looks like

The path, step by step.

01

We establish the right to record, before any code

Who is speaking, who is informed, who consents, who keeps the recording and for how long. The result is not a document that sits in a drawer, but the gate configuration: what exactly “existing consent” means in the client’s situation and what happens when it is missing.

02

We choose the chain by language and sound conditions

Romanian and Russian behave differently, as does a desktop microphone versus a compressed phone call. The choice of model, language index and segmentation strategy is made on samples from the client’s real material, not on a clean demonstration.

03

We put the flow together and break it on purpose

Token, connection, transcription, analysis, export. Then we check the cases that actually happen: missing consent, database down in the middle of the session, expired token, `ffmpeg` absent, provider unavailable. Each must return a message saying what broke.

04

We deliver with counters and limits turned on

Minute metering, cost register, traffic thresholds per user and logs. Without them, the first incident is discussed from memory.

IntrareVerificareDeciziePublicareNothing passes on unverified.ORDER IS THE ARGUMENT
Five steps, in the order in which they are executed: the agreement checked in the register (without it, the road stops here); the one-time token issued by the server, with the key remaining on the server; the transcription in the stream at the provider; the analysis over the transcript, with fallback models in order; the export of the text and the audio. The first step is the only one that can stop everything else, and it is drawn as a gate, not as a stage.

The data

What we touch, where it lives, and how long it stays

The questions anyone with a data protection officer would ask — asked here before they do.

Consent register
One row per session, with the workspace, session identifier and revocation moment, empty while the consent is valid. The check looks specifically for the absence of revocation. It is the single source of truth for the right to capture audio, and it is queried before every session, not only at sign-up.
Audio, transcript and analysis
The raw audio goes through the transcription connection to the provider; what is kept with us is the transcript, timestamps and analysis result, plus the exports requested by the user. What is kept and for how long is set per project, before the first recording — for a board, a medical meeting and a sales call, the answers are not the same.
Where the audio goes and to whom
To speech recognition providers and to the analysis model, through our gateway. Their list is written in the contract before launch, with each name, because an undeclared sub-processor is a legal issue, not a technical omission.
Consumption register
The minutes consumed are deducted atomically in the database, and the cost is written separately, per session and per provider. These are two separate registers precisely so that an error in one does not falsify the other.
What we do not touch
We do not train models on the client’s recordings and we do not use a voice provider’s output to build or test a competing model — this is explicitly forbidden in the provider’s terms we use, and it is a limit we respect even where it would be technically convenient.

A case

A session that does not start, and why that is the correct behaviour

The situation

A multi-participant meeting scenario, in which transcription was supposed to start from the browser, and the recording was to be kept. The situation that breaks most transcription tools: someone presses “record” before the participants’ consent has been recorded anywhere.

What we built

I put the consent check on the request path, not in a warning screen. The server looks for a non-revoked consent row for the current session before accepting the first piece of audio. I wrote the failure behaviour deliberately too: if the database that holds consents does not respond, the request is rejected with 503, not allowed through. Sessions already verified stay in cache for ten minutes, so a short outage does not interrupt an ongoing recording. The route that issues tokens to the provider has been closed by default, with opening possible only through an explicit setting outside production.

What came out

Without recorded consent, the capture returns 451 with a message in Romanian and the event is logged with the session and workspace. The behaviour is covered by tests that run without a database, by injecting the check. The backend suite has 37 tests; in today’s run they all pass.

What the case does not say

The application is not published — it runs on our side, it has no page to sign up on, and the right to record a given conversation remains with the client: we enforce it technically, we do not grant it. And one more limitation: the gate checks for the existence of consent, not its legal quality. If the consent text is poorly written, the code will apply it faithfully.

Questions

What people ask us before they call

Which languages do you transcribe?

We work with Romanian and Russian, because these are the languages in which our real issues appear and which we can verify on our own material. Other languages are technically possible through the same providers, but before we promise anything we do a trial on your recordings — a language works or does not work depending on the audio, not on the list on the provider’s page.

Do you have your own speech recognition model for Romanian?

In research, not in the product, and it is important not to confuse the two. The in-house direction has no public demo, no programming interface and no telephony, and on Romanian recognition accuracy our measurements show that we lose to the large commercial systems. We publish this because it is our conclusion, obtained on our own test bench. The service we sell today runs on providers, through our gateway.

Who is allowed to record a conversation and what do you do if they are not allowed?

The right is set on a case-by-case basis with the client before installation — it is not something we can transfer ourselves. What we do is enforce it in code: without a recorded consent for the current session, the server rejects the capture with 451 and a message in Romanian. If the database that holds consents does not respond, it refuses then too, with 503. There is no configuration that turns the absence of consent into a silent pass-through.

Does my provider key end up in the browser?

No. The page asks the backend for a single-use token for the transcription session, valid by default for 900 seconds, and opens the connection with it. The account key stays on the server. In addition, the route that issues tokens is closed by default and can be opened only through an explicit setting outside production, because it is the route that consumes money.

How accurate is the transcription?

It depends more on the audio than on the model: microphone, overlaps, digits, proper names, background noise. We do not give you a percentage before we hear your material, because a percentage taken from a product sheet says nothing about your meetings. What we do is a trial on real recordings, with the errors laid out plainly — usually it fails on digits and names, not on sentences.

Do you translate conversations in real time between operator and client?

Yes, and it is already running in production in one direction: the colleague types the reply in Romanian, and the message goes to the client in the client’s language. The rules are strict in code — no added information, no invented prices or deadlines, no contradicting the operator. The reverse direction, from client to operator, is handled today by transcribing voice messages; automatic translation of the client’s text to the operator is not switched on everywhere, and we say that before, not after.

What audio formats do you accept and what do I get back?

The format is recognised from the file content, not from the extension — WAV, OGG, MP3 and M4A are handled explicitly, and voice messages from messaging channels usually arrive as OGG. You get the transcript, analysis if requested, and exported audio: WAV without dependencies, FLAC and MP3 if `ffmpeg` exists on the server. If it does not exist, the server says so with a dedicated code, not a generic failure.

Do you use our recordings to train your models?

No. In addition, we do not use the voice providers’ output to train or test a competing model either — their terms of use explicitly forbid it, and we respect them even in our own research direction, where it would have been convenient not to.

What happens when the transcription provider fails in the middle of a meeting?

The session stops with an error that names the cause, not with a blank screen. For analysis, there is an ordered list of backup models in the code, so there unavailability degrades quality instead of stopping the flow. For real-time speech recognition we do not have automatic redundancy between providers, and that is a real limitation, not an omission.

What the statements above rest on (14 sources)
  1. The voice provider's terms prohibit training or testing a competing model on its outputhttps://elevenlabs.io/use-policy · 2026-09-06

13 of them are code and files from our repositories. We don't publish their name or line: together, on a single page, they would describe too precisely how systems that aren't only ours are built. We go through them with you, in the repository, on request — verification stays possible, it just happens in a conversation.

What would you want to work better?

Tell us about your process. Together we decide what is worth building, what we can connect, and how we check the result.

Let's talk