Conversation
Transcript state, voice frames, trajectories, and deltas
Conversation is the shared state model for recorded and live analysis.
Transcription.conversation exposes it directly; LiveSession maintains one
as events arrive.
class Conversation {
static fromAnalysis(result: AnalysisResult): Conversation;
apply(event: ProsodyEvent | Record<string, unknown>): this;
getTranscript(): string;
getTurns(): ConversationTurn[];
getTurn(index: number): ConversationTurn | null;
getSpeakers(): DiarizedSpeaker[];
getVad(): AffectVad | null;
getFrames(speakerId?: string): VoiceFrame[];
getFrame(index: number): VoiceFrame | null;
getProsody(turnIndex?: number): Prosody | null;
getMeasurementSeries(
path: MeasurementPath,
speakerId?: string,
): MeasurementPoint[];
getChanges(speakerId?: string): ChangePoint[];
getMoments(speakerId?: string): Moment[];
getTopMoments(limit?: number, speakerId?: string): Moment[];
}Event application
apply() accepts the realtime event stream:
directivetranscript_updatespeaker_updatespeaker_profilessession_end
Speaker updates fill committed attribution for analyzed intervals.
getTurns() returns the current attribution.
const conversation = new Conversation();
for await (const event of events) {
conversation.apply(event);
render(conversation.getTurns());
}LiveSession and ProsodySession call apply() automatically when supplied a
conversation.
VoiceFrame
One measured interval in the conversation: who spoke, when, how they sounded, how they moved, and the affect when the checkpoint publishes it.
class VoiceFrame {
readonly speakerId: string;
readonly startMs: number;
readonly endMs: number;
readonly timestampMs: number;
readonly state: ProsodyState | null;
readonly change: ProsodyChange | null;
readonly vad: AffectVad | null;
getProsody(): Prosody | null;
getChange(): ProsodyDelta | null;
}Trajectories
const pitch = conversation.getMeasurementSeries('intonation.pitch', speaker.id);
const changes = conversation.getChanges(speaker.id);MeasurementPoint and ChangePoint carry speakerId, the frame bounds, and
the measured value. MeasurementPath is the typed key union, mirroring the
state families: intonation.pitch, intonation.range, intonation.slope,
stress.loudness, stress.peak, rhythm.voiced, rhythm.pause,
rhythm.onset, tilt, clipping. Unavailable measurements are excluded from
series.
frame.getProsody() returns the full measurement bundle: state, how the
frame sounded, and change, the signed movement against the speaker's own
baseline. frame.getChange() returns the movement as a ProsodyDelta: the
reference frame and the signed change values.
Moments
A moment is a span the model committed as having moved the speaker's state.
magnitude is the model's own readout of how far the state travelled, so it
is published rather than derived: only the model carrying the person's state
can measure it.
interface Moment {
frameMs: number; // where the evidence began, on the 80ms frame clock
commitMs: number; // where the decision landed
durationMs: number; // how long the movement ran
magnitude: number; // how far the speaker's state moved
resolved: boolean; // true when the state returned to its prior trajectory
speakerId: string | null;
}getMoments() returns them in commit order. getTopMoments() ranks them by
magnitude, largest first, and defaults to ten. Transcription.moments is that
ranked shortlist.
for (const moment of result.moments) {
console.log(moment.frameMs, moment.magnitude, moment.speakerId);
}
const callerMoments = conversation.getTopMoments(5, speaker.id);frameMs is retrodictive: it points at where the evidence began, while
commitMs is where the model committed. Seek to frameMs to hear the moment.
Moments come from the batch report's committed events. A live conversation carries none, because the live wire publishes measurement and attribution as they land.