InícioBlog → Voz para texto em Java: código no HttpClient padrão

Voz para texto em Java: código no HttpClient padrão

Publicado em 2026-08-20 · 5 min de leitura

O Java traz um cliente HTTP nativo desde a versão 11, e isso basta: nenhuma biblioteca de terceiros é necessária para enviar áudio. O único incômodo é montar o corpo multipart à mão. Segue o código pronto para colar.

Montando a requisição 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("erro " + response.statusCode() + ": " + response.body());
}
System.out.println(response.body());

As quebras de linha nos delimitadores precisam ser retorno de carro mais avanço de linha: com uma quebra simples o servidor não consegue interpretar o corpo.

Lendo a resposta

A resposta é um JSON com o campo text. Qualquer biblioteca conhecida serve — Jackson, Gson ou o suporte nativo do seu framework:

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());

Se você pediu srt ou vtt, a resposta não é JSON e sim um arquivo de legenda pronto — nada a interpretar.

Sob carga

Três coisas que convém fazer desde o começo:

  1. Manter um HttpClient por aplicação — ele é seguro para várias threads e reaproveita conexões.
  2. Não ler arquivos grandes inteiros na memória: BodyPublishers.ofFile os transmite em fluxo.
  3. Limitar o paralelismo com um pool de threads fixo, dimensionado pelo limite de taxa do plano.

Falhas comuns

SintomaCausa
400 num arquivo válidoparte do formulário sem filename ou delimitador quebrado
401a chave não saiu da variável de ambiente
413arquivo acima de 25 MB — comprima ou divida
Corte em arquivos longosrequisição sem tempo limite definido

Teste com as suas próprias gravações. O cadastro leva um minuto e os minutos gratuitos bastam para avaliar a qualidade.

Obter uma chave de API grátis

Perguntas frequentes

Preciso de OkHttp ou Apache HttpClient?

Não necessariamente: o cliente nativo basta. O OkHttp é mais confortável porque monta o corpo multipart por você.

O exemplo roda no Java 8?

Não, o HttpClient nativo chegou no Java 11. Na versão 8 use OkHttp ou Apache HttpClient.

Como indicar o idioma do áudio?

Acrescente outra parte do formulário chamada language com o código, por exemplo pt.

Dá para transmitir o arquivo sem carregá-lo?

Dá, BodyPublishers.ofFile envia sem carregar na memória, o que importa em arquivos próximos do limite.

Leitura relacionada