> ## 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 Typecast and create your first AI voice.

## 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://typecast.ai/developers) 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>

## Make your first request

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

          ```bash Javascript theme={null}
          npm install @neosapience/typecast-js
          # pnpm add @neosapience/typecast-js
          # yarn add @neosapience/typecast-js
          ```

          ```bash C#/.NET theme={null}
          dotnet add package typecast-csharp
          ```

          ```xml Java (Maven) theme={null}
          <dependency>
              <groupId>com.neosapience</groupId>
              <artifactId>typecast-java</artifactId>
              <version>1.2.3</version>
          </dependency>
          ```

          ```kotlin Kotlin (Gradle) theme={null}
          dependencies {
              implementation("com.neosapience:typecast-kotlin:1.2.3")
          }
          ```

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

          ```bash Go theme={null}
          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 theme={null}
          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 theme={null}
          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# theme={null}
          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 theme={null}
          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 theme={null}
          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 theme={null}
          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:

    * Configure it directly in your application code
    * Set it as a shell environment variable

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

      ```bash Shell (Windows) theme={null}
      # Set for current session
      set TYPECAST_API_KEY=YOUR_API_KEY
      ```
    </CodeGroup>

    <CodeGroup>
      ```python Python theme={null}
      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 theme={null}
      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 theme={null}
      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# theme={null}
      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 theme={null}
      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 theme={null}
    {
        "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, please refer to [Listing all voices](https://typecast.ai/developers/api/voices) in our API Reference.</Info>

## List all voices

To use Typecast effectively, you need access to voice IDs. The `/v2/voices` endpoint provides a complete list of available voices with their unique identifiers, names, supported models, and emotions.

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://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 theme={null}
      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_v2(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}, Model: {model.version.value}, Emotions: {', '.join(model.emotions)}")
      ```

      ```javascript Javascript theme={null}
      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.getVoicesV2({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}, Model: ${model.version}, Emotions: ${model.emotions.join(', ')}`);
        });
      });
      ```

      ```csharp C# theme={null}
      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.GetVoicesV2Async(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}, Model: {model.Version}, Emotions: {string.Join(", ", model.Emotions)}");
          }
      }
      ```

      ```java Java theme={null}
      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<VoiceV2Response> voices = client.getVoicesV2(filter);

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

      client.close();
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Direct API">
    <CodeGroup>
      ```python Python theme={null}
      import requests
      import os

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

      url = "https://api.typecast.ai/v2/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']}, Model: {model['version']}, Emotions: {', '.join(model['emotions'])}")
      else:
          print(f"Error: {response.status_code} - {response.text}")
      ```

      ```javascript Javascript theme={null}
      const apiKey = process.env.TYPECAST_API_KEY || 'YOUR_API_KEY';

      async function getVoices() {
        const url = 'https://api.typecast.ai/v2/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}, Model: ${model.version}, Emotions: ${model.emotions.join(', ')}`);
            });
          });
        } catch (error) {
          console.error('Error fetching voices:', error);
        }
      }

      getVoices();
      ```

      ```java Java theme={null}
      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/v2/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# theme={null}
      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/v2/voices?model=ssfm-v30");

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

      ```bash cURL theme={null}
      curl -X GET "https://api.typecast.ai/v2/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 theme={null}
{
  "voice_id": "tc_672c5f5ce59fac2a48faeaee",
  "voice_name": "Dylan",
  "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"]
}
```

<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 theme={null}
      # 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 theme={null}
      // 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 theme={null}
      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 theme={null}
      # 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 theme={null}
      # 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 theme={null}
  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 theme={null}
  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 theme={null}
  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>
