TypeScript SDK

Also available for Python and Go, with the same methods.

@vovix/voixa wraps every endpoint with types, waits for clips and transcripts for you, and has no dependencies. It runs in Node 18+, Bun, Deno, Cloudflare Workers and the browser.

Install

npm

npm install @vovix/voixa

Create a client

import { Voixa } from '@vovix/voixa'

const vx = new Voixa({
  apiKey: process.env.VOIXA_API_KEY!, // Studio → API keys
  // baseUrl: 'https://api.voixa.vovix.io/v1',  (default)
  // timeoutMs: 30_000,                         (per HTTP request)
})

A tour

// Built-in voices and your clones
const { voices } = await vx.voices({ language: 'vi' })

// Text → clip. say() waits until the audio is ready; speak() returns at once.
const clip = await vx.say({ voiceId: 'vi-truc-ly', text: 'Xin chào.', project: 'episode-12' })
clip.url   // signed WAV URL, valid for one hour

// Long text → one audio file
const episode = await vx.makePodcast({ voiceId: 'vi-truc-ly', title: 'Episode 12', text: script })

// Your library, grouped by project
const { items } = await vx.listClips({ project: 'episode-12', source: 'api' })
const { shareUrl } = await vx.shareClip(clip.clipId)

// Clone a voice from 3–10 s of clean speech
const me = await vx.createVoice({ name: 'Me', language: 'vi', audio: wavBytes })
await vx.say({ voiceId: me.voiceId, text: 'Giờ là giọng của tôi.' })

// Speech to text with timestamps
const t = await vx.transcribeFile({ audio: await fs.readFile('interview.mp3'), fileName: 'interview.mp3' })
t.text, t.segments, t.srtUrl

Methods

Speech

MethodReturns
speak({ voiceId, text, project?, wait? }){ clip } as the server has it after its ~20 s wait. wait: false returns at once with status: "processing".
say(req, { timeoutMs?, pollMs? })speak plus polling until the clip is ready; throws if it fails.
createPodcast({ voiceId, title?, text, project? }){ clip } with kind: "podcast", always processing at first.
makePodcast(req, wait?)createPodcast plus polling, up to two hours.

Library

MethodReturns
getClip(clipId), waitFor(clipId)One clip with a fresh signed URL; poll until ready.
listClips({ project?, source?, kind?, voiceId?, limit?, cursor? })Your clips, newest first; cursor for the next page.
projects()Your content groups with clip and character counts.
shareClip(clipId), unshareClip(clipId)A public listening page (shareUrl), and revoking it.
deleteClips(clipIds){ deleted }.

Voices

MethodReturns
voices({ language? }), getVoice(voiceId)Built-in voices, your clones and clones others shared.
samples({ language? })Built-in voices with a public sample URL, for a picker in your app.
createVoice({ name, language, audio, format?, gender?, description?, refText? })Uploads the recording and waits for the clone and its sample.
updateVoice(voiceId, { name?, description?, gender?, styles?, shared? })shared: true lets every Voixa account use your clone.
deleteVoice(voiceId)Deletes the clone and its recording; clips made with it stay.

Voice design

MethodReturns
designVoice({ description, language, text?, count? }){ design } with status: "processing"; 1–3 takes of the described voice.
waitForDesign(designId), getDesign(designId)The design with a signed url per take once ready.
saveDesign(designId, { candidate, name, gender?, description? })Keeps one take as a voice and waits for its sample.
createVoiceFromDescription({ description, language, name, gender?, text? })One call: design one take, wait, keep it.
listDesigns({ limit?, cursor? }), deleteDesign(designId)Your designs, newest first; deleting keeps saved voices.

Transcription

MethodReturns
transcribe({ audio, fileName?, title?, language?, task?, words?, prompt?, project? })Registers and uploads in one go; { transcript } with status: "processing".
transcribeFile(req, wait?)transcribe plus polling until ready.
getTranscript(id), waitForTranscript(id)Text, segments and signed JSON/SRT/VTT/TXT URLs.
listTranscripts({ project?, source?, status?, limit?, cursor? }), deleteTranscripts(ids)Summaries without text; delete also removes the upload.
sttLanguages()Languages you may pin, accepted formats and limits.

Account

MethodReturns
account()Allowances and today's usage.
languages()Languages with limits, cloneable and a clone-recording guide.

Errors

Every failed call throws VoixaError with status, code, retryAfter (seconds, from Retry-After) and, for allowances, used, limit and resetsAt. See Errors.

import { VoixaError } from '@vovix/voixa'

try {
  await vx.say({ voiceId: 'vi-truc-ly', text })
} catch (e) {
  if (e instanceof VoixaError && e.code === 'QUOTA') console.log('Allowance resets at', e.resetsAt)
  else throw e
}

Was this page helpful?