Skip to main content

Realtime emotion results

WSS

wss://devapi.imentiv.ai/v2/ws/realtime?session_id={session_id}

Query parameters

ParameterRequiredDescription
session_idYesFrom POST /v2/realtime/session.
tokenOnly without the headerFallback for clients that cannot set headers on a WebSocket upgrade — browsers, mainly. Prefer the X-API-Key header: a token in the URL ends up in access logs.

Close codes

The connection is refused with 1008 and one of these reasons: Missing authentication token, Invalid or expired token, Missing session_id query parameter, or Insufficient credits for realtime session.

Imentiv sends — Emotion result stream

Frames arrive as they are ready, in no guaranteed order relative to each other. Video frames are frequent — up to about ten per second, sampled at a fixed minimum interval, so a 30 fps stream does not produce 30 results per second. Audio, transcript and text emotion arrive per speech segment. A text_emotion frame follows its transcript frame and matches on start_time_ms.

Every frame carries a type field — switch on it, then on data.source for emotion, which covers both facial and voice results.

emotion frames carry no session_id; the other three do. Parsing code that reads frame.session_id uniformly gets nothing on the frames you receive most often. You opened the socket with the session id, so key off your own value.

Ignore any type you do not recognise — more may be added.

Video emotion

Facial emotion scores for one analysed video frame.

FieldTypeRequiredDescription
type"emotion"Always emotion. Facial and voice results share one type — data.source is what tells them apart.
timestampintegerYesMilliseconds since the session started. Not a Unix epoch: only timestamp_sent, on transcript and text-emotion frames, is a wall-clock time.
frame_numberintegerYesMonotonic counter over the video frames analysed in this session.
dataVideoEmotionDataYes
VideoEmotionData
FieldTypeRequiredDescription
source"video"Always video on this frame. Switch on type first, then on this.
dominantstringYesThe highest-scoring label in scores.
scoresobjectYesThe eight video labels, each 0…1: angry, contempt, disgust, fear, happy, neutral, sad, surprise. Read the keys rather than hardcoding the set — it may be extended. Note this is not the audio set: video has contempt where audio has calm, so the two are not interchangeable.
valencenumber or nullCircumplex valence in [-1, 1]. None if not computed.
arousalnumber or nullCircumplex arousal in [-1, 1]. None if not computed.
intensitynumber or nullMagnitude of (valence, arousal). Bounded by sqrt(2), the corner of the [-1,1]x[-1,1] valence/arousal box. None if not computed.
expressivenessnumber or null1 - p(neutral); how expressive the distribution is, distinct from intensity (see imentiv-face-analysis#144). None if not computed.
emotion_entropynumber or nullNormalized Shannon entropy of the emotion distribution; 0 = certain, 1 = uniform/uncertain. None if not computed.
circumplex_versionstring or nullWhich imentiv-face-analysis COORDINATES table produced valence/arousal/intensity/expressiveness/emotion_entropy (e.g. 'v1', 'v2'). None if not computed.

Audio emotion

Voice-tone emotion scores for one analysed speech segment.

FieldTypeRequiredDescription
type"emotion"Always emotion — the same type a video frame uses. data.source distinguishes them. An audio frame carries no frame_number.
timestampintegerYesEqual to data.start_time_ms: milliseconds since the session started, not a Unix epoch.
dataAudioEmotionDataYes
AudioEmotionData
FieldTypeRequiredDescription
source"audio"Always audio on this frame.
start_time_msintegerYesSegment start, in milliseconds from the start of the session. Also the join key: the matching text_emotion frame arrives carrying this same value.
end_time_msintegerYesSegment end, in milliseconds from the start of the session.
duration_msintegerYesLength of the speech segment in milliseconds.
dominantstringYesThe highest-scoring label in scores.
scoresobjectYesThe eight audio labels, each 0…1: angry, calm, disgust, fear, happy, neutral, sad, surprise. Audio has calm where video has contempt — do not merge the two sets into one chart without accounting for it.
transcriptstringYesWhat was said during this segment.
text_emotionsobjectYesZero-filled while the session is running. The real scores arrive on a separate text_emotion frame, joined on start_time_ms; rendering this field mid-session shows a wall of zeros. The exception is the final segment, finalised during POST /v2/realtime/session/{session_id}/end, which carries real values here and gets no follow-up frame. Code that joins on start_time_ms and falls back to the frame itself handles both.
dominant_text_emotionstring or nullnull while the session is running, for the same reason as text_emotions. Populated only on the final segment.
valencenumber or nullCircumplex valence in [-1, 1]. None if not computed.
arousalnumber or nullCircumplex arousal in [-1, 1]. None if not computed.
intensitynumber or nullMagnitude of (valence, arousal). Bounded by sqrt(2), the corner of the [-1,1]x[-1,1] valence/arousal box. None if not computed.
expressivenessnumber or null1 - p(neutral); how expressive the distribution is, distinct from intensity (see imentiv-face-analysis#144). None if not computed.
emotion_entropynumber or nullNormalized Shannon entropy of the emotion distribution; 0 = certain, 1 = uniform/uncertain. None if not computed.
circumplex_versionstring or nullWhich imentiv-face-analysis COORDINATES table produced valence/arousal/intensity/expressiveness/emotion_entropy (e.g. 'v1', 'v2'). None if not computed.

Transcript

Speech transcribed from the audio track.

FieldTypeRequiredDescription
typestringAlways transcript.
session_idstringYesThe session this frame belongs to. Present here and on text_emotion, but absent from emotion frames — see the operation description.
dataTranscriptDataYes
TranscriptData
FieldTypeRequiredDescription
transcriptstringYesThe text so far, or the complete text once is_final is true. Replace your stored value on each update; appending duplicates every word.
languagestringDetected language code, e.g. en.
start_time_msintegerYesSegment start, in milliseconds from the start of the session.
end_time_msintegerYesSegment end, in milliseconds from the start of the session.
transcript_idstringYesGroups every frame belonging to one utterance. Key your display on this.
seqintegerYesIncrements across the partial frames of one transcript_id.
is_finalbooleantrue once the utterance is closed. Only the final frame is punctuation-restored.
timestamp_sentintegerServer send time as a Unix epoch in milliseconds — a real wall-clock time, unlike timestamp on an emotion frame.

Text emotion

Emotional content of the transcribed speech. Arrives after the matching transcript, as a separate follow-up frame. Best-effort: if analysis fails or times out for a segment, no frame arrives for it — treat absence as 'no update available', never as an error or a zero result.

FieldTypeRequiredDescription
type"text_emotion"Always text_emotion. This frame has no source field.
session_idstringYesThe session this frame belongs to.
dataTextEmotionDataYes
TextEmotionData
FieldTypeRequiredDescription
start_time_msintegerYesJoin key — matches the start_time_ms of the audio emotion frame this analysis belongs to.
end_time_msintegerYesSegment end, in milliseconds from the start of the session.
text_emotionsobjectYesThe text labels, each 0…1. Twenty-eight today; read the keys rather than hardcoding the set — up to four more (sarcasm, boredom, contempt, envy) may appear.
dominant_text_emotionstringYesThe highest-scoring label in text_emotions.
timestamp_sentintegerServer send time as a Unix epoch in milliseconds.

Error

Something went wrong, or the session was cut off.

FieldTypeRequiredDescription
type"error"Yes
session_idstringThe session this error belongs to.
errorstringYesHuman-readable message. Display it, but never branch on it — the wording is free to change.
codestringStable, machine-readable reason. Branch on this. insufficient_credits means the session was cut off mid-stream.
creditsobjectSpend summary for the session, present on the credit-cutoff frame. That path cannot use POST /v2/realtime/session/{id}/end — the session is torn down immediately, so a follow-up call would 404.