Insights & Use Cases
August 21, 2026

How to use AssemblyAI with Java

Use AssemblyAI's Speech AI models from Java with the built-in HttpClient — transcribe files, stream audio in real time, apply LLMs with LLM Gateway, and run sentiment analysis.

Martin Schweiger
Technical Product Marketing Manager
No items found.
Reviewed by
No items found.
Table of contents

Learn how to use AssemblyAI's Speech AI models directly with Java using the built-in HttpClient. Transcribe audio, analyze audio using audio intelligence models, and apply LLMs to your audio data using LLM Gateway.

1. Transcribe an audio file

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class TranscribeUrl {
    public static void main(String[] args) throws Exception {
        HttpClient httpClient = HttpClient.newHttpClient();
        String apiKey = "YOUR_API_KEY";

        // Submit transcription request
        String requestBody = """
            {
                "audio_url": "https://storage.googleapis.com/aai-docs-samples/nbc.mp3",
                "speech_models": ["universal-3-pro", "universal-2"],
                "language_detection": true
            }
            """;

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.assemblyai.com/v2/transcript"))
            .header("Authorization", apiKey)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        JsonObject transcript = JsonParser.parseString(response.body()).getAsJsonObject();
        String transcriptId = transcript.get("id").getAsString();

        // Poll until completed
        while (true) {
            HttpRequest pollRequest = HttpRequest.newBuilder()
                .uri(URI.create("https://api.assemblyai.com/v2/transcript/" + transcriptId))
                .header("Authorization", apiKey)
                .GET()
                .build();

            HttpResponse<String> pollResponse = httpClient.send(pollRequest, HttpResponse.BodyHandlers.ofString());
            JsonObject result = JsonParser.parseString(pollResponse.body()).getAsJsonObject();
            String status = result.get("status").getAsString();

            if (status.equals("completed")) {
                System.out.println(result.get("text").getAsString());
                break;
            } else if (status.equals("error")) {
                System.out.println("Transcription failed: " + result.get("error").getAsString());
                break;
            }

            Thread.sleep(3000);
        }
    }
}

You can also transcribe a local file, as shown here.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class TranscribeLocalFile {
    public static void main(String[] args) throws Exception {
        HttpClient httpClient = HttpClient.newHttpClient();
        String apiKey = "YOUR_API_KEY";

        // Step 1: Upload the file
        byte[] fileBytes = Files.readAllBytes(Path.of("./audio.mp3"));
        HttpRequest uploadRequest = HttpRequest.newBuilder()
            .uri(URI.create("https://api.assemblyai.com/v2/upload"))
            .header("Authorization", apiKey)
            .POST(HttpRequest.BodyPublishers.ofByteArray(fileBytes))
            .build();

        HttpResponse<String> uploadResponse = httpClient.send(uploadRequest, HttpResponse.BodyHandlers.ofString());
        JsonObject uploadResult = JsonParser.parseString(uploadResponse.body()).getAsJsonObject();
        String uploadUrl = uploadResult.get("upload_url").getAsString();

        // Step 2: Submit transcription with upload URL
        String requestBody = String.format("""
            {
                "audio_url": "%s",
                "speech_models": ["universal-3-pro", "universal-2"],
                "language_detection": true
            }
            """, uploadUrl);

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.assemblyai.com/v2/transcript"))
            .header("Authorization", apiKey)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        JsonObject transcript = JsonParser.parseString(response.body()).getAsJsonObject();
        String transcriptId = transcript.get("id").getAsString();

        // Step 3: Poll until completed
        while (true) {
            HttpRequest pollRequest = HttpRequest.newBuilder()
                .uri(URI.create("https://api.assemblyai.com/v2/transcript/" + transcriptId))
                .header("Authorization", apiKey)
                .GET()
                .build();

            HttpResponse<String> pollResponse = httpClient.send(pollRequest, HttpResponse.BodyHandlers.ofString());
            JsonObject result = JsonParser.parseString(pollResponse.body()).getAsJsonObject();
            String status = result.get("status").getAsString();

            if (status.equals("completed")) {
                System.out.println(result.get("text").getAsString());
                break;
            } else if (status.equals("error")) {
                System.out.println("Transcription failed: " + result.get("error").getAsString());
                break;
            }

            Thread.sleep(3000);
        }
    }
}

2. Transcribe audio in real-time

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletionStage;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

String apiKey = System.getenv("ASSEMBLYAI_API_KEY");

WebSocket ws = HttpClient.newHttpClient().newWebSocketBuilder()
    .header("Authorization", apiKey)
    .buildAsync(URI.create("wss://streaming.assemblyai.com/v3/ws?sample_rate=16000&format_turns=true"),
        new WebSocket.Listener() {
            @Override
            public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
                JsonObject message = JsonParser.parseString(data.toString()).getAsJsonObject();
                String messageType = message.get("type").getAsString();

                if (messageType.equals("Begin")) {
                    System.out.println("Session started: " + message.get("id").getAsString());
                } else if (messageType.equals("Turn")) {
                    String transcript = message.get("transcript").getAsString();
                    boolean endOfTurn = message.get("end_of_turn").getAsBoolean();

                    if (endOfTurn) {
                        System.out.println("Final: " + transcript);
                    } else {
                        System.out.println("Partial: " + transcript);
                    }
                } else if (messageType.equals("Termination")) {
                    System.out.println("Session terminated after "
                        + message.get("audio_duration_seconds").getAsDouble() + " seconds of audio");
                }

                webSocket.request(1);
                return null;
            }
        }).join();

// Pseudocode for getting audio from a microphone
// Send raw PCM16 audio as binary WebSocket frames (50 ms chunks recommended)
getAudio((byte[] chunk) -> {
    ws.sendBinary(ByteBuffer.wrap(chunk), true);
});

// Close connection
ws.sendText("{\"type\": \"Terminate\"}", true);
ws.sendClose(WebSocket.NORMAL_CLOSURE, "Done");

3. Use LLM Gateway to build LLM apps on voice data

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

HttpClient httpClient = HttpClient.newHttpClient();
String apiKey = System.getenv("ASSEMBLYAI_API_KEY");

// Use transcript text from a previous transcription
String transcriptText = "Your transcript text here...";

String requestBody = """
    {
        "model": "claude-sonnet-4-5-20250929",
        "messages": [
            {"role": "user", "content": "Provide a brief summary of the transcript.\\n\\nTranscript: %s"}
        ],
        "max_tokens": 1000
    }
    """.formatted(transcriptText);

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://llm-gateway.assemblyai.com/v1/chat/completions"))
    .header("Authorization", apiKey)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(requestBody))
    .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
JsonObject result = JsonParser.parseString(response.body()).getAsJsonObject();
String content = result.getAsJsonArray("choices")
    .get(0).getAsJsonObject()
    .getAsJsonObject("message")
    .get("content").getAsString();

System.out.println(content);

Learn how to use LLMs with audio data using LLM Gateway in our docs.

4. Use Speech Understanding models

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

HttpClient httpClient = HttpClient.newHttpClient();
String apiKey = System.getenv("ASSEMBLYAI_API_KEY");

// Submit with sentiment_analysis enabled
String requestBody = """
    {
        "audio_url": "https://storage.googleapis.com/aai-docs-samples/nbc.mp3",
        "sentiment_analysis": true
    }
    """;

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.assemblyai.com/v2/transcript"))
    .header("Authorization", apiKey)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(requestBody))
    .build();

HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
JsonObject transcript = JsonParser.parseString(response.body()).getAsJsonObject();
String transcriptId = transcript.get("id").getAsString();

// Poll until completed
JsonObject result;
while (true) {
    HttpRequest pollRequest = HttpRequest.newBuilder()
        .uri(URI.create("https://api.assemblyai.com/v2/transcript/" + transcriptId))
        .header("Authorization", apiKey)
        .GET()
        .build();

    HttpResponse<String> pollResponse = httpClient.send(pollRequest, HttpResponse.BodyHandlers.ofString());
    result = JsonParser.parseString(pollResponse.body()).getAsJsonObject();
    String status = result.get("status").getAsString();

    if (status.equals("completed")) break;
    if (status.equals("error")) {
        System.out.println("Failed");
        return;
    }

    Thread.sleep(3000);
}

// Print sentiment results
JsonArray sentimentResults = result.getAsJsonArray("sentiment_analysis_results");
for (int i = 0; i < sentimentResults.size(); i++) {
    JsonObject item = sentimentResults.get(i).getAsJsonObject();
    System.out.println("Text: " + item.get("text").getAsString());
    System.out.println("Sentiment: " + item.get("sentiment").getAsString()); // POSITIVE, NEUTRAL, or NEGATIVE
    System.out.println("Confidence: " + item.get("confidence").getAsDouble());
    System.out.printf("Timestamp: %d - %d%n", item.get("start").getAsInt(), item.get("end").getAsInt());
}

Learn more about our Speech Understanding models in our docs.

Start Building Voice AI in Java

Transcription, real-time streaming, LLM Gateway, and Speech Understanding all run off the same API key. Get one free and ship your first integration today.

Sign up free

Frequently asked questions

Is the Java Speech API still supported?

No — the Java Speech API (JSAPI) is a legacy specification and is not how speech recognition is done in Java today. It never shipped a maintained reference implementation, and the follow-on JSR has been inactive for years. Modern Java applications call a cloud speech-to-text API over HTTP or WebSocket instead, which is what the code in this guide does with the JDK's built-in HttpClient.

Do I need an SDK to use a speech-to-text API in Java?

No. AssemblyAI's API is plain HTTP and WebSocket, so Java's built-in java.net.http.HttpClient is enough — you POST to https://api.assemblyai.com/v2/transcript with your API key in the Authorization header and read the JSON response. The only external dependency in this guide is a JSON parser (Gson). Skipping the SDK means one less version to track and no wrapper between you and the API surface.

Are transcripts returned immediately, or do I need to poll?

Transcription is asynchronous: the submit request returns a transcript ID right away, and the transcript itself is ready a short time later. The simplest approach is polling the GET /v2/transcript/{id} endpoint until status is completed, which is what the examples here do. In production, use a webhook instead — pass a webhook_url when you submit and AssemblyAI POSTs to your endpoint on completion, so you're not holding threads open in a sleep loop.

How do I transcribe audio in real time in Java?

Open a WebSocket to wss://streaming.assemblyai.com/v3/ws using HttpClient.newWebSocketBuilder(), authenticate with your API key in the header, and send raw PCM16 mono audio at 16kHz as binary frames in roughly 50ms chunks. Your listener receives Begin, Turn, and Termination messages as JSON — each Turn carries the running transcript plus an end_of_turn flag telling you when the speaker finished. Always send a Terminate message before closing, since streaming sessions bill by connection duration.

Is there a free API for speech-to-text?

Most production-grade speech-to-text APIs, including AssemblyAI, offer free credits rather than a permanently free tier — enough to build and test an integration before you pay anything. Fully free options exist as self-hosted open-source models, but you take on the GPU cost, the deployment, and the accuracy gap, which is usually a worse trade than a per-hour API for anything user-facing.

What audio file formats work with a speech-to-text API?

AssemblyAI accepts the common formats directly — MP3, WAV, FLAC, M4A, OGG, and WebM — with a 5GB maximum file size, so there's no transcoding step for most inputs. WAV and FLAC preserve the most audio detail and give the highest accuracy ceiling, while MP3 at 128kbps or above is a reasonable trade when bandwidth matters. For real-time streaming the requirement is stricter: raw PCM16 mono at 16kHz, matching the sample_rate you set on the connection.

Title goes here

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Button Text
No items found.