> ## Documentation Index
> Fetch the complete documentation index at: https://typecast.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Java

> Access the Typecast API with our official Java SDK.

The official Java library for the [Typecast API](https://typecast.ai). Convert text to lifelike speech using AI-powered voices.

Compatible with Java 8 and later versions. Works with Maven, Gradle, and manual installation.

<CardGroup cols={2}>
  <Card title="Maven Central" icon="cube" href="https://central.sonatype.com/artifact/com.neosapience/typecast-java">
    Typecast Java SDK
  </Card>

  <Card title="Source Code" icon="github" href="https://github.com/neosapience/typecast-sdk/tree/main/typecast-java">
    Typecast Java SDK Source Code
  </Card>
</CardGroup>

## Installation

<Tabs>
  <Tab title="Maven">
    Add the following dependency to your `pom.xml`:

    ```xml theme={null}
    <dependency>
        <groupId>com.neosapience</groupId>
        <artifactId>typecast-java</artifactId>
        <version>1.2.7</version>
    </dependency>
    ```
  </Tab>

  <Tab title="Gradle">
    Add to your `build.gradle`:

    ```groovy theme={null}
    implementation 'com.neosapience:typecast-java:1.2.7'
    ```
  </Tab>

  <Tab title="Manual">
    Clone and install to local Maven repository:

    ```bash theme={null}
    git clone https://github.com/neosapience/typecast-sdk.git
    cd typecast-sdk/typecast-java
    mvn clean install -DskipTests
    ```
  </Tab>
</Tabs>

<Warning>
  Latest registered version: **1.2.7** on Maven Central. Make sure you have **version 1.2.7 or higher** installed. If you have an older version, update your dependency version in `pom.xml` or `build.gradle`.
</Warning>

## Quick Start

```java theme={null}
import com.neosapience.TypecastClient;
import com.neosapience.models.*;

import java.io.FileOutputStream;

public class QuickStart {
    public static void main(String[] args) throws Exception {
        // Initialize client
        TypecastClient client = new TypecastClient("YOUR_API_KEY");

        // Convert text to speech
        TTSRequest request = TTSRequest.builder()
                .voiceId("tc_672c5f5ce59fac2a48faeaee") // Find voice IDs at https://typecast.ai/developers/api/voices
                .text("Hello there! I'm your friendly text-to-speech agent.")
                .model(TTSModel.SSFM_V30)
                .build();

        TTSResponse response = client.textToSpeech(request);

        // Save audio file
        try (FileOutputStream fos = new FileOutputStream("output." + response.getFormat())) {
            fos.write(response.getAudioData());
        }

        System.out.println("Audio saved! Duration: " + response.getDuration() + "s, Format: " + response.getFormat());

        // Clean up
        client.close();
    }
}
```

## Features

The Typecast Java SDK provides powerful features for text-to-speech conversion:

* **Multiple Voice Models**: Support for `ssfm-v30` (latest) and `ssfm-v21` AI voice models
* **Multi-language Support**: 37 languages including English, Korean, Spanish, Japanese, Chinese, and more
* **Emotion Control**: Preset emotions (normal, happy, sad, angry, whisper, toneup, tonedown) or smart context-aware inference
* **Audio Customization**: Control loudness (LUFS -70 to 0), pitch (-12 to +12 semitones), tempo (0.5x to 2.0x), and format (WAV/MP3)
* **Voice Discovery**: V2 Voices API with filtering by model, gender, age, and use cases
* **Instant Voice Cloning**: Upload a WAV/MP3 sample and create a custom voice ID
* **Timestamp TTS**: Word- and character-level alignment data for subtitles, karaoke, and lip-sync
* **Builder Pattern**: Fluent API with builder pattern for easy request construction
* **Comprehensive Error Handling**: Specific exception classes for each error type
* **Streaming**: Real-time chunked audio delivery for low-latency playback

## Voice Recommendations

Use `recommendVoices` when you know the desired style but not the exact `voice_id`.

```java theme={null}
List<RecommendedVoice> voices = client.recommendVoices(
    "warm female voice for a product tutorial",
    3
);

for (RecommendedVoice voice : voices) {
    System.out.println(voice.getVoiceId() + " " + voice.getVoiceName() + " " + voice.getScore());
}
```

Recommendation results contain only `voiceId`, `voiceName`, and `score`. Use `getVoiceV2` or `getVoicesV2` when you need detailed metadata such as supported models, emotions, gender, age, or use cases.

## Configuration

Set your API key via environment variable, `.env` file, or constructor:

```java theme={null}
// Using environment variable
// export TYPECAST_API_KEY="your-api-key-here"
TypecastClient client = new TypecastClient();

// Or pass directly
TypecastClient client = new TypecastClient("your-api-key-here");

// Or with custom base URL
TypecastClient client = new TypecastClient("your-api-key-here", "https://custom-api.example.com");
```

<Info>
  When requests go through your own proxy, pass the proxy base URL and omit the API key by passing `null` or an empty string. The SDK will not send the `X-API-KEY` header for empty or missing keys. Requests to the default Typecast host still require an API key.
</Info>

```java Proxy without API key theme={null}
TypecastClient client = new TypecastClient(null, "https://your-proxy.example.com");
```

### Environment File

Create a `.env` file in your project root:

```bash theme={null}
TYPECAST_API_KEY=your-api-key-here
```

## Advanced Usage

### Emotion Control (ssfm-v30)

ssfm-v30 offers two emotion control modes: **Preset** and **Smart**.

<Tabs>
  <Tab title="Smart Mode">
    Let the AI infer emotion from context:

    ```java theme={null}
    TTSRequest request = TTSRequest.builder()
            .voiceId("tc_672c5f5ce59fac2a48faeaee")
            .text("Everything is going to be okay.")
            .model(TTSModel.SSFM_V30)
            .prompt(SmartPrompt.builder()
                    .previousText("I just got the best news!")  // Optional context
                    .nextText("I can't wait to celebrate!")     // Optional context
                    .build())
            .build();

    TTSResponse response = client.textToSpeech(request);
    ```
  </Tab>

  <Tab title="Preset Mode">
    Explicitly set emotion with preset values:

    ```java theme={null}
    TTSRequest request = TTSRequest.builder()
            .voiceId("tc_672c5f5ce59fac2a48faeaee")
            .text("I am so excited to show you these features!")
            .model(TTSModel.SSFM_V30)
            .prompt(PresetPrompt.builder()
                    .emotionPreset(EmotionPreset.HAPPY)  // normal, happy, sad, angry, whisper, toneup, tonedown
                    .emotionIntensity(1.5)               // Range: 0.0 to 2.0
                    .build())
            .build();

    TTSResponse response = client.textToSpeech(request);
    ```
  </Tab>
</Tabs>

### Audio Customization

Control loudness, pitch, tempo, and output format:

```java theme={null}
TTSRequest request = TTSRequest.builder()
        .voiceId("tc_672c5f5ce59fac2a48faeaee")
        .text("Customized audio output!")
        .model(TTSModel.SSFM_V30)
        .output(Output.builder()
                .targetLufs(-14.0)                 // Range: -70 to 0 (LUFS)
                .audioPitch(2)                  // Range: -12 to +12 semitones
                .audioTempo(1.2)                // Range: 0.5x to 2.0x
                .audioFormat(AudioFormat.MP3)   // Options: WAV, MP3
                .build())
        .seed(42)  // Non-negative seed for reproducible results
        .build();

TTSResponse response = client.textToSpeech(request);

try (FileOutputStream fos = new FileOutputStream("output." + response.getFormat())) {
    fos.write(response.getAudioData());
}
System.out.println("Duration: " + response.getDuration() + "s, Format: " + response.getFormat());
```

### Generate audio to a file

Use `generateToFile` when you want the SDK to synthesize speech and write the audio bytes directly to a local file. The model defaults to `ssfm-v30`, and `.mp3` / `.wav` extensions infer the output format when `Output.audioFormat` is not set. Browse available voice IDs on the [Voices](https://typecast.ai/developers/api/voices) page.

```java theme={null}
client.generateToFile("output.mp3", GenerateToFileRequest.builder()
    .text("Hello from Typecast.")
    .voiceId("tc_672c5f5ce59fac2a48faeaee") // Find voice IDs at https://typecast.ai/developers/api/voices
    .build());
```

### Text pauses

Use text pause markup when you only need silent gaps inside one composed text segment. Put `<|5s|>`, `<|1s|>`, `<|0.3s|>`, or `<|0.34413s|>` directly in the text. The value is interpreted as seconds and must end with `s`. This keeps the pause expression visible in plain text without adding separate pause calls.

```java theme={null}
TTSResponse audio = client.composeSpeech()
    .defaults(new ComposerSettings().voiceId("tc_672c5f5ce59fac2a48faeaee").model(TTSModel.SSFM_V30))
    .say("Hello<|5s|>Nice to meet you<|1s|>Today<|2s|>how does the weather feel?")
    .generate();
```

### Multi-speaker composition

Use the composer chaining API when one output file needs different voices or per-segment options such as pitch, tempo, prompt, or seed. The composer generates each segment as WAV, trims leading/trailing silent PCM samples, and concatenates the result. If you need MP3, generate WAV first and convert it in your app or server pipeline.

```java theme={null}
TypecastClient client = new TypecastClient("YOUR_API_KEY");

TTSResponse audio = client.composeSpeech()
    .defaults(new ComposerSettings().setVoiceId("tc_672c5f5ce59fac2a48faeaee").setModel(TTSModel.SSFM_V30))
    .say("Hello there")
    .pause(5)
    .say("Nice to meet you", new ComposerSettings()
        .setVoiceId("tc_60e5426de8b95f1d3000d7b5")
        .setOutput(Output.builder().volume(null).audioPitch(2).build()))
    .say("Today")
    .pause(2)
    .say("How does the weather feel?")
    .generate();

Files.write(Path.of("conversation.wav"), audio.getAudioData());
```

### Voice Discovery (V2 API)

List and filter available voices with enhanced metadata:

```java theme={null}
// Get all voices
List<VoiceV2Response> voices = client.getVoicesV2();

// Filter by criteria
VoicesV2Filter filter = VoicesV2Filter.builder()
        .model(TTSModel.SSFM_V30)
        .gender(GenderEnum.FEMALE)
        .age(AgeEnum.YOUNG_ADULT)
        .build();

List<VoiceV2Response> filtered = client.getVoicesV2(filter);

// Display voice info
for (VoiceV2Response voice : voices) {
    System.out.println("ID: " + voice.getVoiceId() + ", Name: " + voice.getVoiceName());
    System.out.println("Gender: " + voice.getGender() + ", Age: " + voice.getAge());
    
    for (ModelInfo model : voice.getModels()) {
        System.out.println("Model: " + model.getVersion() + ", Emotions: " + model.getEmotions());
    }
    
    if (voice.getUseCases() != null) {
        System.out.println("Use cases: " + String.join(", ", voice.getUseCases()));
    }
}
```

### Multilingual Content

The SDK supports 37 languages with automatic language detection:

```java theme={null}
// Auto-detect language (recommended)
TTSRequest request = TTSRequest.builder()
        .voiceId("tc_672c5f5ce59fac2a48faeaee")
        .text("こんにちは。お元気ですか。")
        .model(TTSModel.SSFM_V30)
        .build();

TTSResponse response = client.textToSpeech(request);

// Or specify language explicitly
TTSRequest koreanRequest = TTSRequest.builder()
        .voiceId("tc_672c5f5ce59fac2a48faeaee")
        .text("안녕하세요. 반갑습니다.")
        .model(TTSModel.SSFM_V30)
        .language(LanguageCode.KOR)  // ISO 639-3 language code
        .build();

TTSResponse koreanResponse = client.textToSpeech(koreanRequest);

try (FileOutputStream fos = new FileOutputStream("output." + response.getFormat())) {
    fos.write(response.getAudioData());
}
```

### Streaming

Stream audio chunks in real-time for low-latency playback:

```java theme={null}
import javax.sound.sampled.*;

// Set up audio playback: 32000 Hz, 16-bit, mono, little-endian
AudioFormat format = new AudioFormat(32000, 16, 1, true, false);
SourceDataLine line = AudioSystem.getSourceDataLine(format);
line.open(format, 8192);
line.start();

try (InputStream stream = client.textToSpeechStream(request)) {
    byte[] buf = new byte[4096];
    boolean first = true;
    int bytesRead;

    while ((bytesRead = stream.read(buf)) != -1) {
        int offset = 0;
        if (first) {
            offset = 44;           // Skip 44-byte WAV header
            bytesRead -= 44;
            first = false;
        }
        line.write(buf, offset, bytesRead);
    }
}
line.drain();
line.close();
client.close();
```

<Note>
  **WAV streaming format:** 32000 Hz, 16-bit, mono PCM. The first chunk includes a 44-byte WAV header (size = `0xFFFFFFFF`); subsequent chunks are raw PCM only. For MP3: 320 kbps, 44100 Hz, each chunk is independently decodable. Use `com.neosapience.models.OutputStream` to avoid collision with `java.io.OutputStream`.
</Note>

## Timestamp TTS

`textToSpeechWithTimestamps()` wraps `POST /v1/text-to-speech/with-timestamps` and returns the audio together with per-word and per-character alignment data — useful for karaoke highlights, subtitle generation, and lip-sync applications.

### Basic Usage

```java theme={null}
import com.neosapience.TypecastClient;
import com.neosapience.models.*;

import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

TypecastClient client = new TypecastClient("YOUR_API_KEY");

TTSRequestWithTimestamps request = TTSRequestWithTimestamps.builder()
        .voiceId("tc_60e5426de8b95f1d3000d7b5")
        .text("Hello. How are you?")
        .model(TTSModel.SSFM_V30)
        .build();

TTSWithTimestampsResponse result = client.textToSpeechWithTimestamps(request);

Files.write(Paths.get("output.wav"), result.getAudioBytes());
System.out.printf("Duration: %.3fs%n", result.getAudioDuration());

for (WordAlignment word : result.getWords()) {
    System.out.printf("  [%.3fs – %.3fs] %s%n",
        word.getStartTime(), word.getEndTime(), word.getText());
}

client.close();
```

### Granularity

Pass `.granularity(Granularity.WORD)` (default) or `.granularity(Granularity.CHAR)` to control the alignment unit.

```java theme={null}
TTSRequestWithTimestamps request = TTSRequestWithTimestamps.builder()
        .voiceId("tc_60e5426de8b95f1d3000d7b5")
        .text("Hello. How are you?")
        .model(TTSModel.SSFM_V30)
        .granularity(Granularity.CHAR)  // required for Japanese / Chinese
        .build();
```

### Subtitle Export

```java theme={null}
// Export SRT captions
String srt = result.toSrt();
Files.writeString(Paths.get("output.srt"), srt);

// Export WebVTT captions
String vtt = result.toVtt();
Files.writeString(Paths.get("output.vtt"), vtt);
```

<Note>
  **Japanese / Chinese:** Word-level segmentation is not meaningful for languages without whitespace delimiters (jpn, zho). Use `Granularity.CHAR` for these languages to get character-level alignment.
</Note>

## Instant Voice Cloning

Clone a custom voice from a short audio sample, then pass the returned `uc_` voice ID directly to TTS.

```java theme={null}
import com.neosapience.TypecastClient;
import com.neosapience.models.*;
import java.io.File;

TypecastClient client = new TypecastClient("YOUR_API_KEY");

CustomVoice voice = client.cloneVoice(
    new File("sample.wav"),
    "My Voice",
    "ssfm-v30"
);

TTSRequest request = TTSRequest.builder()
    .voiceId(voice.getVoiceId())
    .text("Hello from my cloned voice!")
    .model(TTSModel.SSFM_V30)
    .build();

TTSResponse response = client.textToSpeech(request);
client.deleteVoice(voice.getVoiceId());
client.close();
```

<Warning>
  Voice cloning audio must be **25 MB or smaller**, the audio duration must be **5-150 seconds**, and the custom voice name must be **1-30 characters**.
</Warning>

## Supported Languages

The SDK supports 37 languages with automatic language detection:

| Code  | Language  | Code  | Language  | Code  | Language   |
| ----- | --------- | ----- | --------- | ----- | ---------- |
| `ENG` | English   | `JPN` | Japanese  | `UKR` | Ukrainian  |
| `KOR` | Korean    | `ELL` | Greek     | `IND` | Indonesian |
| `SPA` | Spanish   | `TAM` | Tamil     | `DAN` | Danish     |
| `DEU` | German    | `TGL` | Tagalog   | `SWE` | Swedish    |
| `FRA` | French    | `FIN` | Finnish   | `MSA` | Malay      |
| `ITA` | Italian   | `ZHO` | Chinese   | `CES` | Czech      |
| `POL` | Polish    | `SLK` | Slovak    | `POR` | Portuguese |
| `NLD` | Dutch     | `ARA` | Arabic    | `BUL` | Bulgarian  |
| `RUS` | Russian   | `HRV` | Croatian  | `RON` | Romanian   |
| `BEN` | Bengali   | `HIN` | Hindi     | `HUN` | Hungarian  |
| `NAN` | Hokkien   | `NOR` | Norwegian | `PAN` | Punjabi    |
| `THA` | Thai      | `TUR` | Turkish   | `VIE` | Vietnamese |
| `YUE` | Cantonese |       |           |       |            |

<Info>
  If not specified, the language will be automatically detected from the input text.
</Info>

## Error Handling

The SDK provides specific exception classes for handling API errors:

```java theme={null}
import com.neosapience.TypecastClient;
import com.neosapience.exceptions.*;

try {
    TTSResponse response = client.textToSpeech(request);
} catch (UnauthorizedException e) {
    // 401: Invalid API key
    System.err.println("Invalid API key: " + e.getMessage());
} catch (PaymentRequiredException e) {
    // 402: Insufficient credits
    System.err.println("Insufficient credits: " + e.getMessage());
} catch (ForbiddenException e) {
    // 403: Access denied
    System.err.println("Access denied: " + e.getMessage());
} catch (NotFoundException e) {
    // 404: Resource not found
    System.err.println("Voice not found: " + e.getMessage());
} catch (UnprocessableEntityException e) {
    // 422: Validation error
    System.err.println("Validation error: " + e.getMessage());
} catch (RateLimitException e) {
    // 429: Rate limit exceeded
    System.err.println("Rate limit exceeded - please retry later");
} catch (InternalServerException e) {
    // 500: Server error
    System.err.println("Server error: " + e.getMessage());
} catch (TypecastException e) {
    // Generic error
    System.err.println("API error (" + e.getStatusCode() + "): " + e.getMessage());
}
```

### Exception Hierarchy

| Exception                      | Status Code | Description                |
| ------------------------------ | ----------- | -------------------------- |
| `BadRequestException`          | 400         | Invalid request parameters |
| `UnauthorizedException`        | 401         | Invalid or missing API key |
| `PaymentRequiredException`     | 402         | Insufficient credits       |
| `ForbiddenException`           | 403         | Access denied              |
| `NotFoundException`            | 404         | Resource not found         |
| `UnprocessableEntityException` | 422         | Validation error           |
| `RateLimitException`           | 429         | Rate limit exceeded        |
| `InternalServerException`      | 500         | Server error               |
| `TypecastException`            | \*          | Base exception class       |

## Eclipse IDE Setup

<Steps>
  <Step title="Import Project">
    1. Open Eclipse
    2. Go to `File` → `Import...`
    3. Select `Maven` → `Existing Maven Projects`
    4. Browse to the `typecast-java` directory
    5. Click `Finish`
  </Step>

  <Step title="Add Dependency">
    Add to your project's `pom.xml`:

    ```xml theme={null}
    <dependency>
        <groupId>com.neosapience</groupId>
        <artifactId>typecast-java</artifactId>
        <version>1.2.7</version>
    </dependency>
    ```
  </Step>

  <Step title="Update Project">
    Right-click on your project → `Maven` → `Update Project...`
  </Step>
</Steps>

## IntelliJ IDEA Setup

<Steps>
  <Step title="Import Project">
    1. Open IntelliJ IDEA
    2. Go to `File` → `Open...`
    3. Select the `typecast-java` directory
    4. Select "Open as Project"
  </Step>

  <Step title="Add Dependency">
    IntelliJ will automatically detect the `pom.xml` and import dependencies.

    Or add to your project's `pom.xml`:

    ```xml theme={null}
    <dependency>
        <groupId>com.neosapience</groupId>
        <artifactId>typecast-java</artifactId>
        <version>1.2.7</version>
    </dependency>
    ```
  </Step>

  <Step title="Reload Maven">
    Click the Maven refresh button or right-click `pom.xml` → `Maven` → `Reload Project`
  </Step>
</Steps>

## API Reference

### TypecastClient Methods

| Method                                          | Description                                          |
| ----------------------------------------------- | ---------------------------------------------------- |
| `textToSpeech(TTSRequest)`                      | Convert text to speech audio                         |
| `generateToFile(String, GenerateToFileRequest)` | Generate speech and save it directly to a local file |
| `cloneVoice(byte[], filename, name, model)`     | Create a custom voice via instant cloning            |
| `cloneVoice(File, name, model)`                 | Create a custom voice from a local audio file        |
| `deleteVoice(String voiceId)`                   | Delete a custom cloned voice                         |
| `getVoicesV2()`                                 | Get all available voices                             |
| `getVoicesV2(VoicesV2Filter)`                   | Get filtered voices                                  |
| `getVoiceV2(String voiceId)`                    | Get a specific voice by ID                           |
| `close()`                                       | Release resources                                    |

### TTSRequest Fields

| Field      | Type                                      | Required | Description                                         |
| ---------- | ----------------------------------------- | -------- | --------------------------------------------------- |
| `voiceId`  | `String`                                  | ✓        | Voice ID (format: `tc_*` or `uc_*`)                 |
| `text`     | `String`                                  | ✓        | Text to synthesize (max 5000 chars)                 |
| `model`    | `TTSModel`                                | ✓        | TTS model (`SSFM_V21` or `SSFM_V30`)                |
| `language` | `LanguageCode`                            |          | ISO 639-3 code (auto-detected if omitted)           |
| `prompt`   | `Prompt` / `PresetPrompt` / `SmartPrompt` |          | Emotion settings                                    |
| `output`   | `Output`                                  |          | Audio output settings                               |
| `seed`     | `Integer`                                 |          | Non-negative integer seed for reproducibility (≥ 0) |

### TTSResponse Fields

| Field       | Type     | Description                   |
| ----------- | -------- | ----------------------------- |
| `audioData` | `byte[]` | Generated audio data          |
| `duration`  | `double` | Audio duration in seconds     |
| `format`    | `String` | Audio format (`wav` or `mp3`) |
