Introducing real-time transcription for Swedish

Co-founder & CPTO

When you caption a meeting or brief a voice agent, text has to arrive while people are still speaking. Until now, transcribing Swedish meant recording the full audio and waiting for the batch.
Today that changes — not as a model release, but as a platform capability. Real-time transcription is now part of the Berget AI API: audio streams in over a WebSocket, text starts arriving while people are still speaking, not after the recording stops, and the finished transcript lands when the stream ends. Applications that used to wait for a recording can react in the moment.
The first model on the endpoint is Klang Pianissimo, announced today by the Swedish speech AI company Klang in their press release. It's a fine-tune of NVIDIA Parakeet, trained for Swedish and Swedish dialects: in Klang's tests it reaches around 3,600× real time — an hour of audio in about a second — with accuracy comparable to KBLab/kb-whisper-large. Full numbers and their caveats are below.
The real-time endpoint is compatible with the OpenAI API. If your application already streams audio to a US provider, moving it to Berget AI is a base URL and an API key away — a working example is at the end of this post.
What it's for
Live transcription earns its keep in conversations that can't stop for a note-taker: meetings captioned as they happen, board minutes drafted while the board still sits.
The same live stream enables applications beyond meetings. Service apps can put voice control into field work: a technician talks to their systems while their hands are busy with the job. And for hearing-impaired users, live captions are the difference between taking part in the conversation and reading about it afterwards.
None of this works if the model only understands studio Swedish. Pianissimo is trained for Swedish as it's actually spoken, dialects and accents included: a Skånska vowel or a strong second-language accent is Swedish to transcribe, not noise to clean up.
It matters just as much for conversations that are sensitive in themselves: patient calls, legal consultations, anything under professional confidentiality. Audio like that is personal data, and where it's processed isn't a detail. On Berget AI the audio never leaves Swedish jurisdiction and isn't subject to the US CLOUD Act or FISA 702. Nothing is stored: not the audio, not the transcript, and no training on any of it.
If you're not a developer, this reaches you through the products you already use. The endpoint implements the OpenAI protocol, so a meeting or note-taking tool can route its transcription to Berget AI without changing anything you'd see. The interface stays theirs; the audio is processed in Sweden. If you rely on such a tool, ask your vendor where its audio goes today.
What the benchmarks show
Klang sent these benchmarks along with the model, and one thing is worth naming before reading them: they're Klang's numbers, and we host the model and sell access to it — so we're not a neutral party here. Common Voice test/dev and FLEURS are public benchmarks; Klang dialects is a dialect test set they collected themselves.
Word recognition accuracy by dataset
Data: Klang · accuracy = 100 − WER · higher is betterCommon Voice test/dev and FLEURS are public benchmarks; Klang dialects is a dialect test set they collected themselves.
| Model | FLEURS | Common Voice test | Common Voice dev | Klang dialects | Mean |
|---|---|---|---|---|---|
| Klang Pianissimo | 6.51 | 4.46 | 4.46 | 4.85 | 4.45 |
| kb-whisper-large | 5.08 | 3.91 | 3.96 | 2.30 | 3.52 |
| kb-whisper-medium | 6.58 | 5.40 | 5.27 | 3.58 | 4.87 |
| parakeet-tdt-0.6b-v3 | 15.18 | 18.54 | 17.47 | 25.82 | 17.70 |
Word error rate (WER), lower is better. Best value per metric is highlighted. Source: Klang.
The caveats matter as much as the means. KBLab/kb-whisper-large is still the most accurate on every dataset, and for transcribing a finished recording it remains the right choice. Real time is a different job: it needs tokens pinned to 80 ms of audio and infrastructure that streams. As of today, Berget AI has both.
Pricing follows the rest of the API: pay-as-you-go, billed per second. Pianissimo is €3.50 per 1,000 minutes of audio, so an hour-long meeting costs about €0.21. Every model's rate is listed on the pricing page.
Pianissimo is available from today through api.berget.ai. It's also the first of several open models Klang plans to release — and it's Swedish-trained only, so for other languages the existing speech-to-text models are still the right call, with Danish and Norwegian versions planned next per Klang's roadmap.
There's a small pattern worth naming on the way out. This is the second Swedish model we host, and both are fine-tunes of open American base models — this one takes NVIDIA Parakeet, built for a different market, and teaches it to understand Swedish properly. We'd like to see many more of that kind: Swedish, Nordic, or European models, each getting genuinely good at something specific. Open weights are what make that possible; serving them well from here is our part of the work.
We hope you get a lot of use out of this model — and that it helps something new get built in Sweden. Together, we're stronger.
Working example
This streams a file over WebSocket with the official OpenAI Node SDK (npm install openai ws), showing both the partial transcripts as speech is recognised and the finished transcript when the stream ends:
import { readFileSync } from 'fs';
import OpenAI from 'openai';
import { OpenAIRealtimeWS } from 'openai/realtime/ws';
const client = new OpenAI({
apiKey: process.env.BERGET_API_KEY,
baseURL: 'https://api.berget.ai/v1',
});
const rt = await OpenAIRealtimeWS.create(client, { model: 'klang/pianissimo' });
rt.on('error', console.error);
// partial transcripts as speech is recognised
rt.on('conversation.item.input_audio_transcription.delta', (event) => {
process.stdout.write(event.delta);
});
// full transcript once the stream ends
rt.on('conversation.item.input_audio_transcription.completed', (event) => {
console.log('\n' + event.transcript);
});
// the SDK doesn't buffer sends, so wait for the session to open
rt.on('session.created', () => {
rt.send({
type: 'session.update',
session: {
type: 'transcription',
audio: {
input: {
format: { type: 'audio/pcm', rate: 24000 },
transcription: { model: 'klang/pianissimo', languages: ['sv'] },
},
},
},
});
// stream a file in 200 ms chunks (24 kHz mono, 16-bit PCM), then commit exactly once
const pcm = readFileSync('audio.pcm');
const chunkBytes = 4800 * 2;
let offset = 0;
const timer = setInterval(() => {
const bytes = pcm.subarray(offset, offset + chunkBytes);
offset += bytes.length;
if (bytes.length === 0) {
clearInterval(timer);
rt.send({ type: 'input_audio_buffer.commit' });
} else {
rt.send({ type: 'input_audio_buffer.append', audio: bytes.toString('base64') });
}
}, 200);
});