novax-js
v0.2.0
Published
Official NovaxVoice Krio Text-to-Speech SDK for Node.js, Next.js, and the browser. v1/v2 versions, auto-retries, and a CLI.
Maintainers
Readme
novax-js
Official NovaxVoice Krio Text-to-Speech SDK for Node.js, Next.js, and the browser.
Zero runtime dependencies — built on the platform fetch.
Synthesizes Krio text and returns a WAV blob (16-bit mono PCM, 24 kHz).
Install
npm install novax-js
# or
pnpm add novax-jsRequires Node.js 18+ (for global fetch).
Quick start (ElevenLabs-style)
The API mirrors the ElevenLabs SDK — resource namespaces, a play() helper, and voice ids:
import { NovaxVoice, play } from "novax-js";
const novax = new NovaxVoice();
const audio = await novax.textToSpeech.convert("nova", {
text: "Kushɛ, aw di bodi?",
modelId: "v2", // "v1" | "v2" selects the backend version
outputFormat: "wav",
});
await play(audio); // or: import { save } and save(audio, "out.wav")NovaxVoice is an alias of NovaxVoiceClient; both are identical. No API key is required by
the current backend.
Streaming and voices
for await (const chunk of novax.textToSpeech.stream("nova", { text: "Stream me" })) {
// chunk: Uint8Array
}
const voices = await novax.voices.getAll(); // [{ voiceId: "nova", name: "Nova", ... }]
const nova = await novax.voices.get("nova");The backend is currently single-voice Krio.
voiceId,outputFormat, andvoiceSettingsare forwarded for forward-compatibility but don't yet change the output (always WAV, voice "nova").modelId"v1"/"v2"does switch the backend version.
API
synthesize(options) → Uint8Array
One-shot synthesis, fully buffered.
const wav = await client.synthesize({ text: "Tɛnki ya." });synthesizeStream(options) → AsyncGenerator<Uint8Array>
Streams the audio download chunk by chunk.
for await (const chunk of client.synthesizeStream({ text })) {
process.stdout.write(chunk);
}The backend returns a single WAV blob, so this streams the HTTP response body — it is not incrementally generated audio.
synthesizeResponse(options) → Response
Returns the raw Response — pipe .body straight through a Next.js route.
synthesizeToFile(path, options) → void
Node.js convenience: synthesize and write the WAV to disk.
await client.synthesizeToFile("out.wav", { text: "A sev am na fail." });CLI
Installing the package provides a novax binary (run via npx or add it to scripts):
npx novax "Kushɛ, aw di bodi?" -o hello.wav
npx novax "Tɛnki ya." --version v1
echo "A de na os" | npx novax -o - > out.wav # stdin -> stdoutAutomatic retries
Transient failures (HTTP 429/500/502/503/504, timeouts, network errors) are retried with
exponential backoff + jitter, honoring Retry-After. Client errors like 400 are never retried.
new NovaxVoiceClient({ maxRetries: 2, retryBaseDelayMs: 500 }); // defaults; maxRetries: 0 disablesChoosing a version (v1 / v2)
The backend has two model versions. The SDK defaults to v2; set a default on the client or override per call:
const client = new NovaxVoiceClient(); // v2 by default
const v1Client = new NovaxVoiceClient({ version: "v1" }); // pin v1 for all calls
await client.synthesize({ text: "Kushɛ", version: "v1" }); // override just this callA custom endpoint always wins over version (use it for staging/gateways).
extraBody — forward-compatible parameters
The backend currently reads only text. To pass new fields as the backend gains
support (e.g. a voice or speed), use extraBody — no SDK upgrade needed:
await client.synthesize({ text: "...", extraBody: { speed: 1.2 } });Configuration
| Option | Default | Description |
| ----------- | ----------------------------------------------------------------- | --------------------------------------------- |
| version | "v2" | Backend version ("v1" or "v2"). |
| endpoint | resolved from version | Full URL override (POSTed to directly). |
| maxRetries| 2 | Retries on transient failures (0 disables). |
| retryBaseDelayMs | 500 | Base backoff delay in ms. |
| apiKey | process.env.NOVAXVOICE_API_KEY | Optional; sent as Bearer if set. |
| timeoutMs | 120000 | Per-request timeout (cold starts take ~20s). |
| fetch | global fetch | Custom fetch implementation. |
| headers | {} | Extra headers on every request. |
Next.js
Call the SDK from a server route and proxy the audio to the browser. See
examples/nextjs-route-handler.ts and the client hook in
examples/useTts.ts.
// app/api/tts/route.ts
import { NovaxVoiceClient, AUDIO_CONTENT_TYPE } from "novax-js";
const client = new NovaxVoiceClient();
export const maxDuration = 120;
export async function POST(req: Request) {
const { text } = await req.json();
const upstream = await client.synthesizeResponse({ text });
return new Response(upstream.body, { headers: { "Content-Type": AUDIO_CONTENT_TYPE } });
}Error handling
All errors extend NovaxVoiceError:
NovaxVoiceAPIError— non-2xx (has.status,.code,.body). A missingtextreturns HTTP 400 with the plain-text messagemissing 'text'.NovaxVoiceAuthError— 401/403NovaxVoiceRateLimitError— 429 (has.retryAfter)NovaxVoiceTimeoutError— request timed out
Build from source
pnpm install
pnpm build # emits dist/ (ESM + CJS + .d.ts)
pnpm typecheckLicense
MIT
