Skip to content

Result format

GET /v1/jobs/{id}/result returns JSON. A shortened example for a stereo call with every option on:

json
{
  "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

FieldWhat it is
audio_secondsLength of the recording; the charge in g is worked out from it
speech_secondsHow much of it is speech
channels, stereo_partiesChannels in the file; true when the sides are separated by channel
speakersHow many voices speaker separation found
textAll text in a row
segmentsUtterances in order
speaker_infoA summary per speaker of the recording
voicesPermanent project voice numbers, with "Recognise by voice"
optionsThe 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_droppedHow many vocabulary terms the job took; the second is true when the cleaning left none
diarization_errortrue when speaker separation did not work: the recording will carry no speaker numbers. When it worked, the field is there and is null
options_reportWhich options were requested, which were not computed and why
segment_voiceprintsWhich 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
timingHow 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

FieldWhat it is
indexOrdinal, from 0
start, endSeconds from the start of the recording
speakerSpeaker number of the recording, or null
textFinal text with the options applied
raw_asr_textWhat the model heard: lower-case, no punctuation
formatted_textWith punctuation and capitals
wordsWords with timing, with word_timestamps; see below
speaker_shareWhat 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_textThe text after the vocabulary, before punctuation and numbers: between raw_asr_text and formatted_text
duration_bucket_secondsA 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

json
{"text": "Uzum", "raw": "uzim", "formatted": "Uzum", "start": 4.12, "end": 4.51, "speaker": 1, "aligned": "term"}
FieldWhat it is
textThe word after the vocabulary, before punctuation
rawWhat the model heard in its place; an inserted word has no such field
formattedThe same with capitals and punctuation, once the utterance is formatted
start, endSeconds from the start of the recording
speakerSpeaker number, where speakers were computed
alignedWhere 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

FieldWhat it is
indexSpeaker number, the same as in utterances
speech_secondsHow 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_voiceprintThe 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.

StatusWhat happenedIs there a voice_id
matchedThe print matched a voice of the projectyes, the number of the known voice
newNo match, but there was enough speech: the voice was registered by this recording and will be recognised from now onyes, a new number
unknownNo match, and under 10 seconds of speech — registering a voice on a print that short is unreliableno
insufficient_speechNo print could be computed at all: there is next to no speechno
no_enrolled_voicesThe project has no voices yet, so there is nothing to compare againstno

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:

Scale01How to read
valenceunpleasantpleasantBelow 0.4 the customer is unhappy, above 0.6 pleased. The most useful scale for rating a call
arousalcalmworked upHigh arousal with low valence is irritation or an argument, with high valence enthusiasm
dominanceunsureassertiveWho 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.