Live events

WS /v1/events

One WebSocket carries everything happening in voxd. This is how the app stays in sync without polling.

Authentication: browsers can't set headers on WebSockets, so pass the token as a query parameter:

ws://127.0.0.1:4870/v1/events?token=<token>

A wrong token closes the socket with code 4401.

Messages

Every message is JSON: {"type": "...", "data": {...}}.

type data When
hello {"version": "0.1.0"} Right after connecting
job a full job object Whenever a job is queued, makes progress or finishes
models.changed {"id": "kokoro-v1", "installed": true} A model finished downloading or was removed. Refresh engines, voices and models.
voices.changed {"id": "cv_…"} A custom voice was created, renamed or deleted
take.updated a take object A take was starred or unstarred
takes.deleted {"ids": […]} Takes were deleted, by you or by retention
design.ready {"voices": 28} Voice analysis for design finished
transcripts.changed {"id": …} A transcript was created, edited or deleted
dubs.changed {"id": …} A dub's status or content changed
books.changed {"id": …} A book was imported, edited, narrated or exported
batches.changed {"id": …} A batch was created or removed. Item progress comes through job events.
watch.changed {"id": …} A watch folder was added, changed, or picked up a new file
projects.changed {"id": …} A project or its items changed
pronunciations.changed {} The pronunciation dictionary changed
keys.changed {} An API key was created or revoked
tags.changed {"kind"?, "id"?, "tag"?} Tags were added, renamed or removed
ratings.changed {"language": …} A blind comparison was recorded or ratings were cleared
take.created a take object, without audio_url Whenever a new take is saved, by any client

More event types will be added over time. Ignore any type you don't recognize.

Example (JavaScript)

const ws = new WebSocket(`ws://127.0.0.1:4870/v1/events?token=${token}`)
ws.onmessage = (e) => {
  const { type, data } = JSON.parse(e.data)
  if (type === 'job') console.log(`${data.title}: ${data.status} ${Math.round(data.progress * 100)}%`)
  if (type === 'take.created') console.log('New take:', data.text)
}

Delivery