Result format
GET /v1/jobs/{id}/result returns JSON. A shortened example for a stereo call with every option on:
{
"schema_version": "gapi_task_result.v0",
"audio_seconds": 282.7,
"speech_seconds": 230.4,
"channels": 2,
"stereo_parties": true,
"speakers": 2,
"vocabulary_terms": 4,
"vocabulary_dropped": false,
"text": "Assalomu alaykum, Metasell kompaniyasi. …",
"segments": [
{
"index": 0,
"start": 0.42,
"end": 3.9,
"speaker": 1,
"text": "Assalomu alaykum, Metasell kompaniyasi.",
"raw_asr_text": "assalomu alaykum metasell kompaniyasi",
"formatted_text": "Assalomu alaykum, Metasell kompaniyasi.",
"emotion": {"mood": "neutral", "label": "neutral", "confidence": 0.88, "valence": 0.52, "arousal": 0.31, "dominance": 0.47, "windows": 1,
"probabilities": {"neutral": 0.88, "happy": 0.05, "sad": 0.02, "angry": 0.02, "fearful": 0.01, "disgusted": 0.01, "surprised": 0.01}},
"pii": {"entities": [], "redacted_text": "Assalomu alaykum, Metasell kompaniyasi."}
}
],
"speaker_info": [
{
"index": 0,
"speech_seconds": 149.2,
"gender": {"label": "male", "confidence": 0.97},
"role": "client",
"identity": {"status": "new", "voice_id": 100, "speaker_id": "e3db…", "name": null},
"has_voiceprint": true,
"emotion": {"dominant_mood": "negative", "mood_share": {"negative": 0.46, "neutral": 0.41, "positive": 0.13}, "valence": 0.38, "arousal": 0.61, "dominance": 0.44}
}
],
"voices": [
{"label": "SPEAKER_1", "speaker": 0, "voice_id": 100, "name": null, "status": "new"},
{"label": "SPEAKER_2", "speaker": 1, "voice_id": 101, "name": "Azimbek", "status": "matched", "score": 0.97}
],
"options_report": {"requested": ["gender", "speaker_roles", "speaker_identification", "emotion", "pii"], "errors": {}, "seconds": 1.8},
"timing": {"decode_seconds": 0.3, "vad_seconds": 0.4, "stt_seconds": 2.1, "total_seconds": 4.9}
}The text comes in Latin script: the model is trained on Latin-script Uzbek, and every option (punctuation, numbers, personal data) works on it. There is no Cyrillic output.
Top level
| Field | What it is |
|---|---|
audio_seconds | Length of the recording; the charge in g is worked out from it |
speech_seconds | How much of it is speech |
channels, stereo_parties | Channels in the file; true when the sides are separated by channel |
speakers | How many voices speaker separation found |
text | All text in a row |
segments | Utterances in order |
speaker_info | A summary per speaker of the recording |
voices | Permanent project voice numbers, with "Recognise by voice" |
options | The settings the recording was actually run with: the project plus the request's settings. Every key from the Options page is here — stereo_channels_as_speakers, max_speakers, call_direction and fuzzy_itn (loose number normalisation, off by default) included |
vocabulary_terms, vocabulary_dropped | How many vocabulary terms the job took; the second is true when the cleaning left none |
diarization_error | true when speaker separation did not work: the recording will carry no speaker numbers. When it worked, the field is there and is null |
options_report | Which options were requested, which were not computed and why |
segment_voiceprints | Which utterances have a voice print: {"dims", "format", "min_seconds", "segments": [indexes]}. The prints themselves never leave the gateway — this is the list of utterances a voice can be enrolled from with POST /v1/speakers/{id}/enroll and segment_indexes |
timing | How many seconds processing took: decode_seconds, vad_seconds, stt_seconds, format_seconds, diarization_seconds, total_seconds. We measure ourselves by these, not you |
options_report shows what was requested (requested), what could not be computed and why (errors), and how many seconds the options took (seconds). When roles were requested it also carries roles, the roles model's own answer as it came, with its score, first_speaker, status and direction. That is diagnostics: its numbers arrive as strings and its shape may change. Take each speaker's role from speaker_info[].role.
Alongside them sit diagnostic fields — word_timing, formatting, partial. They are there for looking into our own tickets: what they hold may change, so do not build logic on them.
Utterance
| Field | What it is |
|---|---|
index | Ordinal, from 0 |
start, end | Seconds from the start of the recording |
speaker | Speaker number of the recording, or null |
text | Final text with the options applied |
raw_asr_text | What the model heard: lower-case, no punctuation |
formatted_text | With punctuation and capitals |
words | Words with timing, with word_timestamps; see below |
speaker_share | What share of the utterance's speech speaker separation itself placed with this speaker, 0 to 1; the rest was carried over from neighbouring words. Present only where speakers were computed |
contextual_text | The text after the vocabulary, before punctuation and numbers: between raw_asr_text and formatted_text |
duration_bucket_seconds | A length bucket for our own telemetry |
emotion | {"mood", "label", "confidence", "probabilities", "valence", "arousal", "dominance", "windows"}, with Emotions; an utterance under a second carries {"label": null, "reason": "too_short"}; see Emotion scales |
pii | {"entities", "redacted_text"}, with Personal data |
mood values: neutral, negative, distressed, positive, surprised. pii labels: NAME, PHONE, ADDRESS, DATE, DOCUMENT_ID, CARD_NUMBER.
A word
{"text": "Uzum", "raw": "uzim", "formatted": "Uzum", "start": 4.12, "end": 4.51, "speaker": 1, "aligned": "term"}| Field | What it is |
|---|---|
text | The word after the vocabulary, before punctuation |
raw | What the model heard in its place; an inserted word has no such field |
formatted | The same with capitals and punctuation, once the utterance is formatted |
start, end | Seconds from the start of the recording |
speaker | Speaker number, where speakers were computed |
aligned | Where the word's timing came from |
aligned is worth reading: exact — the model's own frames for that very word; term — the word came from the vocabulary and is timed by the term spotter's frames, which is direct evidence that the term was applied; span — its share of the raw words that were rewritten; chunk — the bundle gave no usable words for that piece, so the whole piece shares its timing; none — inserted with no acoustic evidence, zero length.
Speaker of the recording
| Field | What it is |
|---|---|
index | Speaker number, the same as in utterances |
speech_seconds | How long they spoke |
gender | {"label": "female" | "male" | "unknown", "confidence", "reason", "windows", "speech_seconds", "probabilities"}. With unknown, confidence is null and reason says why |
role | "client", "manager" or "unknown" |
identity | {"status", "voice_id", "speaker_id", "name", "score", "threshold", "runner_up", "kind"} |
has_voiceprint | The speaker spoke enough for a voice print: this one can be enrolled, see Voices and speakers. The print itself never leaves the gateway |
emotion | {"dominant_mood", "mood_share", "valence", "arousal", "dominance"} |
identity.status answers one question: was this person recognised, and if not, why not.
| Status | What happened | Is there a voice_id |
|---|---|---|
matched | The print matched a voice of the project | yes, the number of the known voice |
new | No match, but there was enough speech: the voice was registered by this recording and will be recognised from now on | yes, a new number |
unknown | No match, and under 10 seconds of speech — registering a voice on a print that short is unreliable | no |
insufficient_speech | No print could be computed at all: there is next to no speech | no |
no_enrolled_voices | The project has no voices yet, so there is nothing to compare against | no |
The difference between unknown and insufficient_speech is that the first has a print and the comparison ran — the person is simply not known and the speech is too short to register them; in the second there was nothing to compute from.
matched and unknown carry score, the closeness to the nearest voice from 0 to 1, and threshold, the point from which a match counts. If score sits just under the threshold again and again, the voice is short of prints: add another from a good recording.
Beside them is runner_up, the closeness to the second most similar voice (-1 when there was nothing to compare with). A match counts only when the first beat the second by a margin: two similar voices must not win against each other by chance. matched and new also carry kind — what sort of voice this is in the project: candidate, recurring or named, see Voices and speakers.
Emotion scales
The emotion model listens to an utterance and answers in two ways at once.
Class. label is one of the model's seven classes: neutral, happy, sad, angry, fearful, disgusted, surprised. probabilities gives the probability of each, confidence the probability of the chosen one. With seven classes a confidence of 0.5 is already a confident answer; below 0.35 the class is better not shown to an operator. mood is the class folded into five plain states: angry and disgusted into negative, sad and fearful into distressed, happy into positive.
Three scales from 0 to 1. They do not depend on the class and describe the state continuously:
| Scale | 0 | 1 | How to read |
|---|---|---|---|
valence | unpleasant | pleasant | Below 0.4 the customer is unhappy, above 0.6 pleased. The most useful scale for rating a call |
arousal | calm | worked up | High arousal with low valence is irritation or an argument, with high valence enthusiasm |
dominance | unsure | assertive | Who leads the conversation. A low value for a customer with high arousal often means confusion |
Values near 0.5 are neutral. Watch the trend across utterances rather than one number: a customer's valence falling over a call says more than its absolute value. windows tells from how many 15-second windows the utterance was averaged; for short utterances it is 1 and the estimate is noisier.
An utterance shorter than a second gets no reading at all: instead of numbers it carries {"label": null, "reason": "too_short"} — the model does not guess from a fragment. Short consecutive turns of one speaker are packed into a single window first, so "too short" mostly falls to a lone utterance such as a "Ha" in the middle of someone else's speech.
speaker_info[].emotion carries the same three scales averaged over all of a speaker's utterances, beside dominant_mood and mood_share, the share of each state. The cabinet draws the scales as bars: short ones on the utterance line, and a card per speaker under the player. Point at a bar and it says which measure it is, what its ends mean and the number itself; beside an utterance the model’s confidence in the emotion sits in the same row.
Before the job is done
GET /v1/jobs/{id}/result answers only for a finished job; while it runs you get 409 result_not_ready. Utterances as they are finished come from GET /v1/jobs/{id}/events: see API.