Разработчикам

API транскрибирования речи

Транскрибируйте завершённые аудиофайлы с помощью заданий в очереди, бесплатных оценок, идемпотентной отправки и отслеживания использования на обоих серверах API.

На этой странице
  1. Конечные точки
  2. Подготовьте аудиофайл
  3. Отправьте задание транскрибирования
  4. Ключ идемпотентности
  5. Получите оценку без создания задания
  6. Получение транскрипции
  7. Использование api.multitel.net

Этот API транскрибирует завершённые аудиофайлы в виде заданий в очереди. Отправьте файл, сохраните возвращённый ID задания и запрашивайте задание, пока обработка не завершится. Отправляйте все запросы по HTTPS с учётными данными своего аккаунта: данными HTTP Basic, как показано в примерах, или токеном API, как описано в разделе Аутентификация. Храните учётные данные на своём сервере.

Конечные точки

Два сервера API, https://api.multi.tel и сервер совместимости https://api.multitel.net, используют общие для аккаунта задания, ключи идемпотентности, ограничения и расчёты. Кодирование загрузки и оболочка ответа различаются, поэтому последовательно используйте один сервер с соответствующим парсером.

ОперацияМетод и путь
Информация о сервисеGET /v3/speech_to_text
Отправить заданиеPOST /v3/speech_to_text
Получить оценку без создания заданияPOST /v3/speech_to_text/estimate
Получить заданиеGET /v3/speech_to_text/JOB_ID
Оплатить задание, ожидающее оплатыPOST /v3/speech_to_text/JOB_ID/settle
ИспользованиеGET /v3/speech_to_text/usage

На сервере api.multi.tel все пути также доступны с префиксом /v1/speech-to-text вместо /v3/speech_to_text, например POST /v1/speech-to-text/estimate. На сервере api.multitel.net используйте пути /v3/speech_to_text.

Ответ с информацией о сервисе содержит mode (batch), realtime (false), paidEnabled (принимаются ли сейчас новые платные задания), pricePerMinuteUsd (0.005), billingUnit (audio_second), maxAudioSeconds (7200) и maxUploadBytes (26214400), а также краткое описание в поле description. Получение этой информации бесплатно и работает, когда отправка платных заданий отключена; ответ 503 transcription_unavailable возвращается только тогда, когда сервис в целом недоступен.

Подготовьте аудиофайл

Используйте завершённый аудиофайл размером не более 25 MiB (26,214,400 байт) и длительностью не более 2 часов (7,200 секунд). При отправке файл должен распознаваться как медиафайл MP3, WAV, Ogg, FLAC, MOV или Matroska с аудиопотоком, а длительность в его метаданных должна быть больше нуля и не превышать 7,200 секунд. Распознанный файл, не прошедший эти проверки, отклоняется с 422 unsupported_audio. Файл, который невозможно прочитать ни в одном из этих форматов, сейчас может вместо этого отклоняться с ошибкой сервера (500); не отправляйте такой файл повторно без изменений. Одно лишь расширение файла не подтверждает совместимость.

Прохождение этих проверок не гарантирует, что аудио можно декодировать. Аудио обрабатывается как один или два канала. Файл с более чем двумя аудиоканалами, файл, декодированное аудио которого длится более 2 часов, или любой другой файл, декодирование которого не удалось при обработке, завершается как задание со статусом failed, обычно с кодом decode_failed, и плата за него не взимается. Перед отправкой преобразуйте многоканальное аудио в моно или стерео.

Необязательная языковая подсказка — это код языка речи из двух или трёх строчных букв, например en. Чтобы не указывать подсказку, пропустите поле; api.multi.tel отклоняет пустую строку. Подсказка направляет обработку, но не проверяется по списку поддерживаемых языков, поэтому используйте действительный код языка речи.

Отправьте задание транскрибирования

Отправьте JSON с заголовком Content-Type: application/json на POST https://api.multi.tel/v3/speech_to_text. Тело запроса может иметь размер до 35 MiB, чтобы вместить файл максимального размера после кодирования base64; большее тело отклоняется с 413.

ПолеЗначение
audioBase64Обязательное. Полный файл в стандартном кодировании base64 (A–Z, a–z, 0–9, +, /) с заполнением = при необходимости. Не добавляйте префикс data-URL, переносы строк или пробелы и не используйте URL-безопасный алфавит. Значение должно декодироваться в файл размером от 1 байта до 25 MiB и при повторном кодировании давать в точности тот же текст.
languageНеобязательная языковая подсказка, как описано выше.

Любое другое свойство JSON, включая idempotency_key, отклоняется с 400 invalid_transcription_request. Отправляйте ключ в заголовке.

Ключ идемпотентности

Для каждой отправки требуется заголовок Idempotency-Key длиной от 1 до 190 символов. Используйте буквы ASCII, цифры, -, _, . и : без пробелов в начале и в конце: сервер совместимости обрезает окружающие пробельные символы и измеряет ключ в байтах, поэтому другие символы на каждом сервере могут считаться по-разному. Отсутствующий ключ или ключ из 191 и более символов отклоняется с 400.

Ключи ограничены вашим аккаунтом и транскрибированием речи на обоих серверах и для всех учётных данных вашего аккаунта. Повторная отправка того же ключа с тем же файлом и языком возвращает существующее задание с HTTP 200 и duplicate: true независимо от его статуса и даже если обработка обновлена после создания задания, без повторной платы. Повторное использование ключа с другим файлом или языком возвращает 409 idempotency_conflict. Новый ключ создаёт новое задание даже для идентичного файла, с отдельной платой при успешном завершении обработки.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

node -e 'process.stdout.write(JSON.stringify({audioBase64:require("node:fs").readFileSync("completed-call.mp3").toString("base64"),language:"en"}))' > completed-call.json

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: speech-call-001" \
  --data-binary @completed-call.json \
  -o speech-job.json \
  https://api.multi.tel/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).data.id'

Новое задание возвращает HTTP 202 с показанными ниже полями, а повторная отправка возвращает HTTP 200 с полным объектом задания, описанным в разделе Получение транскрипции. Прочитайте ID задания, UUID, из data.id. Ответ нового задания выглядит так (идентификатор и значения приведены для примера):

{
  "status": "success",
  "data": {
    "id": "3f6c1b2e-8a4d-4e7f-9c21-5b0d7e4a9f13",
    "status": "queued",
    "mode": "batch",
    "realtime": false,
    "source": "api",
    "durationSeconds": 90.5,
    "billedSeconds": 91,
    "costUsd": "0.007583334",
    "pricePerMinuteUsd": "0.005"
  }
}

Пока задание в очереди или выполняется, durationSeconds, billedSeconds и costUsd являются оценками из метаданных файла. Окончательная плата определяется по декодированной длительности.

Отправка также может вернуть 402 insufficient_balance, когда предоплаченного баланса недостаточно для этого задания вместе с другими вашими незавершёнными заданиями, 429 transcription_queue_full, когда в вашем аккаунте или в сервисе слишком много незавершённых заданий, 429 audio_validation_busy, когда мощности проверки файлов исчерпаны, и 503 paid_transcription_not_enabled, когда платное транскрибирование отключено. После ответов 429 и 503 повторите попытку позже с тем же ключом.

Получите оценку без создания задания

Отправьте то же тело JSON на POST https://api.multi.tel/v3/speech_to_text/estimate. Ключ идемпотентности не требуется. Оценка проверяет и измеряет файл, но не транскрибирует его, не создаёт задание, не резервирует средства, не проверяет баланс и не списывает средства с вашего аккаунта. Подсказка language принимается, но не влияет на оценку.

Успешная оценка возвращает HTTP 200 с полями estimate: true, charged: false, mode, realtime, durationSeconds, billedSeconds, pricePerMinuteUsd и costUsd в объекте data. Она использует длительность из метаданных файла, тогда как плата за завершённое задание определяется по декодированной длительности, которая может отличаться. К оценкам применяются те же проверки файлов, что и к отправкам. Они доступны только когда платное транскрибирование включено (иначе 503 paid_transcription_not_enabled). Они могут возвращать 429 audio_validation_busy, когда мощности проверки файлов исчерпаны; повторите попытку после короткой паузы.

Получение транскрипции

Периодически запрашивайте GET /v3/speech_to_text/JOB_ID, как описано в руководстве по рабочему процессу заданий. Объект задания содержит следующие поля:

ПолеЗначение
idUUID задания.
statusqueued, running, completed, failed или awaiting_payment.
progressПроцент от 0 до 99 во время выполнения, если доступен; 100 после завершения; иначе null.
durationSeconds, billedSecondsДлительность аудио и оплачиваемые целые секунды. Пока задание в очереди или выполняется, это оценки из метаданных; после завершения или при ожидании оплаты используется декодированная длительность.
costUsd, costIsEstimateСтоимость в долларах США в виде десятичной строки с девятью знаками после запятой. costIsEstimate имеет значение true, пока задание в очереди или выполняется. За неудачное задание плата не взимается, хотя его costUsd по-прежнему показывает оценку.
pricePerMinuteUsd0.005 для заданий API и 0.000 для бесплатных заданий записей Hosted PBX.
failureCodeДля неудачного задания: decode_failed (аудио не удалось декодировать, например из-за более чем двух каналов или длительности более 2 часов после декодирования), inference_timeout (обработка длилась слишком долго), service_error или worker_lease_lost (обработка прервана). Также определены коды unsupported_audio и quality_check_failed. Задание, ожидающее оплаты, показывает insufficient_balance, который может сохраниться после оплаты задания.
source, modelVersion, createdAtsource имеет значение api для отправок через API или hpbx для задания записи Hosted PBX вашего аккаунта. modelVersion — непрозрачная строка версии обработки. createdAt — время отправки.
duplicatetrue в ответах, возвращающих существующее задание.
resultПрисутствует только когда status имеет значение completed.
Поле результатаЗначение
textПолная транскрипция: тексты всех сегментов, соединённые переносами строк в порядке сегментов.
segmentsМассив сегментов, упорядоченный по времени начала. Каждый сегмент охватывает участок аудио длительностью примерно до 29 секунд. Его start и end (секунды от начала аудио) обозначают этот участок, а не отдельные слова или предложения, а последовательные участки могут перекрываться до 1 секунды. Каждый сегмент также имеет text и language (код языка, который может быть пустым), а также channel для двухканальных результатов.
channelCount1 или 2. Присутствует в текущих результатах; в старых может отсутствовать.
audioDurationMsДекодированная длительность в миллисекундах. Для начисления платы она округляется вверх до целых секунд.
qualityFlagsПустое или review_recommended вместе с repetition_detected (фраза повторяется на участке необычно часто), no_speech (речь не была транскрибирована), либо оба.
pipelineVersionМожет присутствовать. Непрозрачный идентификатор обработки.

Транскрипции и их временные метки, языковые метки и метки каналов создаются автоматически, и их точность не гарантируется. Считайте любой флаг качества поводом проверить результат и сравнивайте важные имена, числа и обязательства с исходным аудио. Длительные паузы и очень тихие участки пропускаются и не образуют сегментов. Результаты не идентифицируют отдельных говорящих. Когда в результате channelCount равен 2, каждый сегмент имеет channel со значением A (первый, или левый, канал) либо B (второй, или правый, канал). Это разделяет говорящих только тогда, когда каждый был записан на отдельном канале. За двухканальное аудио плата взимается один раз по его общей длительности, а не за каждый канал. Монофонические результаты не имеют меток каналов.

Использование api.multitel.net

Конечная точка совместимости POST https://api.multitel.net/v3/speech_to_text принимает multipart/form-data с файловой частью audio и необязательным полем language вместо JSON audioBase64. Пустое значение language считается отсутствием подсказки. Отправляйте тот же заголовок Idempotency-Key. Если заголовок отсутствует, этот сервер также принимает поле формы idempotency_key. Поля с именами source, free, billing_source, realtime или stream отклоняются с 400 unsupported_transcription_option; другие поля формы игнорируются. Этот сервер также возвращает следующие ошибки:

  • 400 idempotency_key_required, если ключ отсутствует или слишком длинный.
  • 400 audio_upload_required, если загрузка отсутствует или получена не полностью.
  • 400 invalid_language, если язык недействителен.
  • 413 invalid_audio_size, если файл пустой или слишком большой.
  • 400 invalid_job, если ID задания имеет неверный формат.

Ответы сервиса транскрибирования речи на этом сервере используют оболочку {"status":{"code":HTTP_STATUS},"response":{...}}. Обратите внимание: status является объектом, а не строкой. При успехе response содержит тот же объект, что и data на основном сервере, поэтому ID задания — response.id. При ошибке response.code содержит код ошибки; сообщение и ID запроса не включаются. Ошибки аутентификации (401) возвращает общая проверка входа сервера, и они могут иметь другое тело, поэтому проверяйте статус HTTP перед разбором. Не используйте кодирование загрузки или парсер ответа одного сервера для другого.

Чтобы получить оценку на этом сервере, отправьте те же multipart-поля методом POST на /v3/speech_to_text/estimate. Ключ идемпотентности не требуется, а оценка находится в response.

API_USER="your-api-username"
API_PASSWORD="your-api-password"

curl --fail-with-body --silent --show-error --user "$API_USER:$API_PASSWORD" \
  -H "Idempotency-Key: speech-call-001" \
  -F "audio=@completed-call.mp3" -F "language=en" \
  -o speech-job.json \
  https://api.multitel.net/v3/speech_to_text

node -p 'JSON.parse(require("node:fs").readFileSync("speech-job.json","utf8")).response.id'