Zoom встречи
Узнайте, как обрабатывать записи Zoom-встреч через Nexara API.
Записи Zoom-встреч и онлайн-переговоров — частый сценарий: из одной записи можно получить расшифровку, разделение по участникам и готовый протокол встречи. Ниже разберём блок за блоком, а в конце соберём всё в один запрос и поделимся лайфхаками.
Разделение на говорящих
Включите диаризацию (task=diarize) и укажите diarization_setting=telephonic. Этот режим хорошо работает, где участники часто перебивают друг друга и говорят одновременно, как это обычно и бывает на встречах.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@meeting.mp3" \
-F "model=whisper-1" \
-F "task=diarize" \
-F "diarization_setting=telephonic"Модель whisper-1 — универсальная и хорошо подходит для встреч на разных языках. Число участников определяется автоматически.
Роли участников
Чтобы вместо безликих speaker_0/speaker_1 в расшифровке были понятные роли, добавьте roles=auto — модель сама подберёт подписи по содержанию разговора (например, Ведущий, Участник). Если роли известны заранее, можно передать их списком.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@meeting.mp3" \
-F "model=whisper-1" \
-F "task=diarize" \
-F "diarization_setting=telephonic" \
-F "roles=auto"Подробнее о режимах разметки — на странице спикеры и роли.
Аналитика встречи
Самое ценное — сразу получить из встречи структурированный результат. Добавьте prompt (и, для строгой структуры, json_schema). Модель получает расшифровку с ролями, поэтому учитывает, кто что говорил. Подробно про режимы — на странице LLM-анализ. Ниже — три частых сценария.
Протокол встречи
Готовый протокол, в котором будут указаны краткое резюме, принятые решения и задачи с ответственными.
{
"type": "object",
"properties": {
"summary": { "type": "string", "description": "Краткое резюме встречи" },
"decisions": {
"type": "array",
"items": { "type": "string" },
"description": "Принятые решения"
},
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"task": { "type": "string" },
"owner": {
"type": "string",
"description": "Ответственный, если назван"
}
},
"required": ["task"]
}
}
},
"required": ["summary", "decisions", "action_items"]
}Prompt: Составь протокол встречи: резюме, решения и задачи с ответственными.
Краткое резюме
Самый простой вариант — без схемы, ответ придёт текстом.
Prompt: Сделай краткое резюме встречи в пяти предложениях.
Список задач
Только задачи, поставленные на встрече, — для трекера или таск-менеджера.
{
"type": "object",
"properties": {
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"task": { "type": "string" },
"owner": { "type": "string" },
"deadline": { "type": "string", "description": "Срок, если назван" }
},
"required": ["task"]
}
}
},
"required": ["action_items"]
}Prompt: Выпиши все задачи, поставленные на встрече, с ответственными и сроками.
Собираем всё вместе
Один запрос: распознавание whisper-1, диаризация в режиме telephonic, авто-роли и протокол встречи через prompt + json_schema.
curl https://api.nexara.ru/v1/audio/transcriptions \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@meeting.mp3" \
-F "model=whisper-1" \
-F "task=diarize" \
-F "diarization_setting=telephonic" \
-F "roles=auto" \
-F "prompt=Составь протокол встречи: резюме, решения и задачи с ответственными." \
-F 'json_schema={"type":"object","properties":{"summary":{"type":"string"},"decisions":{"type":"array","items":{"type":"string"}},"action_items":{"type":"array","items":{"type":"object","properties":{"task":{"type":"string"},"owner":{"type":"string"}},"required":["task"]}}},"required":["summary","decisions","action_items"]}'import json
import requests
schema = {
"type": "object",
"properties": {
"summary": {"type": "string"},
"decisions": {"type": "array", "items": {"type": "string"}},
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"task": {"type": "string"},
"owner": {"type": "string"},
},
"required": ["task"],
},
},
},
"required": ["summary", "decisions", "action_items"],
}
with open("meeting.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": "whisper-1",
"task": "diarize",
"diarization_setting": "telephonic",
"roles": "auto",
"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: {
summary: { type: "string" },
decisions: { type: "array", items: { type: "string" } },
action_items: {
type: "array",
items: {
type: "object",
properties: {
task: { type: "string" },
owner: { type: "string" },
},
required: ["task"],
},
},
},
required: ["summary", "decisions", "action_items"],
};
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("meeting.mp3")]), "meeting.mp3");
form.append("model", "whisper-1");
form.append("task", "diarize");
form.append("diarization_setting", "telephonic");
form.append("roles", "auto");
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":{"summary":{"type":"string"},"decisions":{"type":"array","items":{"type":"string"}},"action_items":{"type":"array","items":{"type":"object","properties":{"task":{"type":"string"},"owner":{"type":"string"}},"required":["task"]}}},"required":["summary","decisions","action_items"]}`
file, _ := os.Open("meeting.mp3")
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, _ := writer.CreateFormFile("file", "meeting.mp3")
io.Copy(part, file)
writer.WriteField("model", "whisper-1")
writer.WriteField("task", "diarize")
writer.WriteField("diarization_setting", "telephonic")
writer.WriteField("roles", "auto")
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" => {
"summary" => { "type" => "string" },
"decisions" => { "type" => "array", "items" => { "type" => "string" } },
"action_items" => {
"type" => "array",
"items" => {
"type" => "object",
"properties" => {
"task" => { "type" => "string" },
"owner" => { "type" => "string" },
},
"required" => ["task"],
},
},
},
"required" => ["summary", "decisions", "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("meeting.mp3")],
["model", "whisper-1"],
["task", "diarize"],
["diarization_setting", "telephonic"],
["roles", "auto"],
["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": 3.4,
"text": "Давайте начнём. Сегодня обсудим релиз.",
"speaker": "Ведущий"
},
{
"start": 3.8,
"end": 7.2,
"text": "Я подготовлю тестовую сборку к пятнице.",
"speaker": "Участник"
}
]
},
"llm_output": {
"summary": "Команда обсудила предстоящий релиз и распределила задачи.",
"decisions": ["Выпустить релиз в конце недели"],
"action_items": [
{ "task": "Подготовить тестовую сборку", "owner": "Участник" }
]
}
}Лайфхаки
- Режим
telephonic. На встречах участники часто перебивают друг друга — этот режим справляется с такими записями лучше стандартного. - Авто-роли. На встречах состав участников заранее не известен, поэтому
roles=autoобычно удобнее фиксированного списка, но если у вас есть список, лучше его передать для лучшего качества. - Длинные встречи — асинхронный режим. Записи совещаний бывают долгими, не держите HTTP-соединение открытым всё это время.
- Большие файлы — по ссылке. Запись встречи удобно отдавать по URL (например, pre-signed ссылке на хранилище), а не загружать файлом.
- Вложенные схемы. Для задач с ответственными используйте массив объектов в
json_schema— так каждую задачу можно сразу разложить на поля.
Диаризация, разметка ролей и LLM-анализ тарифицируются дополнительно к стоимости распознавания. Итоговую стоимость смотрите на странице тарифов.