> ## 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.

# Quickstart

## Get Started with Authentication
To use the Typecast API, you'll need to authenticate your requests with an API key. Follow these steps:

<Steps>
  <Step title="First Step">
    Visit your [Typecast API Console](https://studio.typecast.ai/developers/api) to generate a new API key
  </Step>
  <Step title="Second Step">
    Keep your API key secure - we recommend storing it as an environment variable
  </Step>
</Steps>

<Note>
Python SDK 0.5.0 supports Python 3.11 through 3.14. **Python 3.8, 3.9, and 3.10 are no longer supported because they have reached end of life (EOL).** The last compatible SDK is **typecast-python 0.3.15** for Python 3.8/3.9 and **0.4.1** for Python 3.10. Upgrade Python first. See [supported versions and migration guidance](/sdk/python).
</Note>

## Make your first request

<Tabs>
  <Tab title="SDK">
    <Steps>
      <Step title="Install SDK">
        <CodeGroup>
        ```bash Python
        pip install --upgrade typecast-python
        ```

        ```bash Javascript
        npm install @neosapience/typecast-js
        # pnpm add @neosapience/typecast-js
        # yarn add @neosapience/typecast-js
        ```

        ```bash C#/.NET
        dotnet add package typecast-csharp
        ```

        ```xml Java (Maven)
        <dependency>
            <groupId>com.neosapience</groupId>
            <artifactId>typecast-java</artifactId>
            <version>1.2.12</version>
        </dependency>
        ```

        ```kotlin Kotlin (Gradle)
        dependencies {
            implementation("com.neosapience:typecast-kotlin:1.2.13")
        }
        ```

        ```toml Rust (Cargo.toml)
        [dependencies]
        typecast-rust = "0.3.15"
        tokio = { version = "1", features = ["full"] }
        ```

        ```bash Go
        go get github.com/neosapience/typecast-sdk/typecast-go
        ```
        </CodeGroup>

        <Warning>
        All SDKs require the latest version.
        - **Python**: If you have an older version, upgrade with `pip install --upgrade typecast-python`
        - **Javascript**: If you have an older version, upgrade with `npm update @neosapience/typecast-js`
        - **C#**: Update with `dotnet add package typecast-csharp`
        - **Java**: Update the version in your `pom.xml` or `build.gradle`
        - **Kotlin**: Update the version in your `build.gradle.kts`
        - **Rust**: Update the version in your `Cargo.toml`
        </Warning>

        <Tip>
        If you only need to synthesize speech and save an audio file, use the SDK's `generateToFile` or `generate_to_file` helper. Each SDK page includes a language-specific example.
        </Tip>
      </Step>
      <Step title="Import and Initialize">
        <CodeGroup>

        ```python Python
        from typecast import Typecast
        from typecast.models import TTSRequest, SmartPrompt

        # Initialize client
        client = Typecast(api_key="YOUR_API_KEY")

        # Convert text to speech
        response = client.text_to_speech(TTSRequest(
            text="Everything is going to be okay.",
            model="ssfm-v30",
            voice_id="tc_672c5f5ce59fac2a48faeaee",
            prompt=SmartPrompt(
                emotion_type="smart",
                previous_text="I just got the best news!",
                next_text="I can't wait to celebrate!"
            )
        ))

        # Save audio file
        with open('typecast.wav', 'wb') as f:
            f.write(response.audio_data)
        ```

        ```javascript Javascript
        import { TypecastClient } from '@neosapience/typecast-js';
        import fs from 'fs';

        // Initialize client
        const client = new TypecastClient({
            apiKey: 'YOUR_API_KEY'
        });

        // Convert text to speech
        const audio = await client.textToSpeech({
            text: "Everything is going to be okay.",
            model: "ssfm-v30",
            voice_id: "tc_672c5f5ce59fac2a48faeaee",
            prompt: {
                emotion_type: "smart",
                previous_text: "I just got the best news!",
                next_text: "I can't wait to celebrate!"
            }
        });

        // Save audio file
        await fs.promises.writeFile('typecast.wav', Buffer.from(audio.audioData));
        ```

        ```csharp C#
        using Typecast;
        using Typecast.Models;

        // Initialize client
        using var client = new TypecastClient("YOUR_API_KEY");

        // Convert text to speech
        var request = new TTSRequest(
            text: "Everything is going to be okay.",
            voiceId: "tc_672c5f5ce59fac2a48faeaee",
            model: TTSModel.SsfmV30
        )
        {
            Prompt = new SmartPrompt(
                previousText: "I just got the best news!",
                nextText: "I can't wait to celebrate!"
            )
        };

        var response = await client.TextToSpeechAsync(request);

        // Save audio file
        await response.SaveToFileAsync("typecast.wav");
        ```

        ```java Java
        import com.neosapience.TypecastClient;
        import com.neosapience.models.*;

        import java.io.FileOutputStream;

        // Initialize client
        TypecastClient client = new TypecastClient("YOUR_API_KEY");

        // Convert text to speech
        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!")
                        .nextText("I can't wait to celebrate!")
                        .build())
                .build();

        TTSResponse response = client.textToSpeech(request);

        // Save audio file
        try (FileOutputStream fos = new FileOutputStream("typecast.wav")) {
            fos.write(response.getAudioData());
        }

        client.close();
        ```

        ```kotlin Kotlin
        import com.neosapience.TypecastClient
        import com.neosapience.models.*
        import java.io.File

        // Initialize client
        val client = TypecastClient.create("YOUR_API_KEY")

        // Convert text to speech
        val 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!")
                .nextText("I can't wait to celebrate!")
                .build())
            .build()

        val response = client.textToSpeech(request)

        // Save audio file
        File("typecast.wav").writeBytes(response.audioData)

        client.close()
        ```

        ```rust Rust
        use typecast_rust::{TypecastClient, TTSRequest, TTSModel, SmartPrompt};
        use std::fs;

        #[tokio::main]
        async fn main() -> Result<(), Box<dyn std::error::Error>> {
            // Initialize client
            let client = TypecastClient::with_api_key("YOUR_API_KEY")?;

            // Convert text to speech
            let request = TTSRequest::new(
                "tc_672c5f5ce59fac2a48faeaee",
                "Everything is going to be okay.",
                TTSModel::SsfmV30,
            )
            .prompt(
                SmartPrompt::new()
                    .previous_text("I just got the best news!")
                    .next_text("I can't wait to celebrate!")
            );

            let response = client.text_to_speech(&request).await?;

            // Save audio file
            fs::write("typecast.wav", &response.audio_data)?;

            Ok(())
        }
        ```

        </CodeGroup>
      </Step>
    </Steps>
  </Tab>
  <Tab title="Direct API">
    You can set up your API key in two ways:
    {/* - Add it to your `.env` file */}
    - Configure it directly in your application code
    - Set it as a shell environment variable

    <CodeGroup>
    ```bash Shell (Linux/macOS)
    # Set for current session
    export TYPECAST_API_KEY='YOUR_API_KEY'
    ```

    ```bash Shell (Windows)
    # Set for current session
    set TYPECAST_API_KEY=YOUR_API_KEY
    ```

    {/* ```bash .env
    TYPECAST_API_KEY = 'YOUR_API_KEY';
    ``` */}
    </CodeGroup>

    <CodeGroup>

    ```python Python
    import requests
    import os

    api_key = os.environ.get("TYPECAST_API_KEY", "YOUR_API_KEY")

    url = "https://api.typecast.ai/v1/text-to-speech"
    headers = {"X-API-KEY": api_key, "Content-Type": "application/json"}
    payload = {
        "text": "Everything is going to be okay.",
        "model": "ssfm-v30",
        "voice_id": "tc_672c5f5ce59fac2a48faeaee",
        "prompt": {
            "emotion_type": "smart",
            "previous_text": "I just got the best news!",
            "next_text": "I can't wait to celebrate!"
        }
    }

    response = requests.post(url, headers=headers, json=payload)

    if response.status_code == 200:
        with open('typecast.wav', 'wb') as f:
            f.write(response.content)
        print("Audio file saved as typecast.wav")
    else:
        print(f"Error: {response.status_code} - {response.text}")
    ```

    ```javascript Javascript
    import fs from "fs";
    const apiKey = process.env.TYPECAST_API_KEY || 'YOUR_API_KEY';

    async function convertTextToSpeech() {
      const url = 'https://api.typecast.ai/v1/text-to-speech';
      const payload = {
        text: "Everything is going to be okay.",
        model: "ssfm-v30",
        voice_id: "tc_672c5f5ce59fac2a48faeaee",
        prompt: {
          emotion_type: "smart",
          previous_text: "I just got the best news!",
          next_text: "I can't wait to celebrate!"
        }
      };

      try {
        const response = await fetch(url, {
          method: 'POST',
          headers: {
            'X-API-KEY': apiKey,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(payload)
        });

        if (!response.ok) {
          throw new Error(`Error: ${response.status} - ${await response.text()}`);
        }

        const audioData = await response.arrayBuffer();
        fs.writeFileSync('typecast.wav', Buffer.from(audioData));
        console.log('Audio file saved as typecast.wav');
      } catch (error) {
        console.error('Error converting text to speech:', error);
      }
    }

    convertTextToSpeech();
    ```

    ```java Java
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;

    String apiKey = System.getenv("TYPECAST_API_KEY");
    if (apiKey == null) apiKey = "YOUR_API_KEY";

    String urlString = "https://api.typecast.ai/v1/text-to-speech";
    String payload = "{" +
        "\"text\": \"Everything is going to be okay.\"," +
        "\"model\": \"ssfm-v30\"," +
        "\"voice_id\": \"tc_672c5f5ce59fac2a48faeaee\"," +
        "\"prompt\": {" +
            "\"emotion_type\": \"smart\"," +
            "\"previous_text\": \"I just got the best news!\"," +
            "\"next_text\": \"I can't wait to celebrate!\"" +
        "}" +
    "}";

    URL url = new URL(urlString);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");
    conn.setRequestProperty("X-API-KEY", apiKey);
    conn.setRequestProperty("Content-Type", "application/json");
    conn.setDoOutput(true);

    try (OutputStream os = conn.getOutputStream()) {
        os.write(payload.getBytes("UTF-8"));
    }

    if (conn.getResponseCode() == 200) {
        try (InputStream is = conn.getInputStream();
             FileOutputStream fos = new FileOutputStream("typecast.wav")) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
        }
        System.out.println("Audio file saved as typecast.wav");
    } else {
        System.out.println("Error: " + conn.getResponseCode());
    }
    ```

    ```csharp C#
    using System.Net.Http.Headers;
    using System.Text;
    using System.Text.Json;

    var apiKey = Environment.GetEnvironmentVariable("TYPECAST_API_KEY") ?? "YOUR_API_KEY";

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("X-API-KEY", apiKey);

    var payload = new
    {
        text = "Everything is going to be okay.",
        model = "ssfm-v30",
        voice_id = "tc_672c5f5ce59fac2a48faeaee",
        prompt = new
        {
            emotion_type = "smart",
            previous_text = "I just got the best news!",
            next_text = "I can't wait to celebrate!"
        }
    };

    var content = new StringContent(
        JsonSerializer.Serialize(payload),
        Encoding.UTF8,
        "application/json"
    );

    var response = await client.PostAsync("https://api.typecast.ai/v1/text-to-speech", content);

    if (response.IsSuccessStatusCode)
    {
        var audioData = await response.Content.ReadAsByteArrayAsync();
        await File.WriteAllBytesAsync("typecast.wav", audioData);
        Console.WriteLine("Audio file saved as typecast.wav");
    }
    else
    {
        Console.WriteLine($"Error: {response.StatusCode}");
    }
    ```

    ```bash cURL
    curl -X POST "https://api.typecast.ai/v1/text-to-speech" \
         -H "X-API-KEY: YOUR_API_KEY" \
         -H "Content-Type: application/json" \
         -d '{
             "model": "ssfm-v30",
             "text": "Everything is going to be okay.",
             "voice_id": "tc_672c5f5ce59fac2a48faeaee",
             "prompt": {
                 "emotion_type": "smart",
                 "previous_text": "I just got the best news!",
                 "next_text": "I can't wait to celebrate!"
             }
         }' --output typecast.wav
    ```

    </CodeGroup>

    ### Audio Output Settings

    You can customize the audio output by adding an `output` object to your request:

    | Parameter | Type | Range | Default | Description |
    |-----------|------|-------|---------|-------------|
    | `volume` | integer | 0–200 | 100 | Relative volume scaling. Cannot be used with `target_lufs`. |
    | `target_lufs` | number | -70–0 | - | Absolute loudness normalization in LUFS. Cannot be used with `volume`. |
    | `audio_pitch` | integer | -12–12 | 0 | Pitch adjustment in semitones. |
    | `audio_tempo` | number | 0.5–2.0 | 1.0 | Speed multiplier. |
    | `audio_format` | string | wav, mp3 | wav | Output audio format. |

    <Tip>Use `target_lufs` for consistent loudness across different clips. Use `volume` for simple relative scaling.</Tip>

    ```json Example: output with target_lufs
    {
        "text": "Consistent loudness example.",
        "model": "ssfm-v30",
        "voice_id": "tc_672c5f5ce59fac2a48faeaee",
        "output": {
            "target_lufs": -14.0,
            "audio_format": "mp3"
        }
    }
    ```
  </Tab>
</Tabs>

<Info>To browse and select available voice IDs for your requests, refer to [List Voices](/docs/api-reference/voices/list-voices) in the API Reference.</Info>

## List all voices
To use Typecast effectively, you need access to voice IDs. The current `/v3/voices` endpoint provides available voices with localized names, supported models, emotions, and preview metadata.

You can filter voices by model, gender, age, and use cases using optional query parameters.

<Info>You can preview available API voices and listen to sample audio without making an API call on the [Voices](https://studio.typecast.ai/developers/api/voices) page. Use it to compare voices first, then copy the Voice ID into your API request.</Info>

<Tabs>
  <Tab title="SDK">
    <CodeGroup>
    ```python Python
    from typecast import Typecast
    from typecast.models import VoicesV2Filter, TTSModel

    # Initialize client
    client = Typecast(api_key="YOUR_API_KEY")

    # Get all voices (optionally filter by model, gender, age, use_cases)
    voices = client.voices_v3(VoicesV2Filter(model=TTSModel.SSFM_V30))

    print(f"Found {len(voices)} voices:")
    for voice in voices:
        for model in voice.models:
            print(f"ID: {voice.voice_id}, Name: {voice.voice_name.eng}, Model: {model.version.value}, Emotions: {', '.join(model.emotions)}")
    ```

    ```javascript Javascript
    import { TypecastClient } from '@neosapience/typecast-js';

    // Initialize client
    const client = new TypecastClient({
        apiKey: 'YOUR_API_KEY'
    });

    // Get all voices (optionally filter by model, gender, age, use_cases)
    const voices = await client.getVoicesV3({model: 'ssfm-v30'});

    console.log(`Found ${voices.length} voices:`);
    voices.forEach(voice => {
      voice.models.forEach(model => {
        console.log(`ID: ${voice.voice_id}, Name: ${voice.voice_name.eng}, Model: ${model.version}, Emotions: ${model.emotions.join(', ')}`);
      });
    });
    ```

    ```csharp C#
    using Typecast;
    using Typecast.Models;

    // Initialize client
    using var client = new TypecastClient("YOUR_API_KEY");

    // Get all voices (optionally filter by model, gender, age, use_cases)
    var filter = new VoicesV2Filter { Model = TTSModel.SsfmV30 };
    var voices = await client.GetVoicesV3Async(filter);

    Console.WriteLine($"Found {voices.Count} voices:");
    foreach (var voice in voices)
    {
        foreach (var model in voice.Models)
        {
            Console.WriteLine($"ID: {voice.VoiceId}, Name: {voice.VoiceName.Eng}, Model: {model.Version}, Emotions: {string.Join(", ", model.Emotions)}");
        }
    }
    ```

    ```java Java
    import com.neosapience.TypecastClient;
    import com.neosapience.models.*;

    // Initialize client
    TypecastClient client = new TypecastClient("YOUR_API_KEY");

    // Get all voices (optionally filter by model, gender, age, use_cases)
    VoicesV2Filter filter = VoicesV2Filter.builder()
            .model(TTSModel.SSFM_V30)
            .build();

    List<VoiceV3Response> voices = client.getVoicesV3(filter);

    System.out.println("Found " + voices.size() + " voices:");
    for (VoiceV3Response voice : voices) {
        for (ModelInfo model : voice.getModels()) {
            System.out.println("ID: " + voice.getVoiceId() + ", Name: " + voice.getVoiceName().eng +
                    ", Model: " + model.getVersion() + ", Emotions: " + String.join(", ", model.getEmotions()));
        }
    }

    client.close();
    ```

    </CodeGroup>
  </Tab>
  <Tab title="Direct API">
    <CodeGroup>
    ```python Python
    import requests
    import os

    api_key = os.environ.get("TYPECAST_API_KEY", "YOUR_API_KEY")

    url = "https://api.typecast.ai/v3/voices"
    headers = {"X-API-KEY": api_key}
    params = {"model": "ssfm-v30"}  # Optional: model, gender, age, use_cases

    response = requests.get(url, headers=headers, params=params)

    if response.status_code == 200:
        voices = response.json()
        print(f"Found {len(voices)} voices:")
        for voice in voices:
            for model in voice['models']:
                print(f"ID: {voice['voice_id']}, Name: {voice['voice_name']['eng']}, Model: {model['version']}, Emotions: {', '.join(model['emotions'])}")
    else:
        print(f"Error: {response.status_code} - {response.text}")
    ```

    ```javascript Javascript
    const apiKey = process.env.TYPECAST_API_KEY || 'YOUR_API_KEY';

    async function getVoices() {
      const url = 'https://api.typecast.ai/v3/voices';
      const params = new URLSearchParams({model: 'ssfm-v30'});  // Optional: model, gender, age, use_cases

      try {
        const response = await fetch(`${url}?${params}`, {
          method: 'GET',
          headers: {'X-API-KEY': apiKey}
        });

        if (!response.ok) {
          throw new Error(`Error: ${response.status} - ${await response.text()}`);
        }

        const voices = await response.json();
        console.log(`Found ${voices.length} voices:`);
        voices.forEach(voice => {
          voice.models.forEach(model => {
            console.log(`ID: ${voice.voice_id}, Name: ${voice.voice_name.eng}, Model: ${model.version}, Emotions: ${model.emotions.join(', ')}`);
          });
        });
      } catch (error) {
        console.error('Error fetching voices:', error);
      }
    }

    getVoices();
    ```

    ```java Java
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;

    String apiKey = System.getenv("TYPECAST_API_KEY");
    if (apiKey == null) apiKey = "YOUR_API_KEY";

    String urlString = "https://api.typecast.ai/v3/voices?model=ssfm-v30";

    URL url = new URL(urlString);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("X-API-KEY", apiKey);

    if (conn.getResponseCode() == 200) {
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(conn.getInputStream(), "UTF-8"))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                response.append(line);
            }
            System.out.println(response.toString());
        }
    } else {
        System.out.println("Error: " + conn.getResponseCode());
    }
    ```

    ```csharp C#
    var apiKey = Environment.GetEnvironmentVariable("TYPECAST_API_KEY") ?? "YOUR_API_KEY";

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("X-API-KEY", apiKey);

    var response = await client.GetAsync("https://api.typecast.ai/v3/voices?model=ssfm-v30");

    if (response.IsSuccessStatusCode)
    {
        var json = await response.Content.ReadAsStringAsync();
        Console.WriteLine(json);
    }
    else
    {
        Console.WriteLine($"Error: {response.StatusCode}");
    }
    ```

    ```bash cURL
    curl -X GET "https://api.typecast.ai/v3/voices?model=ssfm-v30" \
         -H "X-API-KEY: YOUR_API_KEY"
    ```
    </CodeGroup>
  </Tab>
</Tabs>

The response will be a JSON array of voice objects, each containing:

```json
{
  "voice_id": "tc_672c5f5ce59fac2a48faeaee",
  "voice_name": {"eng": "Dylan", "kor": "딜런"},
  "models": [
    {
      "version": "ssfm-v30",
      "emotions": ["normal", "happy", "sad", "angry", "whisper", "toneup", "tonedown"]
    }
  ],
  "gender": "male",
  "age": "young_adult",
  "use_cases": ["Conversational", "TikTok/Reels/Shorts", "Audiobook/Storytelling"],
  "voice_type": "original",
  "preview_url": "https://..."
}
```

<Info>
You'll need a valid voice ID when making text-to-speech requests. With ssfm-v30, all 7 emotion presets are available across all voices.
</Info>


## Stream audio in real time

For low-latency applications, use the streaming endpoint to play audio as chunks arrive - no need to wait for full synthesis.

**WAV streaming format:** 32000 Hz, 16-bit, mono PCM. The first chunk includes a 44-byte WAV header; subsequent chunks are raw PCM only.

<Tabs>
  <Tab title="SDK">
    <CodeGroup>

    ```python Python
    # pip install typecast-python sounddevice
    import sounddevice as sd
    from typecast import Typecast
    from typecast.models import TTSRequestStream, OutputStream

    client = Typecast(api_key="YOUR_API_KEY")

    request = TTSRequestStream(
        text="Stream this text as audio in real time.",
        model="ssfm-v30",
        voice_id="tc_672c5f5ce59fac2a48faeaee",
        output=OutputStream(audio_format="wav", target_lufs=-14.0)
    )

    with sd.RawOutputStream(samplerate=32000, channels=1, dtype="int16") as player:
        buf, first = bytearray(), True
        for chunk in client.text_to_speech_stream(request):
            if first:
                chunk = chunk[44:]  # Skip 44-byte WAV header
                first = False
            buf.extend(chunk)
            n = len(buf) - (len(buf) % 2)  # int16 alignment
            if n:
                player.write(bytes(buf[:n]))
                del buf[:n]
    ```

    ```javascript Javascript
    // Node 18+. Pipe stream to ffplay for real-time playback.
    // Prerequisite: ffmpeg (brew/choco/apt install ffmpeg)
    import { spawn } from "node:child_process";
    import { TypecastClient } from '@neosapience/typecast-js';

    const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });

    const ffplay = spawn(
        "ffplay",
        ["-autoexit", "-nodisp", "-loglevel", "error", "-i", "pipe:0"],
        { stdio: ["pipe", "ignore", "ignore"] },
    );

    const stream = await client.textToSpeechStream({
        text: "Stream this text as audio in real time.",
        model: "ssfm-v30",
        voice_id: "tc_672c5f5ce59fac2a48faeaee",
        output: { audio_format: "wav", target_lufs: -14.0 }
    });

    const reader = stream.getReader();
    while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        ffplay.stdin.write(value);
    }
    ffplay.stdin.end();
    await new Promise((resolve) => ffplay.on("close", resolve));
    ```

    ```java Java
    import com.neosapience.TypecastClient;
    import com.neosapience.models.*;
    import javax.sound.sampled.*;
    import java.io.*;

    TypecastClient client = new TypecastClient("YOUR_API_KEY");

    TTSRequestStream request = TTSRequestStream.builder()
            .voiceId("tc_672c5f5ce59fac2a48faeaee")
            .text("Stream this text as audio in real time.")
            .model(TTSModel.SSFM_V30)
            .output(com.neosapience.models.OutputStream.builder()
                    .audioFormat(AudioFormat.WAV)
                    .targetLufs(-14.0).build())
            .build();

    // 32000 Hz, 16-bit, mono, signed, little-endian
    javax.sound.sampled.AudioFormat format =
        new javax.sound.sampled.AudioFormat(32000, 16, 1, true, false);
    SourceDataLine line = javax.sound.sampled.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; bytesRead -= 44; first = false; }
            line.write(buf, offset, bytesRead);
        }
    }
    line.drain();
    line.close();
    client.close();
    ```

    </CodeGroup>

    <Info>See each [SDK documentation](/sdk/python) for more languages (Go, Rust, Swift, C#, Kotlin, C) with real-time playback examples.</Info>
  </Tab>
  <Tab title="Direct API">
    <CodeGroup>

    ```python Python
    # pip install requests sounddevice
    import requests
    import sounddevice as sd
    import os

    api_key = os.environ.get("TYPECAST_API_KEY", "YOUR_API_KEY")

    response = requests.post(
        "https://api.typecast.ai/v1/text-to-speech/stream",
        headers={"X-API-KEY": api_key, "Content-Type": "application/json"},
        json={
            "text": "Stream this text as audio in real time.",
            "model": "ssfm-v30",
            "voice_id": "tc_672c5f5ce59fac2a48faeaee",
            "output": {"audio_format": "wav", "target_lufs": -14.0},
        },
        stream=True
    )
    response.raise_for_status()

    with sd.RawOutputStream(samplerate=32000, channels=1, dtype="int16") as player:
        buf, first = bytearray(), True
        for chunk in response.iter_content(chunk_size=4096):
            if not chunk:
                continue
            if first:
                chunk = chunk[44:]  # Skip WAV header
                first = False
            buf.extend(chunk)
            n = len(buf) - (len(buf) % 2)
            if n:
                player.write(bytes(buf[:n]))
                del buf[:n]
    ```

    ```bash cURL + ffplay
    # Pipe directly to ffplay for instant playback
    curl -s -X POST "https://api.typecast.ai/v1/text-to-speech/stream" \
         -H "X-API-KEY: YOUR_API_KEY" \
         -H "Content-Type: application/json" \
         -d '{
             "model": "ssfm-v30",
             "text": "Stream this text as audio in real time.",
             "voice_id": "tc_672c5f5ce59fac2a48faeaee",
             "output": {"audio_format": "wav", "target_lufs": -14.0}
         }' | ffplay -autoexit -nodisp -loglevel error -i pipe:0
    ```

    </CodeGroup>

    | Parameter | Type | Range | Default | Description |
    |-----------|------|-------|---------|-------------|
    | `audio_pitch` | integer | -12–12 | 0 | Pitch adjustment in semitones. |
    | `audio_tempo` | number | 0.5–2.0 | 1.0 | Speed multiplier. |
    | `audio_format` | string | wav, mp3 | wav | Output audio format. |
    | `target_lufs` | number | -70–0 | - | Absolute loudness normalization in LUFS. |

    <Tip>Use `target_lufs` to keep streaming audio loudness consistent across clips. `volume` is not supported in streaming mode.</Tip>
  </Tab>
</Tabs>

## Generate subtitles with Timestamp TTS

Need word-level timing for captions, karaoke, or lip-sync? Use the timestamp TTS endpoint - it returns the audio together with per-word (and optionally per-character) alignment data.

<CodeGroup>

```python Python
from typecast import Typecast
from typecast.models import TTSRequestWithTimestamps

client = Typecast(api_key="YOUR_API_KEY")
result = client.text_to_speech_with_timestamps(TTSRequestWithTimestamps(
    text="Hello. How are you?",
    model="ssfm-v30",
    voice_id="tc_60e5426de8b95f1d3000d7b5",
))

with open("output.wav", "wb") as f:
    f.write(result.audio_bytes())

# Export SRT captions
with open("output.srt", "w") as f:
    f.write(result.to_srt())
```

```javascript Javascript
import { TypecastClient } from '@neosapience/typecast-js';
import fs from 'fs';

const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
const result = await client.textToSpeechWithTimestamps({
    text: "Hello. How are you?",
    model: "ssfm-v30",
    voice_id: "tc_60e5426de8b95f1d3000d7b5",
});

await fs.promises.writeFile("output.wav", result.audioBytes());
await fs.promises.writeFile("output.srt", result.toSrt(), "utf-8");
```

```bash cURL
curl -X POST "https://api.typecast.ai/v1/text-to-speech/with-timestamps" \
     -H "X-API-KEY: YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{
         "model": "ssfm-v30",
         "text": "Hello. How are you?",
         "voice_id": "tc_60e5426de8b95f1d3000d7b5"
     }'
```

</CodeGroup>

<Info>See each [SDK documentation](/sdk/python) for all 11 language examples including subtitle export helpers (`toSrt()`, `toVtt()`).</Info>

## Next steps
Congratulations on creating your first AI voice! Here are some resources to help you dive deeper:

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference">
    Learn how to use the Typecast API
  </Card>
  <Card title="Models" icon="microchip" href="/models">
    Learn about ssfm-v30 and ssfm-v21 models
  </Card>
  <Card title="Changelog" icon="clock-rotate-left" href="/changelog">
    See the latest API changes and updates
  </Card>
</CardGroup>
