Асинхронное распознавание
Узнайте, как поставить задачу транскрибации в фон.
Асинхронный режим подходит для длинных записей и пакетной обработки: запрос не держит HTTP-соединение открытым всё время обработки. Вместо этого он сразу возвращает job_id, а готовый результат вы забираете отдельным запросом. Подробнее о разнице режимов — на странице синхронная и асинхронная обработка.
Шаг 1. Поставить задачу
Отправьте аудио на POST /v1/audio/transcriptions/async. Запрос принимает те же параметры, что и синхронный (можно передать локальный file или ссылку url), но возвращается сразу, не дожидаясь обработки.
curl https://api.nexara.ru/v1/audio/transcriptions/async \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@long-audio.mp3" \
-F "model=whisper-1"import requests
with open("long-audio.mp3", "rb") as audio_file:
response = requests.post(
"https://api.nexara.ru/v1/audio/transcriptions/async",
headers={"Authorization": "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"},
files={"file": audio_file},
data={"model": "whisper-1"},
)
job_id = response.json()["job_id"]
print(job_id)Node.js 18+:
import fs from "fs";
const form = new FormData();
form.append("file", new Blob([fs.readFileSync("long-audio.mp3")]), "long-audio.mp3");
form.append("model", "whisper-1");
const response = await fetch(
"https://api.nexara.ru/v1/audio/transcriptions/async",
{
method: "POST",
headers: { Authorization: "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" },
body: form,
},
);
const { job_id } = await response.json();
console.log(job_id);package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
file, _ := os.Open("long-audio.mp3")
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, _ := writer.CreateFormFile("file", "long-audio.mp3")
io.Copy(part, file)
writer.WriteField("model", "whisper-1")
writer.Close()
req, _ := http.NewRequest("POST", "https://api.nexara.ru/v1/audio/transcriptions/async", &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"
uri = URI("https://api.nexara.ru/v1/audio/transcriptions/async")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"
request.set_form(
[
["file", File.open("long-audio.mp3")],
["model", "whisper-1"],
],
"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)["job_id"]В ответ приходит идентификатор задачи и её статус:
{
"job_id": "5f1c2e3a-...",
"status": "in_progress",
"created_at": "2026-07-13T10:00:00+00:00"
}Сохраните job_id — по нему вы будете забирать результат.
Шаг 2. Опросить статус
Периодически запрашивайте GET /v1/audio/transcriptions/async/{job_id}, пока задача не завершится.
curl https://api.nexara.ru/v1/audio/transcriptions/async/5f1c2e3a-... \
-H "Authorization: Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"import requests
job_id = "5f1c2e3a-..."
response = requests.get(
f"https://api.nexara.ru/v1/audio/transcriptions/async/{job_id}",
headers={"Authorization": "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"},
)
print(response.json())const jobId = "5f1c2e3a-...";
const response = await fetch(
`https://api.nexara.ru/v1/audio/transcriptions/async/${jobId}`,
{ headers: { Authorization: "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX" } },
);
console.log(await response.json());package main
import (
"fmt"
"io"
"net/http"
)
func main() {
jobID := "5f1c2e3a-..."
req, _ := http.NewRequest("GET", "https://api.nexara.ru/v1/audio/transcriptions/async/"+jobID, nil)
req.Header.Set("Authorization", "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX")
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"
job_id = "5f1c2e3a-..."
uri = URI("https://api.nexara.ru/v1/audio/transcriptions/async/#{job_id}")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.bodyПока задача выполняется, поле result пустое:
{
"job_id": "5f1c2e3a-...",
"status": "in_progress",
"created_at": "2026-07-13T10:00:00+00:00",
"completed_at": null,
"result": null,
"error": null
}После завершения в поле result появляется готовая расшифровка:
{
"job_id": "5f1c2e3a-...",
"status": "complete",
"created_at": "2026-07-13T10:00:00+00:00",
"completed_at": "2026-07-13T10:01:12+00:00",
"result": {
"text": "Привет! Это пример транскрибации."
},
"error": null
}Поле result может содержать любой из форматов ответа — в зависимости от параметра response_format, переданного при постановке задачи.
Статусы задачи
in_progress: задача поставлена в очередь или обрабатывается. Полеresultпустое;complete: обработка завершена успешно. Результат находится в полеresult, а время завершения — вcompleted_at;error: обработка завершилась ошибкой. Описание причины находится в полеerror.
Полный пример
Постановка задачи и опрос до готового результата в одном скрипте:
import time
import requests
headers = {"Authorization": "Bearer nx-XXXXXXXXXXXXXXXXXXXXXXXX"}
# 1. Поставить задачу
with open("long-audio.mp3", "rb") as audio_file:
job = requests.post(
"https://api.nexara.ru/v1/audio/transcriptions/async",
headers=headers,
files={"file": audio_file},
data={"model": "whisper-1"},
).json()
job_id = job["job_id"]
# 2. Опрашивать статус, пока задача не завершится
while True:
status = requests.get(
f"https://api.nexara.ru/v1/audio/transcriptions/async/{job_id}",
headers=headers,
).json()
if status["status"] == "complete":
print(status["result"]["text"])
break
if status["status"] == "error":
raise RuntimeError(status["error"])
time.sleep(3)Что учитывать
- Хранение результата. После завершения результат хранится на сервере 12 часов, а затем удаляется безвозвратно.
- Интервал опроса. Опрашивайте статус с разумным интервалом (например, раз в несколько секунд), чтобы так вы не упереться в лимит частоты запросов.
- Одновременные задачи. На один API-ключ может выполняться не более 200 задач одновременно. Дождитесь завершения текущих, прежде чем ставить новые. Подробнее — на странице лимитов.
- Частота запросов. Постановка задач и опрос статуса ограничены 10 запросами в секунду. Подробнее — на странице лимитов.
- Форматы и размер. Как и в синхронном режиме, принимается большинство аудио- и видеоформатов, а максимальный размер файла — 3 ГБ.
- Хранение ключа. Не вставляйте API-ключ прямо в код. Храните его в переменной окружения (например,
export NEXARA_API_KEY="nx-...") и ссылайтесь на неё. Подробнее — на странице аутентификации.