Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

JavaScript / TypeScript SDK

The official Node SDK (@vakyam-ai/tts) provides a fully typed client for the public TTS API: voices, speech synthesis, HTTP streaming, and realtime WebSocket synthesis. Types are generated from the OpenAPI contract.

Install

pnpm add @vakyam-ai/tts
Requires Node 20+ (for the global fetch and Web Streams). In other runtimes, pass a fetch implementation explicitly.

Create a client

Use VakyamAI for regular HTTP calls (voices.list, tts.generate):
import { VakyamAI } from "@vakyam-ai/tts"; const client = new VakyamAI({ apiKey: process.env.VAKYAM_API_KEY! });
Use VakyamAIAsync for HTTP streaming and realtime WebSocket synthesis (tts.stream, tts.websocket):
import { VakyamAIAsync } from "@vakyam-ai/tts"; const asyncClient = new VakyamAIAsync({ apiKey: process.env.VAKYAM_API_KEY! });
Options:
OptionTypeDescription
apiKeystringRequired. Your vak_live_... key.
baseUrlstringOverride the API base URL. Defaults to https://api.vakyam.ai.
allowInsecureBaseUrlbooleanPermit a non-local HTTP base URL. HTTPS is required by default.
timeoutMsnumberRequest/initial-response timeout in milliseconds.
fetchtypeof fetchCustom fetch implementation for older runtimes.

List voices

The return type narrows based on groupBy:
const byLanguage = await client.voices.list(); // VoicesByLanguage const byVoice = await client.voices.list({ groupBy: "voice" }); // VoicesByVoice

Create speech

import { writeFile } from "node:fs/promises"; const speech = await client.tts.generate({ text: "வணக்கம், நான் வாக்யம் AI பேசுகிறேன்.", model_id: "raaga-v1", voice: "Archana", language: "ta-IN", output_format: "mp3", // mp3 | wav | pcm | mulaw, default mp3 sample_rate: 24000, // 8000 | 16000 | 24000 | 48000, default 24000 speed: 1.0, // 0.5 - 2.0, default 1.0 }); await writeFile(`speech.${speech.format}`, speech.audioBytes); console.log(speech.duration_seconds, speech.characters_used);
output_format, sample_rate, and speed are optional and are also accepted by tts.stream and the WebSocket config.
voice accepts a preset name (e.g. "Archana") or a custom voice ID beginning with vc_ (e.g. voice: "vc_01EXAMPLE").
The response includes every field from the API plus a decoded audioBytes: Uint8Array.

HTTP streaming

tts.stream (on VakyamAIAsync) returns an async generator of Uint8Array chunks:
import { createWriteStream } from "node:fs"; const output = createWriteStream("speech.pcm"); for await (const chunk of asyncClient.tts.stream({ text: "வணக்கம்.", model_id: "raaga-v1", voice: "Archana", language: "ta-IN", output_format: "pcm", })) { output.write(chunk); } output.end();
You can pass an AbortSignal to cancel a request:
const controller = new AbortController(); const speech = await client.tts.generate(params, { signal: controller.signal });

WebSocket

The session config (model, voice, language, format, speed) is sent before any text — websocket(...) opens the connection and sends the config message first, so every sendText call after it uses that config.
import { writeFile } from "node:fs/promises"; // Opens the connection and sends the config message first const socket = await asyncClient.tts.websocket({ model_id: "raaga-v1", voice: "Archana", language: "ta-IN", output_format: "pcm", }); // Then send text — one complete sentence per call const utterance = await socket.sendText("நான் சரியாக இருக்கிறேன்."); await writeFile("sentence.pcm", utterance.audioBytes); socket.close();
sendText resolves once the full utterance has been received. The returned object includes audioBytes, audioChunks, characters_used, and duration_seconds.
Wait for the current sendText promise to resolve before calling it again. The SDK throws if you send another sentence while one is in flight.

Interrupting an utterance (barge-in)

Call socket.cancel() to interrupt the current utterance. It sends a cancel, collects any audio received before the server acknowledges, and resolves with a WebSocketCancelledUtterance (type: "cancellation", plus audioBytes, audioChunks, characters_used, duration_seconds). The session stays open, and you are billed only for audio produced before the cancel.
const cancelled = await socket.cancel(); console.log(cancelled.characters_used, cancelled.audioBytes.byteLength);
The server closes idle connections after 60 seconds without an incoming message. By default the SDK sends a JSON ping every 30 seconds to keep the session alive. You can send one manually at any time:
await socket.ping();
Tune or disable the automatic keepalive with keepAliveIntervalMs:
// Custom interval (milliseconds) const socket = await asyncClient.tts.websocket( { model_id: "raaga-v1", voice: "Archana", language: "ta-IN", output_format: "pcm", }, { keepAliveIntervalMs: 30000 }, ); // Disable keepalive entirely const socketNoKeepAlive = await asyncClient.tts.websocket( { model_id: "raaga-v1", voice: "Archana", language: "ta-IN", output_format: "pcm", }, { keepAliveIntervalMs: false }, );
The same options object also accepts connectionTimeoutMs (handshake + config timeout, default 60000) and utteranceTimeoutMs (per-utterance timeout, default 300000).

Error handling

import { VakyamAPIError, VakyamValidationError, VakyamWebSocketError, } from "@vakyam-ai/tts"; try { await client.tts.generate({ text: "...", model_id: "raaga-v1", voice: "Archana", language: "ta-IN", }); } catch (err) { if (err instanceof VakyamValidationError) { console.error(err.field, err.message); } else if (err instanceof VakyamAPIError) { console.error(err.statusCode, err.code, err.message); } }
Exported error classes:
  • VakyamError — base error.
  • VakyamAPIError — HTTP API errors; exposes statusCode, code, message.
  • VakyamValidationError — client-side input validation errors; exposes field and message.
  • VakyamWebSocketError — per-message WebSocket errors; exposes code and retryAfterSeconds.
  • VakyamWebSocketClosedError — connection closed; exposes code and reason.