Телефонные звонки
Узнайте, как обрабатывать телефонные звонки через Nexara API.
Телефонные звонки — самый частый сценарий для колл-центров и отделов продаж. Из одной записи можно получить сразу всё: расшифровку, разделение на оператора и клиента, а также готовую аналитику звонка. Ниже разберём блок за блоком, а в конце соберём всё в один запрос и поделимся лайфхаками.
Разделение на говорящих
Для звонков включите диаризацию (task=diarize) и передайте num_speakers=2 — в разговоре обычно двое.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@call.mp3" \
-F "model=whisper-1" \
-F "task=diarize" \
-F "num_speakers=2"Если телефония умеет писать звонки в двухканальном (стерео) формате, где каждый
участник на своём канале, — используйте именно его. В связке с num_speakers=2
это даёт самое точное разделение.
Роли вместо speaker_0 и speaker_1
Чтобы в расшифровке сразу были понятные роли, а не безликие speaker_0/speaker_1, передайте roles со своими метками. Для аналитики это гораздо удобнее.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@call.mp3" \
-F "model=whisper-1" \
-F "task=diarize" \
-F "num_speakers=2" \
-F 'roles=["Оператор", "Клиент"]'В сегментах вместо speaker_N появятся Оператор и Клиент. Подробнее — на странице спикеры и роли.
Русские звонки
Если разговор на русском языке, используйте модель nexara-ru — она заточена под русскую речь и даёт более точную расшифровку, чем универсальная whisper-1.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@call.mp3" \
-F "model=nexara-ru" \
-F "task=diarize" \
-F "num_speakers=2"Фильтрация мата
В звонках нередко проскакивает нецензурная лексика. Чтобы замаскировать её в расшифровке (например, для отчётов и выгрузок), добавьте profanity_filter=true.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@call.mp3" \
-F "model=nexara-ru" \
-F "task=diarize" \
-F "num_speakers=2" \
-F "profanity_filter=true"Аналитика звонка
Самое ценное — сразу получить из звонка структурированную аналитику. Для этого добавьте prompt (и, для строгой структуры, json_schema). Модель получает расшифровку с ролями, поэтому анализ учитывает, кто что сказал. Подробно про режимы — на странице LLM-анализ. Ниже — три самых частых сценария.
Карточка звонка
Готовая карточка для записи в CRM: тема, тональность, резюме, решён ли вопрос и список задач.
{
"type": "object",
"properties": {
"topic": { "type": "string", "description": "Причина обращения" },
"sentiment": {
"type": "string",
"enum": ["положительная", "нейтральная", "отрицательная"]
},
"summary": { "type": "string", "description": "Резюме разговора" },
"resolved": { "type": "boolean", "description": "Решён ли вопрос клиента" },
"action_items": { "type": "array", "items": { "type": "string" } }
},
"required": ["topic", "sentiment", "summary", "resolved", "action_items"]
}Prompt: Проанализируй телефонный разговор в поддержке и заполни карточку звонка.
Оценка качества (QA)
Проверка работы оператора по чек-листу для контроля качества.
{
"type": "object",
"properties": {
"greeting": { "type": "boolean", "description": "Оператор поздоровался и представился" },
"polite": { "type": "boolean", "description": "Оператор был вежлив" },
"resolved": { "type": "boolean", "description": "Вопрос клиента решён" },
"score": { "type": "integer", "description": "Оценка звонка от 1 до 5" },
"comment": { "type": "string", "description": "Короткий комментарий к оценке" }
},
"required": ["greeting", "polite", "resolved", "score", "comment"]
}Prompt: Оцени работу оператора в этом звонке по чек-листу.
Извлечение данных в CRM
Вытащить из разговора конкретные поля для автоматического заполнения карточки сделки.
{
"type": "object",
"properties": {
"client_name": { "type": "string" },
"phone": { "type": "string" },
"product": { "type": "string", "description": "Обсуждаемый товар или услуга" },
"amount": { "type": "number", "description": "Сумма сделки, если названа" },
"next_step": { "type": "string", "description": "О чём договорились" }
},
"required": ["client_name", "product"]
}Prompt: Извлеки данные о клиенте и сделке из разговора.
Собираем всё вместе
Один запрос для русского звонка: распознавание nexara-ru, диаризация с num_speakers=2, роли Оператор/Клиент и карточка звонка через prompt + json_schema.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@call.mp3" \
-F "model=nexara-ru" \
-F "task=diarize" \
-F "num_speakers=2" \
-F 'roles=["Оператор", "Клиент"]' \
-F "prompt=Проанализируй телефонный разговор в поддержке и заполни карточку звонка." \
-F 'json_schema={"type":"object","properties":{"topic":{"type":"string"},"sentiment":{"type":"string","enum":["положительная","нейтральная","отрицательная"]},"summary":{"type":"string"},"resolved":{"type":"boolean"},"action_items":{"type":"array","items":{"type":"string"}}},"required":["topic","sentiment","summary","resolved","action_items"]}'import json
import requests
schema = {
"type": "object",
"properties": {
"topic": {"type": "string"},
"sentiment": {
"type": "string",
"enum": ["положительная", "нейтральная", "отрицательная"],
},
"summary": {"type": "string"},
"resolved": {"type": "boolean"},
"action_items": {"type": "array", "items": {"type": "string"}},
},
"required": ["topic", "sentiment", "summary", "resolved", "action_items"],
}
with open("call.mp3", "rb") as audio_file:
response = requests.post(
"https://api.nexara.ru/v1/audio/transcriptions",
headers={"Authorization": "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"},
files={"file": audio_file},
data={
"model": "nexara-ru",
"task": "diarize",
"num_speakers": "2",
"roles": json.dumps(["Оператор", "Клиент"]),
"prompt": "Проанализируй телефонный разговор в поддержке и заполни карточку звонка.",
"json_schema": json.dumps(schema),
},
)
result = response.json()
print(result["llm_output"])Node.js 18+:
import fs from "fs";
const schema = {
type: "object",
properties: {
topic: { type: "string" },
sentiment: {
type: "string",
enum: ["положительная", "нейтральная", "отрицательная"],
},
summary: { type: "string" },
resolved: { type: "boolean" },
action_items: { type: "array", items: { type: "string" } },
},
required: ["topic", "sentiment", "summary", "resolved", "action_items"],
};
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("call.mp3")]), "call.mp3");
form.append("model", "nexara-ru");
form.append("task", "diarize");
form.append("num_speakers", "2");
form.append("roles", JSON.stringify(["Оператор", "Клиент"]));
form.append("prompt", "Проанализируй телефонный разговор в поддержке и заполни карточку звонка.");
form.append("json_schema", JSON.stringify(schema));
const response = await fetch(
"https://api.nexara.ru/v1/audio/transcriptions",
{
method: "POST",
headers: { Authorization: "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" },
body: form,
},
);
const result = await response.json();
console.log(result.llm_output);package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
schema := `{"type":"object","properties":{"topic":{"type":"string"},"sentiment":{"type":"string","enum":["положительная","нейтральная","отрицательная"]},"summary":{"type":"string"},"resolved":{"type":"boolean"},"action_items":{"type":"array","items":{"type":"string"}}},"required":["topic","sentiment","summary","resolved","action_items"]}`
file, _ := os.Open("call.mp3")
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, _ := writer.CreateFormFile("file", "call.mp3")
io.Copy(part, file)
writer.WriteField("model", "nexara-ru")
writer.WriteField("task", "diarize")
writer.WriteField("num_speakers", "2")
writer.WriteField("roles", `["Оператор", "Клиент"]`)
writer.WriteField("prompt", "Проанализируй телефонный разговор в поддержке и заполни карточку звонка.")
writer.WriteField("json_schema", schema)
writer.Close()
req, _ := http.NewRequest("POST", "https://api.nexara.ru/v1/audio/transcriptions", &buf)
req.Header.Set("Authorization", "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX")
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "uri"
require "json"
schema = {
"type" => "object",
"properties" => {
"topic" => { "type" => "string" },
"sentiment" => {
"type" => "string",
"enum" => ["положительная", "нейтральная", "отрицательная"],
},
"summary" => { "type" => "string" },
"resolved" => { "type" => "boolean" },
"action_items" => { "type" => "array", "items" => { "type" => "string" } },
},
"required" => ["topic", "sentiment", "summary", "resolved", "action_items"],
}
uri = URI("https://api.nexara.ru/v1/audio/transcriptions")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"
request.set_form(
[
["file", File.open("call.mp3")],
["model", "nexara-ru"],
["task", "diarize"],
["num_speakers", "2"],
["roles", ["Оператор", "Клиент"].to_json],
["prompt", "Проанализируй телефонный разговор в поддержке и заполни карточку звонка."],
["json_schema", schema.to_json],
],
"multipart/form-data",
)
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts JSON.parse(response.body)["llm_output"]В ответе придёт расшифровка с ролями и готовая карточка звонка:
{
"transcription": {
"task": "diarize",
"segments": [
{ "start": 0.0, "end": 2.1, "text": "Служба поддержки, здравствуйте.", "speaker": "Оператор" },
{ "start": 2.5, "end": 5.0, "text": "Здравствуйте, хочу оформить возврат.", "speaker": "Клиент" }
]
},
"llm_output": {
"topic": "Возврат товара",
"sentiment": "нейтральная",
"summary": "Клиент попросил оформить возврат, оператор объяснил условия и создал заявку.",
"resolved": true,
"action_items": ["Отправить клиенту инструкцию по возврату"]
}
}Лайфхаки
- Двухканальная запись. Если телефония поддерживает раздельную запись каналов, включите её — вместе с
num_speakers=2это даёт максимально точное разделение. - Точные роли. В сложных звонках передавайте роли с описаниями (
{"Оператор": "сотрудник поддержки", "Клиент": "позвонивший"}) — так модель распределяет их точнее. - Русская речь —
nexara-ru. Для звонков на русском эта модель точнее универсальной. - Передавайте большие файлы по ссылке. Удобно отдавать запись по URL (например, pre-signed ссылке на хранилище), а не загружать файлом.
Диаризация, разметка ролей и LLM-анализ тарифицируются дополнительно к стоимости распознавания. Итоговую стоимость смотрите на странице тарифов.