Access the Typecast API with our official Java SDK.
The official Java library for the Typecast API. Convert text to lifelike speech using AI-powered voices.Compatible with Java 8 and later versions. Works with Maven, Gradle, and manual installation.
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.
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.
Set your API key via environment variable, .env file, or constructor:
// Using environment variable// export TYPECAST_API_KEY="your-api-key-here"TypecastClient client = new TypecastClient();// Or pass directlyTypecastClient client = new TypecastClient("your-api-key-here");// Or with custom base URLTypecastClient client = new TypecastClient("your-api-key-here", "https://custom-api.example.com");
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.
Proxy without API key
TypecastClient client = new TypecastClient(null, "https://your-proxy.example.com");
ssfm-v30 offers two emotion control modes: Preset and Smart.
Smart Mode
Preset Mode
Let the AI infer emotion from context:
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);
Explicitly set emotion with preset values:
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);
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 page.
client.generateToFile("output.mp3", GenerateToFileRequest.builder() .text("Hello from Typecast.") .voiceId("tc_672c5f5ce59fac2a48faeaee") // Find voice IDs at https://typecast.ai/developers/api/voices .build());
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.
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();
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.
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());
Stream audio chunks in real-time for low-latency playback:
import javax.sound.sampled.*;// Set up audio playback: 32000 Hz, 16-bit, mono, little-endianAudioFormat 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();
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.
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.
Pass .granularity(Granularity.WORD) (default) or .granularity(Granularity.CHAR) to control the alignment unit.
TTSRequestWithTimestamps request = TTSRequestWithTimestamps.builder() .voiceId("tc_60e5426de8b95f1d3000d7b5") .text("Hello. How are you?") .model(TTSModel.SSFM_V30) .granularity(Granularity.CHAR) // required for Japanese / Chinese .build();
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.