Главная → Блог → Распознавание речи на Java: код на стандартном HttpClient
Распознавание речи на Java: код на стандартном HttpClient
В Java начиная с одиннадцатой версии есть встроенный HTTP-клиент, и этого достаточно: сторонние библиотеки для отправки аудио не нужны. Единственная неприятность — multipart тело придётся собрать руками. Ниже готовый код.
Сборка multipart-запроса
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
import java.io.ByteArrayOutputStream;
String boundary = "----vs" + System.nanoTime();
Path audio = Path.of("call.ogg");
var body = new ByteArrayOutputStream();
body.write(("--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"model\"\r\n\r\nwhisper-1\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"file\"; filename=\"" + audio.getFileName() + "\"\r\n"
+ "Content-Type: audio/ogg\r\n\r\n").getBytes());
body.write(Files.readAllBytes(audio));
body.write(("\r\n--" + boundary + "--\r\n").getBytes());
var request = HttpRequest.newBuilder(URI.create("https://voicesscribe.com/v1/audio/transcriptions"))
.header("Authorization", "Bearer " + System.getenv("VS_KEY"))
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.timeout(java.time.Duration.ofMinutes(3))
.POST(HttpRequest.BodyPublishers.ofByteArray(body.toByteArray()))
.build();
var client = HttpClient.newHttpClient();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IllegalStateException("ошибка " + response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
Переводы строк в разделителях обязаны быть именно парой возврат каретки и перевод строки: с одиночным символом сервер не разберёт тело.
Разбор ответа
Ответ приходит в JSON с полем text. Любая привычная библиотека разбора подойдёт — Jackson, Gson или встроенные средства фреймворка:
record Transcription(String text) {}
var mapper = new com.fasterxml.jackson.databind.ObjectMapper();
var result = mapper.readValue(response.body(), Transcription.class);
System.out.println(result.text());
Если запрошен формат srt или vtt, ответ придёт не в JSON, а готовым текстом субтитров — разбирать его не нужно.
В сервисе под нагрузкой
Три вещи, которые стоит сделать сразу:
- Держать один экземпляр HttpClient на приложение — он потокобезопасен и переиспользует соединения.
- Не читать файл целиком в память для больших записей: BodyPublishers.ofFile отдаёт его потоком.
- Ограничить параллельность пулом фиксированного размера, подобранным под лимит запросов вашего тарифа.
Типовые ошибки
| Симптом | Причина |
|---|---|
| 400 на корректном файле | нет filename в части формы или неверный boundary |
| 401 | ключ не подставился из переменной окружения |
| 413 | файл больше 25 МБ, нужно сжать или разрезать |
| Обрыв на длинных записях | не задан timeout у запроса |
Попробуйте на своих записях. Регистрация занимает минуту, бесплатных минут хватает, чтобы оценить качество.
Получить ключ бесплатноЧастые вопросы
Нужна ли библиотека вроде OkHttp?
Не обязательно: встроенного HttpClient достаточно. OkHttp удобнее тем, что собирает multipart за вас.
Работает ли пример на Java 8?
Нет, встроенный HttpClient появился в одиннадцатой версии. На восьмой используйте OkHttp или Apache HttpClient.
Как передать язык записи?
Добавьте ещё одну часть формы с именем language и кодом языка, например ru.
Можно ли отправлять файл потоком?
Да, BodyPublishers.ofFile передаёт файл без загрузки в память — это важно для записей у верхней границы лимита.
Читайте также
- Распознавание речи в C#: подключение из .NET за пять минут — Как расшифровать аудио из C#: официальный клиент и вариант на HttpClient, асинхронная обработка, тайм-ауты и разбор ошибок в приложении на .NET.
- Распознавание речи на Go: рабочий код на стандартной библиотеке — Как отправить аудио на распознавание из Go: multipart-запрос на стандартной библиотеке, разбор ответа, тайм-ауты, повторы и параллельная обработка архива.
- Ошибки API распознавания речи и что они означают — Разбор кодов ответа API транскрибации: почему приходит 401, 400, 413, 429 и 502, как это чинить и как правильно повторять неудачные запросы.