Перейти к содержанию

Классификация эмоций в аудио

Emotion API анализирует голосовую окраску записи моделью DUSHA и возвращает вероятности пяти классов: angry, neutral, other, positive, sad. Модель валидирована для русской речи: API принимает lang=ru и lang=ru-RU. Поддержка эмоций для казахской, кыргызской, узбекской и таджикской речи не заявляется, даже если выбранная STT-модель умеет распознавать эти языки. Доступны два эквивалентных пути:

POST /api/stt/v1:recognizeEmotion
POST /api/emotion/v1

Запрос — multipart/form-data; требуется обычная аутентификация API-ключом или portal-сессией.

Параметры

Параметр По умолчанию Описание
audio — Обязательный аудио- или видеофайл в пределах лимита загрузки
aggregate mean mean усредняет вероятности всех окон; max_confidence выбирает окно с самой уверенной меткой
includeSegments false Вернуть результат каждого временного окна в segments; принимается также include_segments
negativeEmotionThreshold 0.5 Порог от 0 до 1 для суммы вероятностей angry + sad; принимается также negative_emotion_threshold
lang ru-RU После BCP-47-нормализации допустимы только ru и ru-RU; другой locale отклоняется с 400
format oggopus Подсказка формата, если контейнер нельзя определить по байтам
sampleRateHertz 16000 Частота только для headerless format=lpcm

Параметры можно передавать в query string или форму; для дублирующихся значений форма имеет приоритет. WAV читается напрямую, остальные контейнеры конвертируются в mono WAV 16 кГц. В отличие от файлового STT v1, здесь headerless PCM поддержан явно через format=lpcm&sampleRateHertz=.... В этом случае ожидается signed little-endian PCM16 mono.

Ответ

{
  "result": "neutral",
  "audio": "call.wav",
  "source_sample_rate": 48000,
  "model_sample_rate": 16000,
  "duration_sec": 12.4,
  "model": "dusha_emotion_ensemble_wav2vec_conformer_calibrated",
  "model_version": "1",
  "calibration_version": "sha256:...",
  "prediction": "neutral",
  "confidence": 0.71,
  "dominantEmotion": {
    "label": "neutral",
    "score": 0.71,
    "negative": false
  },
  "emotions": [
    {"label": "angry", "score": 0.05, "negative": true},
    {"label": "neutral", "score": 0.71, "negative": false},
    {"label": "other", "score": 0.08, "negative": false},
    {"label": "positive", "score": 0.12, "negative": false},
    {"label": "sad", "score": 0.04, "negative": true}
  ],
  "negative_emotion": false,
  "negative_emotion_score": 0.09,
  "negative_emotion_threshold": 0.5,
  "negativeEmotion": {
    "detected": false,
    "score": 0.09,
    "threshold": 0.5,
    "labels": ["angry", "sad"]
  },
  "probs": {
    "angry": 0.05,
    "neutral": 0.71,
    "other": 0.08,
    "positive": 0.12,
    "sad": 0.04
  },
  "top": [
    {"label": "neutral", "prob": 0.71},
    {"label": "positive", "prob": 0.12},
    {"label": "other", "prob": 0.08},
    {"label": "angry", "prob": 0.05},
    {"label": "sad", "prob": 0.04}
  ],
  "window_seconds": 3.0,
  "hop_seconds": 1.0,
  "num_windows": 11,
  "aggregate": "mean",
  "segments": null
}

top содержит все пять классов по убыванию вероятности. negativeEmotion дублирует snake_case-поля в удобной для совместимых клиентов форме. negative_emotion_score равен P(angry) + P(sad). Класс other следует интерпретировать только как другую или неопределённую акустическую окраску: контракт не называет его отдельным психологическим состоянием и не выдаёт за механизм достоверного определения намерений.

model_version содержит версию модели, а calibration_version — идентификатор использованной калибровки. Если идентификатор недоступен, поле равно null.

При includeSegments=true каждый элемент segments содержит start_sec, end_sec, prediction, confidence, negative_emotion, negative_emotion_score, dominantEmotion, emotions и probs. Размер окна и шаг возвращаются в ответе. В отдельном Emotion API это окна аудио без привязки к словам, репликам или спикерам STT. Для готовой связи «эпизод → таймкод → реплика → аудио» используйте интегрированный анализ в STT v1.

Интеграция со STT v1

POST /api/stt/v1 и POST /api/stt/v1:recognizeAsync могут запустить DUSHA параллельно с распознаванием того же канонического WAV. Повторно отправлять аудио в отдельный Emotion API не нужно:

emotionAnalysis=true
emotionIncludeSegments=true
emotionNegativeThreshold=0.5

Принимаются также snake_case-формы emotion_analysis, emotion_include_segments, emotion_negative_threshold. В ответ добавляются emotion_analysis и emotion_analysis_status. Результат содержит сглаженный negative-score, а также устойчивые негативные, позитивные и неопределённые эпизоды. Короткие разрывы объединяются, эпизоды связываются с пересекающимися utterances или segments. После сведения физических stereo- каналов модель не приписывает сигнал конкретному спикеру; персональная атрибуция требует отдельного per-channel анализа.

В session доступны:

  • negative_share — доля исходной временной шкалы, где сглаженный сигнал выше порога;
  • peak_negative_score — максимум сглаженного negative-score; поле peak_negative_ema содержит тот же показатель как явный alias;
  • peak_negative_raw_score — максимум исходного, несглаженного P(angry) + P(sad);
  • peak_at_ms — положение максимума сглаженного сигнала;
  • deescalation_score — среднее сглаженное значение на первых 20% окон минус среднее на последних 20%; положительное значение означает снижение сигнала;
  • каждый эпизод хранит mean_confidence и max_confidence, а совместимое поле confidence повторяет среднее значение;
  • deescalation_trend — improved, stable или worsened с опубликованным в metadata порогом изменения.

negative_share взвешен по времени исходной записи, а positive_share и uncertain_share показывают долю окон соответствующего производного состояния. Каждое окно и каждый эпизод сохраняют все пять raw probabilities. Параметры расчёта возвращаются вместе с результатом. Если анализ эмоций временно недоступен, успешный STT не теряется: статус становится unavailable или failed, а транскрипт возвращается как обычно.

Независимый сигнал по тексту

Для lang=ru-RU тот же emotionAnalysis=true дополнительно анализирует финальные utterances или segments по тексту. Результаты не смешиваются с акустическими вероятностями и возвращаются в соседних полях text_emotion_analysis и text_emotion_analysis_status.

Модель многометочная и возвращает joy, sadness, surprise, fear, anger и no_emotion. Каждый сигнал содержит model_score, все raw scores, исходную цитату, проанализированную clause, таймкоды, speaker и индексы исходной реплики/сегмента. model_score — выход модели, а не калиброванная вероятность истинной эмоции.

Контексты с отрицанием, возможным сарказмом, вопросом, косвенной речью или несколькими активными метками получают warnings и review_required=true. Если текстовый анализ недоступен, его статус равен unavailable, при ошибке обработки — failed; акустический анализ и готовая транскрипция при этом сохраняются.

Пример

curl -X POST \
  "https://api.speech.example.com/api/stt/v1:recognizeEmotion?aggregate=mean&includeSegments=true" \
  -H "Authorization: Api-Key $API_KEY" \
  -F "audio=@call.wav" \
  -F "negativeEmotionThreshold=0.5"

Связь со STT v3

Классификатор recognitionClassifier.classifiers[].classifier="negative" в STT v3 использует тот же анализ DUSHA, но возвращает SpeechKit-совместимый classifierUpdate. STT v3 вычисляет одну классификацию по полному файлу. Отдельный Emotion API удобнее, если нужны все вероятности и временные окна.

Интерпретация и ограничения

Модель оценивает вероятностную акустическую окраску русской речи. Это сигнал для навигации и ручной проверки исходного аудио, а не объективное определение внутреннего состояния человека. Безопасная последовательность использования:

emotion signal → выбор фрагмента → проверка человеком

Не используйте score как единственное основание для оценки сотрудника, штрафа, найма, медицинского вывода, оценки честности, кредитного или страхового решения. Для контакт-центра порог и качество следует отдельно проверить на своей телефонии, шуме, кодеках и составе спикеров.

Ошибки

Код Когда возникает
400 Пустой файл, неподдерживаемый язык, невалидный порог, частота LPCM, WAV или ошибка конвертации
401 Нет действующей аутентификации
413 Файл превышает серверный лимит
422 aggregate или другой параметр не прошёл проверку схемы
500 Неожиданная внутренняя ошибка
503 Сервис анализа эмоций недоступен или вернул ошибку

См. также