Speech: Listening and Speaking
Hear any answer aloud in its own language, and speak to the model. 322 neural voices across 75 languages, streamed as MP3 as it is written.
Every answer the ZYRAXON provider produces can be heard, not just read — and in the language the answer was written in. Ask in Bengali, and a Bengali voice reads the reply. This is the speech-to-speech loop: your speech in, the model's answer out, both in the same language.
POST https://zyraxonai.lovable.app/api/public/tts — send text, get streamed MP3.
Voices: GET https://zyraxonai.lovable.app/api/public/tts/voices — 322 voices across 75 languages.
Speak: POST https://zyraxonai.lovable.app/api/public/stt — send a recording, get the transcript.Hear an answer
Send the answer's text and the audio starts arriving before the sentence is finished being synthesised, so a client can begin playing almost immediately rather than waiting for a whole file.
curl -s https://zyraxonai.lovable.app/api/public/tts \
-H "Content-Type: application/json" \
-d '{"text":"Hello from ZYRAXON.","locale":"en"}' \
-o answer.mp3
# Play it
ffplay -nodisp -autoexit answer.mp3 # macOS: afplay Windows: startThe same in any language
Name the language and the voice follows. A Bengali answer is read by a Bengali voice — bn-BD-NabanitaNeural — not by an English one reading Bengali letters.
# Bengali
curl -s https://zyraxonai.lovable.app/api/public/tts -H "Content-Type: application/json" \
-d '{"text":"আমি একটি ZYRAXON মডেল।","locale":"bn"}' -o bn.mp3
# Hindi, naming the voice exactly
curl -s https://zyraxonai.lovable.app/api/public/tts -H "Content-Type: application/json" \
-d '{"text":"नमस्ते","voice":"hi-IN-SwaraNeural"}' -o hi.mp3
# Arabic
curl -s https://zyraxonai.lovable.app/api/public/tts -H "Content-Type: application/json" \
-d '{"text":"مرحبا","locale":"ar"}' -o ar.mp3| Field | Required | What it does |
|---|---|---|
text | Yes | What to speak. Up to 5000 characters. |
voice | No | An exact voice name from the voices list. Wins over locale. |
locale | No | A language or region, e.g. bn, bn-IN, en-US. Picks a voice in that language. |
locale only when you want to override the detection.Speaking in real time
For a live conversation the audio must start before the answer is finished. Synthesising the whole reply first means seconds of silence. The pattern is to split the answer into sentences and speak each one as it is ready, queued in order so nothing is reordered.
// Speak an answer while it is still being written.
// A reply arrives token by token; feed the growing text and speak each
// completed sentence as it appears. The first sentence is heard while the
// model is still writing the second.
const queue: string[] = [];
let buffer = "";
let speaking = false;
async function speak(text: string) {
const res = await fetch("https://zyraxonai.lovable.app/api/public/tts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text }), // the locale is detected from the text
});
const audio = new Audio(URL.createObjectURL(await res.blob()));
await new Promise<void>((done) => {
audio.onended = () => done();
audio.onerror = () => done();
audio.play();
});
}
async function pump() {
if (speaking) return;
speaking = true;
while (queue.length) await speak(queue.shift()!);
speaking = false;
}
// Call this on every streamed token.
function feed(chunk: string) {
buffer += chunk;
// Cut after each sentence terminator, including the Bengali danda.
let at = -1;
for (let i = 0; i < buffer.length; i++) if (/[.!?।॥]/.test(buffer[i]!)) at = i;
if (at >= 0) {
queue.push(buffer.slice(0, at + 1).trim());
buffer = buffer.slice(at + 1).trimStart();
void pump();
}
}
// When the answer ends, speak whatever is left.
function finish() {
if (buffer.trim()) queue.push(buffer.trim());
buffer = "";
void pump();
}Which voices exist
curl -s https://zyraxonai.lovable.app/api/public/tts/voices | jq '{count, languages: (.languages|length)}'
# {"count": 322, "languages": 75}
# Every Bengali voice
curl -s https://zyraxonai.lovable.app/api/public/tts/voices | jq -r '.data[] | select(.locale | startswith("bn")) | .name'
# bn-BD-NabanitaNeural
# bn-BD-PradeepNeural
# bn-IN-BashkarNeural
# bn-IN-TanishaaNeuralPlay it in a browser, as it streams
// The endpoint streams MP3, so playback can start before synthesis finishes.
const res = await fetch("https://zyraxonai.lovable.app/api/public/tts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: answer, locale: "bn" }),
});
const audio = new Audio(URL.createObjectURL(await res.blob()));
await audio.play();Speak to the model
Record on the device, transcribe it, then send the transcript as an ordinary chat turn. That is the input half of the loop.
TEXT=$(curl -s https://zyraxonai.lovable.app/api/public/stt -F "file=@recording.mp3" -F "language=bn" | jq -r '.text')
curl -s https://zyraxonai.lovable.app/api/public/zyraxon/v1/chat/completions \
-H "Content-Type: application/json" \
-d "{\"model\":\"zyraxon-codex\",\"messages\":[{\"role\":\"user\",\"content\":\"$TEXT\"}]}" \
| jq -r '.choices[0].message.content'A complete spoken conversation
Transcribe the recording, ask the model, then speak the answer back. This is the whole loop in one script.
#!/usr/bin/env bash
# talk.sh — speak a question, hear the answer.
set -euo pipefail
ORIGIN="https://zyraxonai.lovable.app"
QUESTION=$(curl -s "${ORIGIN}/api/public/stt" -F "file=@$1" -F "language=bn" | jq -r '.text')
echo "You said: $QUESTION"
ANSWER=$(curl -s "${ORIGIN}/api/public/zyraxon/v1/chat/completions" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg q "$QUESTION" \
'{model:"zyraxon-apex", messages:[{role:"user", content:$q}]}')" \
| jq -r '.choices[0].message.content')
echo "ZYRAXON: $ANSWER"
# Speak the answer in the language the question was asked in.
curl -s "${ORIGIN}/api/public/tts" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg t "$ANSWER" '{text:$t, locale:"bn"}')" -o reply.mp3
ffplay -nodisp -autoexit reply.mp3What gets spoken
The endpoint speaks what a person would say, not the raw Markdown. A reply containing a code block is not read character by character — that would be unusable — so a fence becomes a short spoken note, links become their label, and the punctuation goes.
| In the answer | What is spoken |
|---|---|
| A fenced code block | “A code block, 12 lines.” |
[the docs](/docs/getting-started) | “the docs” |
| A bare URL | “a link” |
**important** | “important” |
## Heading | “Heading” |
Which engine, and why it matters
Synthesis runs on Microsoft Edge's Read Aloud engine — the same one behind the browser feature — through the same protocol. That is what gives 322 neural voices in 75 languages with no key to buy and no per-character bill. Audio is MP3 at 24 kHz mono.
Content-Type: audio/mpeg, plus X-ZYRAXON-Voice naming the voice that actually spoke, so a client can show which language it chose.Errors
| Status | Means | What to do |
|---|---|---|
400 | text is missing, or nothing remained after markup was removed. | Send the answer's text. |
413 | The text is over 5000 characters. | Split it and speak it in parts. |
502 | The speech engine refused the connection. | Retry; it is usually transient. |