Live Translation
VALSEA provides a real-time speech-to-text and translation API via WebSocket — stream audio in one language and receive both the original transcript and a live translation into your target language.
Live Translation is an add-on workflow for applications that need both the original transcript and a translated final transcript. For transcription only, start with Real-time Transcription.
Automatic language detection is the default
valsea-rtt automatically detects the source language by default, so you do not need to select an
input language in advance — language can be omitted from the session.start message entirely.
You can make this explicit by setting language to "auto". Set target_language to the language
you want for final translated transcripts.
{
"type": "session.start",
"model": "valsea-rtt",
"target_language": "english"
}
VALSEA supports 181 languages, dialects, and variants overall; coverage varies by endpoint. Auto-detect supports multilingual conversations and code-switching, including language changes within a conversation or sentence. Partial transcripts remain in the detected source language; completed transcripts are translated into the selected target language.
Connection
Endpoint: wss://api.valsea.ai/v1/realtime/translate
Authentication
You must authenticate the WebSocket connection by passing your API key in the HTTP headers during the handshake.
Headers:
Authorization:Bearer YOUR_API_KEY(Recommended)X-API-Key:YOUR_API_KEY(Supported)
Browser clients can also authenticate with ?api_key=YOUR_API_KEY because standard browser
WebSocket constructors do not support custom headers.
Paid Rate-Limit Bypass
If you need to exceed the realtime connection RPM limit for a session, you can bypass the rate-limit check by sending one of these opt-in flags during the WebSocket handshake:
- Header:
X-Bypass-Rate-Limit: true - Query parameter:
bypass_rate_limit=true - Query parameter:
bypassRateLimit=true
Bypass applies only to the per-organization rate-limit check. Authentication, credit checks, and
session billing still apply. RTT sessions using this bypass are billed at 2x the normal realtime
credit cost. The initial session.created event includes rateLimitBypass: true and
billingMultiplier: 2 when bypass is active. If speaker diarization is also enabled for the session,
the final session cost is 4x the normal realtime credit cost.
Message Flow
- Connect: Client establishes WebSocket connection.
- Session Created: Server sends
session.createdevent. - Start Session: Client sends
session.startto configure language, target language, and model. - Stream Audio: Client sends
audio.appendmessages with base64-encoded PCM16 audio chunks. - Receive Transcripts: Server streams
transcript.partialandtranscript.finalevents —transcript.finalincludes the translation oncetarget_languageis set. - Commit Audio: Client sends
audio.commitwhen a user stops speaking (optional/VAD dependent). - Stop Session: Client sends
session.stopto end the session.
Partial vs Final (Important)
RTT emits two transcript event types for each utterance:
transcript.partial: low-latency, in-progress text in the original language. This can change as more audio arrives. Partials are never translated.transcript.final: stable text for a completed segment — translated, iftarget_languagewas requested. Treat this as the committed result.
Recommended client behavior:
- Keep a temporary
currentPartialstring fortranscript.partial. - Append only
transcript.finalto your persisted transcript history. - Clear
currentPartialwhen you receive a matchingtranscript.final.
Do not persist partial text as final output. Partials are intentionally mutable and may be revised by the engine before a final segment is produced.
Client Messages
session.start
Initialize the session with configuration.
{
"type": "session.start",
"model": "valsea-rtt",
"hint_text": "Optional context or vocabulary",
"enable_correction": true,
"language": "auto",
"language_hints": ["en", "vi", "ar"],
"target_language": "spanish",
"noise_suppression": "off"
}
When target_language is set and differs from the input language, transcript.final.text is
translated to that target language, and rawText holds the original transcript. Partial transcripts
are never translated. Supported translation targets are english, chinese, japanese, korean,
vietnamese, thai, french, spanish, german, russian, indonesian, malay, filipino,
tamil, khmer, lao, and hindi.
An unsupported or malformed target_language returns INVALID_TRANSLATION_TARGET and ends the
session — see the error example below. Double-check the value against the supported list before
sending it.
audio.append
Send audio data.
{
"type": "audio.append",
"audio": "BASE64_ENCODED_PCM16_DATA"
}
- Format: Raw PCM 16-bit, 16kHz (recommended), mono.
- Encoding: Base64 string.
You may also send raw binary PCM16 frames directly over the WebSocket. Binary frames are treated as
audio.append messages by the server.
audio.commit
Signal the end of a speech segment (e.g., VAD triggered silence).
{
"type": "audio.commit"
}
session.stop
End the session gracefully.
{
"type": "session.stop"
}
Server Messages
session.created
Sent immediately upon connection.
{
"type": "session.created",
"sessionId": "rtt_...",
"supportedModels": ["valsea-rtt"]
}
session.ready
Sent when the backend engine is connected and ready to receive audio.
{
"type": "session.ready",
"sessionId": "rtt_...",
"engine": "valsea-7"
}
engine is an opaque identifier for the backend that handled your session.transcript.partial
Intermediate transcription results, in the original language (low latency, may change).
{
"type": "transcript.partial",
"text": "The quick brown",
"isFinal": false,
"timestampMs": 1888
}
transcript.final
Finalized text for a speech segment. Without translation:
{
"type": "transcript.final",
"text": "The quick brown fox jumps over the lazy dog while the market",
"rawText": "The quick brown fox jumps over the lazy dog while the market",
"isFinal": true,
"timestampMs": 3765
}
With target_language set — real, captured output translating English to Spanish:
{
"type": "transcript.final",
"text": "El rápido zorro marrón salta sobre el perro perezoso mientras el mercado",
"rawText": "The quick brown fox jumps over the lazy dog while the market",
"isFinal": true,
"timestampMs": 3765,
"translated": true,
"sourceLanguage": "english",
"targetLanguage": "spanish"
}
When translated: true, text is the translation and rawText is the original
transcript — easy to mix up if you're not checking the flag.
error
Sent when an error occurs.
{
"type": "error",
"code": "INVALID_MESSAGE",
"message": "Failed to parse message"
}
Real example — invalid translation target. Captured during testing: "chinese" normalizes
internally to "chinese-mandarin", which isn't in the allowed target list, so the session ends:
{
"type": "error",
"code": "INVALID_TRANSLATION_TARGET",
"message": "Translation target language 'chinese-mandarin' is not supported"
}
{
"type": "session.ended",
"reason": "invalid_translation_target",
"error": "Translation target language 'chinese-mandarin' is not supported"
}
Error codes on this endpoint
Event Handling Pattern
Use this pattern to avoid duplicated or unstable transcript content:
let currentPartial = '';
const finalSegments = [];
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'transcript.partial') {
currentPartial = msg.text || '';
}
if (msg.type === 'transcript.final') {
finalSegments.push(msg.text || '');
currentPartial = '';
}
});
Example (Node.js)
const WebSocket = require('ws');
const fs = require('fs');
const ws = new WebSocket('wss://api.valsea.ai/v1/realtime/translate', {
headers: { 'X-API-Key': 'YOUR_KEY' },
});
ws.on('open', () => {
ws.send(
JSON.stringify({
type: 'session.start',
model: 'valsea-rtt',
target_language: 'spanish',
}),
);
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.type === 'session.ready') {
const audioStream = fs.createReadStream('audio.raw');
audioStream.on('data', (chunk) => {
ws.send(
JSON.stringify({
type: 'audio.append',
audio: chunk.toString('base64'),
}),
);
});
} else if (msg.type === 'transcript.final') {
console.log('Original:', msg.rawText);
console.log('Translated:', msg.text);
}
});
Use a fixed input language
By default, sessions auto-detect the source language. If you already know the language being spoken, set it explicitly for the most consistent routing:
{
"model": "valsea-rtt",
"language": "singlish"
}
Language Hints
Omit language or use "language": "auto" to detect the source language. To constrain source-language routing, use a supported code such as english, vietnamese, arabic, arabic-egypt, or arabic-uae. Set target_language to a supported translation target such as english, chinese, or vietnamese.
With automatic detection, language_hints can contain up to 20 expected two- or three-letter codes such as ["en", "vi", "ar"]. Hints bias detection but do not restrict it, and they are ignored when language is fixed. See Bias Automatic Detection.
VALSEA supports 181 languages, dialects, and variants overall. Source detection, translation targets, and feature coverage vary by endpoint. See the current supported-language matrix for the authoritative list.