Introduction
One client for diarized turns and per-speaker voice measurement
ProsodyAI answers three questions about a conversation: who is speaking, what they said, and how the voice behaved. One client, typed results, and the same capability over a recording or a live socket.
Quickstart
Analyze a recording in five lines
Recorded analysis
Upload a file, get turns and frames
Live analysis
Open a socket while the call is running
LiveKit plugin
Measure a room track inside a LiveKit Agent
Voice agents
Steer an agent from how the voice moves
Analyze a conversation
| Call | Returns |
|---|---|
prosody.transcribe(file) | Turns, speakers, voice measurement |
prosody.stream.session() | Live analysis WebSocket (start / send / stop) |
prosody.realtime.attach(room, …) | Browser-side frame stream over a LiveKit room (see LiveKit plugin for the agent worker path) |
const result = await prosody.transcribe('./call.wav');
for (const turn of result.turns) {
console.log(turn.speaker.label, turn.text, turn.prosody?.state.intonation.pitch);
}Read the measurements
Every turn carries prosody.state, how the voice sounded, and prosody.change,
how that turn moved against the same speaker's own baseline.
turn.prosody.state.intonation.pitch // median F0, Hz
turn.prosody.state.intonation.range // F0 span, semitones
turn.prosody.state.intonation.slope // rising or falling contour
turn.prosody.state.stress.loudness // loudness, dBFS
turn.prosody.state.stress.peak // loudest instant
turn.prosody.state.rhythm.voiced // fraction phonated, 0 to 1
turn.prosody.state.rhythm.pause // fraction silent, 0 to 1
turn.prosody.state.rhythm.onset // phonation restarts per second
turn.prosody.state.tilt // voice quality: spectral slope
turn.prosody.state.clipping // signal health
turn.prosody.change?.intonation.pitch // semitones against baseline
turn.prosody.change?.stress.loudness // dB against baselineA field is null when the audio did not support the measurement: pitch on a
turn with no voiced audio, for example, because pitch does not exist on
unphonated audio.
For the whole call measured frame by frame, result.frames gives every
measured moment, each attributed to a speaker, with its state, its change,
and its affect.
Who is speaking
Every turn carries a speaker, taken from the waveform: no transcript, no
channel split, no enrollment step. It holds the label, talk time, and that
voice's measured baseline.
speaker.label; // "Speaker 1"
speaker.talkSeconds; // 142.5
speaker.state.intonation.pitch?.median; // 118.4Feedback
| Call | Returns |
|---|---|
prosody.submitCorrection() | Corrects a prediction you disagree with |
prosody.submitSessionOutcome() | Attaches how the conversation actually went |
Authentication
Every request carries a psk_* API key. Create one under API keys in the
dashboard. See Credits for
rates.