OpenTranscription
OpenTranscription
RankerModelsPlayground
OpenTranscription
OpenTranscription

One API to every speech-to-text model worth using. Compare them on your audio, route to the best one, pay per second.

Platform status

Product

RankerModelsTranscriptionsPlaygroundBlog

Developers

DocumentationReliabilityAPI VersioningStatus

Legal

Privacy PolicyTerms of ServiceSupport
© 2026 OpenTranscription
Back to Models$0.0017/min

MAI-Transcribe-2 (preview)

Microsoft Azure

Batch

Microsoft MAI-Transcribe-2 — Microsoft AI's in-house transcription model, in public preview on Azure Speech. 60 languages with automatic language detection and mid-sentence code-switching, speaker diarization, word-level timestamps and custom vocabulary. Accepts WAV, MP3 and FLAC.

Transcribe with this modelCompare in playground

59 languages · benchmarked

About MAI-Transcribe-2 (preview)

MAI-Transcribe-2 (preview) is a speech-to-text model from Microsoft Azure. In our standardized benchmarks it reaches 7.72% word error rate, ranking #1 of 36 models tested. It supports 59 languages and runs at $0.002/min — cheaper than most alternatives.

Its nearest benchmarked alternative is Whisper Large V3 Turbo. Best suited for multi-speaker conversations, multilingual workloads, accuracy-critical work, and high-volume, cost-sensitive pipelines.

Overall Score

90.0

#1 of 36

Word Error Rate

7.72%

Character Error Rate

6.03%

Match Error Rate

6.92%

Word Info Lost

10.12%

Avg Latency

912ms

Benchmarks Run

35

Cost vs. accuracy

overall WER · 36 models

MAI-Transcribe-2 (preview)

field · 35 models

lower-left is better

Performance by category

8 categories

WER

lower is better

Technical

1.1%

Medical

2.1%

Legal

2.9%

General

5.0%

Conversational

5.2%

Finance

7.1%

Code-Switching

16.4%

Noisy Environment

26.3%

CategoryWERCERMERWILLatencyBenchmarks

Code-Switching

16.42%
11.03%
15.86%
20.58%

1.1s

2

Conversational

5.18%
2.98%
5.03%
6.82%

980ms

2

Finance

7.11%
3.68%
7.03%
11.62%

1.1s

2

General

5.03%
4.87%
4.97%
8.06%

876ms

19

Legal

2.93%
1.72%
2.86%
3.91%

931ms

2

Medical

2.10%
0.93%
2.10%
3.22%

931ms

2

Noisy Environment

26.25%
19.23%
19.97%
26.37%

761ms

4

Technical

1.13%
0.50%
1.13%
1.59%

1.1s

2

Performance by accent

5 accents

AccentWERBenchmarks

African

24.62%

1

Australian

1.54%

1

Indian

9.52%

1

British

1.49%

1

American

5.66%

1

Pricing

pay per second

Rate

$0.0017

/min

Per-second billing. Bring your own provider key and pay your provider directly — a 5% routing fee applies (first 100 min/mo free).

Set up BYOK

Cost estimator

1 hour

$0.10

10 hours

$1.01

100 hours

$10.08

1,000 hours

$100.80

Billed per second of audio processed.

API & usage

POST /api/v1/transcriptions

Model ID

azure/mai-transcribe-2

Get an API key

Authenticate every request with your secret API key as a Bearer token. Issue a key from your dashboard.

Use it with your agent

Paste this into Claude Code, Cursor, Codex or any agent with a shell. It installs the CLI and the OpenTranscription skill, then transcribes with this model.

Transcribe an audio file for me with OpenTranscription, using the model azure/mai-transcribe-2.
Set it up first:
npm install -g @opentranscription/cli
ot login
npx skills add opentranscription/skills
Then run:
ot transcribe <my-file> --model azure/mai-transcribe-2
Ask me one question at a time, and give me options to pick from rather than open questions. Look for audio files here before asking which one I mean. Leave the language alone unless I tell you what it is, since the model detects it.
This model can also label speakers with --diarize, and take a vocabulary of names and jargon with --vocab "Kubernetes,Sanjay". Offer those one at a time, and only if I have not already said.
The login step opens my browser and waits for me to approve it, so stop and tell me when you reach it. The skill covers the rest.
Agent SkillTypeScript SDKPython SDKCLI on npm

Quickstart

Upload your audio, create a job with this model, then poll the job or set a webhook_url to be notified when it completes.

// npm install @opentranscription/sdk
import { readFile } from 'node:fs/promises';
import { OpenTranscription } from '@opentranscription/sdk';
const ot = new OpenTranscription({ apiKey: process.env.OT_API_KEY! });
// Uploads the audio and opens the job. The signed-URL round trip is inside.
const job = await ot.transcribe({
file: await readFile('interview.mp3'),
fileName: 'interview.mp3',
model: 'azure/mai-transcribe-2',
language: 'af',
diarization: true,
customWords: ['Kubernetes', 'Grafana', 'Sanjay Bhattacharya'],
webhookUrl: 'https://your-app.com/webhooks/ot',
});
// We POST a signed event to that URL when the job finishes: no polling required.

Key parameters

file_path

string

required

Storage path returned by the upload step.

model

string

required

The model to run this job on.

models

string[]

Ordered fallback chain: primary first, then backups tried in order if a provider fails.

language

string

ISO 639-1 language code. Omit to auto-detect.

diarization

boolean

Label speakers (A, B, …) in the output.

word_timestamps

boolean

Per-word start, end and confidence. Defaults to true; send false to leave them out.

custom_words

string[]

Names, jargon and product terms to bias the model toward. Up to 1000 entries.

vocabulary_list_id

uuid

A vocabulary list saved in your workspace. Merged with custom_words when both are sent.

webhook_url

string

HTTPS URL notified with the result when the job completes. Delivered events are signed (X-OT-Signature).

title

string

Display name for this job in the dashboard. Falls back to the file name.

Response

A completed job returns the transcript in the OpenTranscription Unified Schema (OTUS).

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"transcript": {
"text": "Welcome to the meeting, everyone.",
"language": "en",
"confidence": 0.97,
"segments": [
{
"id": 0,
"start": 0,
"end": 3.5,
"text": "Welcome to the meeting, everyone.",
"speaker": "A"
}
],
"word_timestamps": "available",
"words": [
{
"text": "Welcome",
"start": 0,
"end": 0.42,
"confidence": 0.99
}
]
}
}

Webhooks — skip polling

We POST a signed event to your webhook_url when a job completes or fails; verify the X-OT-Signature (HMAC-SHA256, reject if older than 300 s) and dedupe on the event id, then fetch the full transcript via GET /api/v1/transcriptions/{id}.

import { createHmac, timingSafeEqual } from "node:crypto";
// Your signing secret from Settings → API keys.
const SECRET = process.env.OT_WEBHOOK_SECRET ?? "";
function verify(
rawBody: string,
header: string,
nowSeconds = Math.floor(Date.now() / 1000),
): boolean {
const segments = header.split(",");
// Exactly one t= segment, finite, within the replay window.
const tValues = segments.filter((s) => s.startsWith("t=")).map((s) => s.slice(2));
if (tValues.length !== 1) return false;
const t = Number(tValues[0]);
if (!Number.isFinite(t) || Math.abs(nowSeconds - t) > 300) return false;
const expected = createHmac("sha256", SECRET)
.update(`${t}.${rawBody}`)
.digest("hex");
// Header may carry multiple v1 sigs (key rotation). Match any.
return segments
.filter((s) => s.startsWith("v1="))
.some((s) => {
const got = Buffer.from(s.slice(3), "hex");
const exp = Buffer.from(expected, "hex");
return got.length === exp.length && timingSafeEqual(got, exp);
});
}
// Express example. Use the RAW body buffer, not the parsed JSON.
// The X-OT-Signature header carries t=<unix>,v1=<hmac-hex>.
app.post("/webhooks/ot", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["x-ot-signature"] as string;
if (!verify(req.body.toString(), sig)) {
return res.sendStatus(400);
}
const event = JSON.parse(req.body.toString());
// Dedupe on event.id (at-least-once delivery), then enqueue + return 2xx fast.
res.sendStatus(200);
});
Get your signing secret

Rate-limited per tier — see the X-RateLimit-* response headers.

Full API reference

Reliability

rolling 30 days

Uptime · 30d

100.00%

Error rate

0.00%

Avg latency

2.1s

Last incident

None in 30d

Similar models

from the same field

Cheaper

Whisper Large V3 Turbo

Groq

14.31% WER

$0.0007/min

Compare →

Compare MAI-Transcribe-2 (preview) with…

same benchmark, every match

vs Soniox STT (Async)vs Whisper Large V3 Turbovs Nova-3vs Chirp 3vs Speechmatics Enhancedvs Azure Speechvs Scribe v2vs GPT Transcribevs Gladia Solaria-3vs Qwen3 ASR Flashvs Voxtral Mini Transcribevs Amazon Transcribevs GPT-4o Mini Transcribevs Whisper Large V3 (Groq)vs GPT-4o Transcribe Diarize

Supported Languages

AfrikaansArabicAssameseAzerbaijaniBulgarianBengaliBosnianCatalanCzechDanishGermanGreekEnglishSpanishEstonianPersianFinnishFrenchGalicianGujaratiHebrewHindiHungarianArmenianIndonesianIcelandicItalianJapaneseKazakhKannadaKoreanLithuanianLatvianMacedonianMalayalamMarathiMalaynbNepaliDutchOdiaPunjabiPolishPortugueseRomanianRussianSlovakSlovenianSwedishSwahiliTamilTeluguThaiTagalogTurkishUkrainianUrduVietnameseChinese

Supported Formats

wavmp3flac

Features

Auto-detectDiarizationCode-switching+2

Limits

Max file size

250 MB

Max duration

2 h