Skip to content

Формат ответа ​

GET /v1/jobs/{id}/result возвращает JSON. Пример для стерео-звонка со всеми опциями, сокращённый:

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. …",
  "language": {"code": "uz", "confidence": 0.97, "speech_seconds": 230.4, "share": {"uz": 0.91, "ru": 0.09}, "posterior": {"uz": 0.97, "ru": 0.03}},
  "call_outcome": {"outcome": "conversation", "reached": true, "confidence": 0.99, "probabilities": {"conversation": 0.99, "no_answer": 0.004, "operator_message": 0.003, "ivr": 0.003}, "answer_at": 11.4, "seconds": 180.0},
  "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.",
      "pii": {"entities": [], "redacted_text": "Assalomu alaykum, Metasell kompaniyasi."},
      "language": {"code": "uz", "confidence": 0.99}
    }
  ],
  "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,
      "clarity": {"scored_words": 412, "low_confidence_share": 0.071, "estimated_error_share": 0.118, "speech_rate": 5.6,
                  "line_quality": {"snr_db": 31.5, "clipping_share": 0.0, "bandwidth_hz": 3850, "band": "telephone"}}
    }
  ],
  "voices": [
    {"label": "SPEAKER_1", "speaker": 0, "voice_id": 100, "name": null, "status": "new"},
    {"label": "SPEAKER_2", "speaker": 1, "voice_id": 101, "name": "Азимбек", "status": "matched", "score": 0.97}
  ],
  "options_report": {"requested": ["gender", "speaker_roles", "speaker_identification", "pii", "language_detection", "call_outcome"], "errors": {}, "seconds": 1.8},
  "timing": {"decode_seconds": 0.3, "vad_seconds": 0.4, "stt_seconds": 2.1, "total_seconds": 4.9}
}

Текст приходит латиницей: модель обучена на латинской записи узбекского, и все опции (пунктуация, числа, персональные данные) работают с ней. Кириллицы на выходе нет.

Верхний уровень ​

ПолеЧто это
audio_secondsДлина записи; из неё считается списание в g
speech_secondsСколько в ней речи
channels, stereo_partiesКаналов в файле; true, если стороны разделены по каналам
speakersСколько голосов нашло разделение по спикерам
textВесь текст подряд
segmentsРеплики по порядку
speaker_infoСводка по каждому спикеру записи: что нашли опции, и clarity, когда спикеры известны
languageОсновной язык речи записи и доля каждого языка, при «Языке речи»; см. Опции
call_outcomeБыл ли живой разговор, а если нет, что играло вместо него; секунда, когда ответили. При «Дозвоне»; см. Опции
voice_eventsСмех, недовольство и энергия голоса: `[{"type": "laughter"
summaryКраткое резюме звонка: {"text", "lines", "read_lines"}, при «Кратком резюме звонка»; см. Опции
voicesПостоянные номера голосов проекта, при «Узнавать по голосу»
optionsНастройки, с которыми запись реально считалась: проект плюс settings запроса. Здесь все ключи со страницы Опции — включая stereo_channels_as_speakers, max_speakers, call_direction и fuzzy_itn (нестрогая нормализация чисел; по умолчанию выключена)
tenantБизнес интегратора, к которому относится запись, если задание его назвало; см. Тенанты
vocabulary_terms, vocabulary_droppedСколько терминов словаря взяла задача; true во втором, если после чистки не осталось ни одного
diarization_errortrue, если разделение по спикерам не отработало: номеров спикеров в записи не будет. При удачном разделении поле есть и равно null
options_reportКакие опции запрашивались, какие не посчитались и почему
segment_voiceprintsУ каких реплик есть голосовой отпечаток: {"dims", "format", "min_seconds", "segments": [индексы]}. Сами отпечатки наружу не отдаются — это список реплик, из которых можно завести голос через POST /v1/speakers/{id}/enroll с segment_indexes
timingСколько секунд заняла обработка: decode_seconds, vad_seconds, stt_seconds, format_seconds, diarization_seconds, total_seconds. Считаем по ним себя, а не вас

options_report показывает, что запрашивалось (requested), что не посчиталось и почему (errors), и сколько секунд ушло на опции (seconds). Если запрашивались роли, там же лежит roles: status, откалиброванный score (вероятность, что роли распределены верно) и остальные поля, описанные в разделе Клиент и менеджер. Роль каждого спикера берите из speaker_info[].role.

Рядом лежат служебные поля — word_timing, formatting, partial. Они для разбора наших же обращений: состав может поменяться, не стройте на них логику.

Реплика ​

ПолеЧто это
indexПорядковый номер, с 0
start, endСекунды от начала записи
speakerНомер спикера записи или null
textИтоговый текст с включёнными опциями
raw_asr_textКак услышала модель: строчные, без знаков
formatted_textС пунктуацией и заглавными
wordsСлова с временем, при word_timestamps; см. ниже
speaker_shareКакая доля речи реплики размечена самим разделением по спикерам, от 0 до 1; остальное унаследовано от соседних слов. Есть только там, где спикеры считались
contextual_textТекст после словаря, до пунктуации и чисел; между raw_asr_text и formatted_text
duration_bucket_secondsСлужебная корзина длительности для нашей телеметрии
emotionТолько если запрос присылает убранный ключ emotion: всегда {"label": null, "reason": "removed"}; см. Эмоции (убраны)
pii{"entities", "redacted_text"}, при «Персональных данных»
language{"code", "confidence"}, при «Языке речи»; у реплики короче секунды — {"code": null, "reason": "too_short"}

Метки pii: NAME, PHONE, ADDRESS, DATE, DOCUMENT_ID, CARD_NUMBER.

Слово ​

json
{"text": "kredit", "raw": "kredit", "formatted": "kredit", "start": 12.40, "end": 12.81, "speaker": 0, "aligned": "exact", "confidence": 0.93}
{"text": "Uzum", "raw": "uzim", "formatted": "Uzum", "start": 4.12, "end": 4.51, "speaker": 1, "aligned": "term", "confidence": null}
ПолеЧто это
textСлово после словаря, до пунктуации
rawЧто услышала модель на этом месте; у вставленного слова поля нет
formattedОно же с заглавными и знаками, когда реплика отформатирована
start, endСекунды от начала записи
speakerНомер спикера, если спикеры считались
alignedОткуда взято время слова
confidenceВероятность от 0 до 1, что слово распознано верно; null, если это не собственное слово модели (см. ниже)

aligned стоит читать: exact — кадры самой модели на этом слове; term — слово пришло из словаря и размечено по кадрам поисковика терминов, то есть это прямое доказательство, что термин применился; span — доля от переписанного куска; chunk — на этот кусок модель не дала слов, время у всего куска общее; none — слово вставлено без акустического подтверждения, длина нулевая.

Уверенность в слове. confidence — вероятность от 0 до 1, что слово распознано правильно. Она откалибрована на звонках, проверенных людьми: из всех слов с отметкой 0.8 верны примерно восемь из десяти. Число есть только у собственных слов модели (aligned: exact). У слова, которое корректор или ваш словарь поставили вместо услышанного (span, term), у вставленного без акустического подтверждения (none) и у куска без пригодных слов (chunk) — confidence: null: акустической оценки у них нет. Слова, переписанные корректором, верны заметно реже собственных слов модели, так что на null тоже стоит взглянуть.

Что измеряет уверенность. Она показывает, насколько распознаватель был уверен в услышанном, а не насколько хорошо человек говорил. Узкая телефонная линия, шум, тихий или перегруженный микрофон, наложение голосов, редкие имена и вставки на русском или английском снижают её так же, как неразборчивая речь. Большая доля слов с низкой уверенностью на одном звонке значит, что расшифровке этого спикера меньше стоит доверять. Сама по себе это не доказательство плохой дикции.

Спикер записи ​

ПолеЧто это
indexНомер спикера, тот же, что в репликах
speech_secondsСколько он говорил
gender{"label": "female" | "male" | "unknown", "confidence", "reason", "windows", "speech_seconds", "probabilities"}. У unknown поле confidence равно null, а reason говорит почему
role"client", "manager", "machine" (голос, звучавший только до ответа живого человека: голосовое меню, сообщение оператора связи), "other" (живой голос сверх двух собеседников) или "unknown". См. Клиент и менеджер
identity{"status", "voice_id", "speaker_id", "name", "score", "threshold", "runner_up", "kind"}
has_voiceprintУ спикера хватило речи на голосовой отпечаток: его можно назвать через Голоса и спикеры. Сам отпечаток наружу не отдаётся
emotionТолько с убранным ключом emotion: {"dominant_mood": null, "mood_share": {}, "valence": null, "arousal": null, "dominance": null, "reason": "removed"}
language{"code", "confidence", "seconds"} — язык по всей речи спикера; меньше двух секунд речи — {"code": null, "reason": "insufficient_speech"}
clarityНасколько распознаватель был уверен в словах этого спикера, рядом с качеством линии, по которой они пришли; см. Clarity

identity.status отвечает на один вопрос: узнали ли этого человека и, если нет, почему.

СтатусЧто произошлоЕсть ли voice_id
matchedОтпечаток совпал с голосом проектада, номер знакомого голоса
newНе совпал, но речи хватило: голос заведён этой записью и дальше будет узнаватьсяда, новый номер
unknownНе совпал, и речи меньше 10 секунд — заводить голос по такому отпечатку ненадёжнонет
insufficient_speechОтпечаток не удалось посчитать вовсе: речи почти нетнет
no_enrolled_voicesВ проекте ещё нет ни одного голоса, сравнивать не с чемнет

Разница между unknown и insufficient_speech в том, что в первом случае отпечаток есть и сравнение прошло, просто человек незнаком и речи мало для регистрации; во втором считать было нечего.

У matched и unknown рядом лежат score, близость к ближайшему голосу от 0 до 1, и threshold, порог, начиная с которого совпадение засчитывается. Если score регулярно чуть ниже порога, голосу не хватает отпечатков: добавьте ещё один из хорошей записи.

С known_speakers (только сотрудники) identity говорит о линиях сотрудников тенанта: status это matched, not_matched, not_enrolled (у названной линии ещё нет голоса) или insufficient_speech; совпадение несёт external_id, role, voice (кто из людей линии, 1–4) и expected, threshold равен 0,65, а runner_up это другой спикер звонка против той же линии. voice_id получают только сотрудники, а has_voiceprint нет: отпечатков такой записи не хранится.

Там же runner_up — близость ко второму по похожести голосу (-1, если сравнивать было не с чем). Совпадение засчитывается, только если первый обошёл второго с запасом: два похожих голоса не должны выигрывать друг у друга случайно. У matched и new есть ещё kind — какой это голос в проекте: candidate, recurring или named, см. Голоса и спикеры.

Clarity: уверенность распознавания по спикеру ​

speaker_info[].clarity считается для каждой записи, где известны спикеры, — стереозвонка со сторонами на разных каналах или моно-записи с разделением по спикерам, — при любых опциях и без доплаты.

json
"clarity": {
  "scored_words": 412,
  "low_confidence_share": 0.071,
  "estimated_error_share": 0.118,
  "speech_rate": 5.6,
  "line_quality": {"snr_db": 31.5, "clipping_share": 0.0, "bandwidth_hz": 3850, "band": "telephone"}
}
ПолеЧто это
scored_wordsСлова спикера, у которых есть confidence
low_confidence_shareДоля из них ниже 0.5, то есть скорее неверных, чем верных
estimated_error_shareСреднее 1 - confidence по ним: какая доля из них, по ожиданию, неверна
reasoninsufficient_words, когда таких слов меньше 40; обе доли тогда null
speech_rateСлоги (гласные буквы) в секунду собственной речи спикера
line_quality.snr_dbНасколько пики речи громче пауз между словами внутри реплик спикера, в дБ
line_quality.clipping_shareДоля речи спикера с отсчётами на пределе шкалы: перегруженный микрофон или линия
line_quality.bandwidth_hzДо какой частоты голос спикера доходит по этой линии
line_quality.bandnarrow — ниже 3 800 Гц, telephone — от 3 800 до 4 500 Гц, wide — от 4 500 Гц

Всё считается по собственным репликам спикера за всю запись, без моментов, когда одновременно говорит кто-то другой. На стереозвонке линия каждой стороны — её собственный канал. Если такой речи меньше секунды, line_quality и speech_rate равны null.

Линия отдельно от спикера. Доли стоят рядом с line_quality, измеренным по голосу того же спикера. Линию мы из них не вычитаем: по нашим измерениям она объясняет в них немногое. Сильнее всего сказывалась ширина полосы: у спикеров на narrow линии доля слов с низкой уверенностью почти вдвое выше, чем у остальных. В пределах шума обычных звонков уровень шума заметной разницы не давал. Почти половина разницы между спикерами общая для обоих участников одного звонка, то есть принадлежит звонку, а не человеку. Сравнивайте людей в одной band. Судите о человеке по многим звонкам, а не по одному, и в сравнении с собеседником на тех же звонках. Внимания стоит тот, кто звонок за звонком заметно выше своего собеседника на линии того же типа.

Ограничения. Доли не даются, если слов с оценкой меньше 40, и остаются шумными примерно до 100: плюс-минус 4 пункта при 40 словах, 2,5 при 100. В моно-записях разделение по спикерам относит примерно одно слово из двадцати не тому человеку; у стереозаписей со стороной на каждом канале этой проблемы нет. Темп речи считается по распознанным словам, поэтому там, где распознавание не справилось, он занижен. Калибровка сделана для узбекских звонков и текущей версии распознавателя и пересчитывается при каждой её смене.

Эмоции (убраны) ​

Опция «Эмоции» убрана 10 октября 2026 года: спрос на неё был невелик, а надёжно определять эмоции в звонках оказалось трудно. Ключ emotion по-прежнему принимается, чтобы интеграции не сломались, и ничего не стоит. Запрос, который его присылает, получает в прежних полях заглушку: {"label": null, "reason": "removed"} у каждой реплики, сводку спикера со значениями null и пустым mood_share в speaker_info[].emotion и options_report.emotion = {"status": "removed"}. Позже ключ будет удалён; см. Опции.

Пока задача не готова ​

GET /v1/jobs/{id}/result отдаёт результат только у готовой задачи; пока она идёт, приходит 409 result_not_ready. Реплики по мере готовности берутся из GET /v1/jobs/{id}/events: см. API.