Use case · Live captions
Speech-to-text for live captions
Live captions need two things: words on screen while people are still talking, and a clean final line as soon as they stop. Wire-1, Saidwire's real-time English speech-to-text model, sends interim results continuously and the final transcript fast: 50 ms p95 from the end of speech, 1st of 29 on mean time to final segment in Coval's STT benchmark (30-day window to Nov 9, 2026). On clean speech its mean was 36 ms; on far-field microphones, 37 ms. Source: Coval model page, 30-day window to Nov 9, 2026, 2,857 samples, US-hosted endpoint. Add your own network round trip. Method and how to reproduce.
The caption model: interim, then final
- Interim results (
is_final: false) replace each other while the person speaks. Show them in a lighter style on the current line. - Finals (
is_final: true) carry case, punctuation and word timings, and never change. Commit the line and start a new one. speech_final: truemarks a pause in speech, a natural place to break a caption block.
Keep the key on your server
API keys belong on a server. A small relay receives the microphone or venue audio, streams it to Saidwire and pushes caption lines to viewers:
// npm install ws
const WebSocket = require("ws");
const stt = new WebSocket(
"wss://api.saidwire.com/v1/listen?encoding=linear16&sample_rate=16000" +
"&interim_results=true&punctuate=true&endpointing=500",
{ headers: { Authorization: `Token ${process.env.SAIDWIRE_API_KEY}` } });
stt.on("message", (raw) => {
const m = JSON.parse(raw);
if (m.type !== "Results") return;
const text = m.channel.alternatives[0].transcript;
if (!text) return;
broadcast({ text, final: m.is_final, start: m.start }); // send to viewers
});
// feed 20-100 ms frames of 16-bit PCM as they are captured:
function onAudio(frame) { if (stt.readyState === WebSocket.OPEN) stt.send(frame); }
// when the session ends:
function end() { stt.send(JSON.stringify({ type: "CloseStream" })); }
In the browser, render the committed lines plus one interim line; when a final arrives for that line, replace the interim text with it.
Audio formats
Linear PCM from 8 to 48 kHz, μ-law or A-law telephone audio, or a WAV, Ogg, WebM, FLAC or MP3 stream if you omit encoding. One channel per stream; for several speakers on separate microphones, open one stream each and label the lines yourself.
Options for captions
| parameter | what it does |
|---|---|
keyterm= | speaker names, company names and jargon spelled the way you wrote them |
numerals=true | "fifty percent" becomes "50%", "twenty five dollars" becomes "$25" in finals |
utterance_end_ms= | an UtteranceEnd message after this much silence, to close a caption block |
redact=true | masks card numbers, Social Security numbers, phone numbers and emails before they are shown |
Cost
120 free hours with no card and no deadline, up to 4 streams at once, then $0.25 per audio hour, billed per second. A one-hour talk costs $0.25. Streams can run up to 4 hours each.
Questions
How quickly do words appear?
Interim results arrive while the person is speaking; the final line follows the end of speech within tens of milliseconds on the server, plus your network round trip.
Can I put my key in the browser?
Keep keys on a server and relay audio and captions through it.
How long can a caption stream run?
Up to 4 hours per stream. Open a new stream to continue.
Which languages?
English only.
Questions or stuck? Email support@saidwire.com with the request ID from the failed call.
Pipecat, LiveKit, Vapi, OpenAI and the other names on this page belong to their respective owners. They are named only to describe compatibility; no partnership or endorsement is implied. Coval benchmark figures are from Coval's public model page; Coval does not endorse Saidwire.