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

# PHP

> Access the Typecast API with our official PHP SDK.

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

Built with Guzzle 7 for reliable HTTP communication. Requires PHP 8.1+ and Composer.

<CardGroup cols={2}>
  <Card title="Packagist" icon="cube" href="https://packagist.org/packages/neosapience/typecast-php">
    Typecast PHP SDK
  </Card>

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

## Installation

Install via Composer:

```bash theme={null}
composer require neosapience/typecast-php
```

<Warning>
  Latest registered version: **typecast-php/v0.1.8** in the SDK Git tags. Requires **PHP 8.1 or higher** and Composer. Check your version with `php -v`.
</Warning>

## Quick Start

```php theme={null}
<?php
use Neosapience\Typecast\TypecastClient;
use Neosapience\Typecast\Models\TTSRequest;

// Initialize client
$client = new TypecastClient(apiKey: 'YOUR_API_KEY');

// Convert text to speech
$response = $client->textToSpeech(new TTSRequest(
    voiceId: 'tc_672c5f5ce59fac2a48faeaee',
    text: "Hello there! I'm your friendly text-to-speech agent.",
    model: 'ssfm-v30',
));

// Save audio file
file_put_contents('output.wav', $response->audioData);

echo "Duration: {$response->duration}s, Format: {$response->format}\n";
```

## Features

* **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
* **Streaming**: Real-time chunked audio delivery for low-latency playback via callback
* **Guzzle 7**: Industry-standard HTTP client with automatic retries and connection pooling
* **Type Safety**: Typed properties and named arguments (PHP 8.1+)

## Voice Recommendations

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

```php theme={null}
$voices = $client->recommendVoices(
    'warm female voice for a product tutorial',
    count: 3,
);

foreach ($voices as $voice) {
    echo "{$voice->voiceId} {$voice->voiceName} {$voice->score}\n";
}
```

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 or pass directly:

<CodeGroup>
  ```bash Environment Variable theme={null}
  export TYPECAST_API_KEY="your-api-key-here"
  ```

  ```php From Environment theme={null}
  use Neosapience\Typecast\TypecastClient;

  $client = new TypecastClient(
      apiKey: getenv('TYPECAST_API_KEY'),
  );
  ```

  ```php Direct Configuration theme={null}
  use Neosapience\Typecast\TypecastClient;

  $client = new TypecastClient(
      apiKey: 'your-api-key-here',
  );
  ```
</CodeGroup>

<Info>
  When requests go through your own proxy, set `baseUrl` to the proxy endpoint and omit `apiKey`. 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>

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

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

    ```php theme={null}
    use Neosapience\Typecast\Models\{TTSRequest, SmartPrompt};

    $response = $client->textToSpeech(new TTSRequest(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: 'Everything is going to be okay.',
        model: 'ssfm-v30',
        prompt: new SmartPrompt(
            previousText: 'I just got the best news!',
            nextText: "I can't wait to celebrate!",
        ),
    ));
    ```
  </Tab>

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

    ```php theme={null}
    use Neosapience\Typecast\Models\{TTSRequest, PresetPrompt};

    $response = $client->textToSpeech(new TTSRequest(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: 'I am so excited to show you these features!',
        model: 'ssfm-v30',
        prompt: new PresetPrompt(
            emotionPreset: 'happy',
            emotionIntensity: 1.5,
        ),
    ));
    ```
  </Tab>
</Tabs>

### Audio Customization

Control loudness, pitch, tempo, and output format:

```php theme={null}
use Neosapience\Typecast\Models\{TTSRequest, Output};

$response = $client->textToSpeech(new TTSRequest(
    voiceId: 'tc_672c5f5ce59fac2a48faeaee',
    text: 'Customized audio output!',
    model: 'ssfm-v30',
    output: new Output(
        targetLufs: -14.0,
        audioPitch: 2,
        audioTempo: 1.2,
        audioFormat: 'mp3',
    ),
    seed: 42,
));

file_put_contents('output.mp3', $response->audioData);
```

### 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 no output format is set. Browse available voice IDs on the [Voices](https://typecast.ai/developers/api/voices) page.

```php theme={null}
$client->generateToFile(
    'output.mp3',
    'Hello from Typecast.',
    'tc_672c5f5ce59fac2a48faeaee' // Find voice IDs at https://typecast.ai/developers/api/voices
);
```

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

```php theme={null}
$audio = $client->composeSpeech()
    ->defaults(new ComposerSettings(voiceId: 'tc_672c5f5ce59fac2a48faeaee', model: '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.

```php theme={null}
use Neosapience\Typecast\ComposerSettings;
use Neosapience\Typecast\Models\Output;

$audio = $client->composeSpeech()
    ->defaults(new ComposerSettings(voiceId: 'tc_672c5f5ce59fac2a48faeaee', model: 'ssfm-v30'))
    ->say('Hello there')
    ->pause(5.0)
    ->say('Nice to meet you', new ComposerSettings(
        voiceId: 'tc_60e5426de8b95f1d3000d7b5',
        output: new Output(audioPitch: 2)
    ))
    ->say('Today')
    ->pause(2.0)
    ->say('How does the weather feel?')
    ->generate();

file_put_contents('conversation.wav', $audio->audioData);
```

### Voice Discovery (V2 API)

List and filter available voices with enhanced metadata:

```php theme={null}
use Neosapience\Typecast\Models\VoicesV2Filter;

// Get all voices
$voices = $client->getVoicesV2();

// Filter by criteria
$filtered = $client->getVoicesV2(new VoicesV2Filter(
    model: 'ssfm-v30',
    gender: 'female',
    age: 'young_adult',
));

foreach ($voices as $voice) {
    echo "ID: {$voice->voiceId}, Name: {$voice->voiceName}\n";
    echo "Gender: {$voice->gender}, Age: {$voice->age}\n";
}

// Get a specific voice by ID
$voice = $client->getVoiceV2('tc_672c5f5ce59fac2a48faeaee');
```

### Streaming

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

```php theme={null}
use Neosapience\Typecast\Models\TTSRequestStream;

$first = true;
$client->textToSpeechStream(
    new TTSRequestStream(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: 'Stream this text as audio in real time.',
        model: 'ssfm-v30',
    ),
    function (string $chunk) use (&$first): void {
        if ($first) {
            $chunk = substr($chunk, 44); // Skip 44-byte WAV header
            $first = false;
        }
        // $chunk is raw 16-bit mono PCM at 32000 Hz
        // Feed to your audio output or pipe to ffplay
    },
);
```

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

```php theme={null}
use Neosapience\Typecast\TypecastClient;
use Neosapience\Typecast\Models\TTSRequestWithTimestamps;

$client = new TypecastClient(apiKey: 'YOUR_API_KEY');

$result = $client->textToSpeechWithTimestamps(new TTSRequestWithTimestamps(
    voiceId:  'tc_60e5426de8b95f1d3000d7b5',
    text:     'Hello. How are you?',
    model:    'ssfm-v30',
));

file_put_contents('output.wav', $result->audioData);
echo "Duration: {$result->audioDuration}s\n";

foreach ($result->words as $word) {
    echo "  [{$word->startTime}s – {$word->endTime}s] {$word->text}\n";
}
```

### Granularity

Pass `granularity: 'word'` (default) or `granularity: 'char'` to control the alignment unit.

```php theme={null}
$result = $client->textToSpeechWithTimestamps(new TTSRequestWithTimestamps(
    voiceId:     'tc_60e5426de8b95f1d3000d7b5',
    text:        'Hello. How are you?',
    model:       'ssfm-v30',
    granularity: 'char',  // required for Japanese / Chinese
));
```

### Subtitle Export

```php theme={null}
file_put_contents('output.srt', $result->toSrt());
file_put_contents('output.vtt', $result->toVtt());
```

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

```php theme={null}
<?php
use Neosapience\Typecast\TypecastClient;
use Neosapience\Typecast\Models\TTSRequest;

$client = new TypecastClient(apiKey: 'YOUR_API_KEY');

$voice = $client->cloneVoice(
    audio: file_get_contents('sample.wav'),
    filename: 'sample.wav',
    name: 'My Voice',
    model: 'ssfm-v30',
);

$response = $client->textToSpeech(new TTSRequest(
    voiceId: $voice->voiceId,
    text: 'Hello from my cloned voice!',
    model: 'ssfm-v30',
));

file_put_contents('output.wav', $response->audioData);
$client->deleteVoice($voice->voiceId);
```

<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 throws specific exceptions for each HTTP error:

```php theme={null}
use Neosapience\Typecast\Exceptions\{
    TypecastException,
    UnauthorizedException,
    PaymentRequiredException,
    RateLimitException,
};

try {
    $response = $client->textToSpeech($request);
} catch (UnauthorizedException $e) {
    echo "Invalid API key: {$e->getMessage()}\n";
} catch (PaymentRequiredException $e) {
    echo "Insufficient credits\n";
} catch (RateLimitException $e) {
    echo "Rate limit exceeded - please retry later\n";
} catch (TypecastException $e) {
    echo "Error: {$e->getMessage()}\n";
}
```

| Exception                      | Status Code | Description                |
| ------------------------------ | ----------- | -------------------------- |
| `BadRequestException`          | 400         | Invalid request parameters |
| `UnauthorizedException`        | 401         | Invalid or missing API key |
| `PaymentRequiredException`     | 402         | Insufficient credits       |
| `NotFoundException`            | 404         | Resource not found         |
| `UnprocessableEntityException` | 422         | Validation error           |
| `RateLimitException`           | 429         | Rate limit exceeded        |
| `InternalServerException`      | 500         | Server error               |

## API Reference

### TypecastClient Methods

| Method                                           | Description                                          |
| ------------------------------------------------ | ---------------------------------------------------- |
| `textToSpeech(TTSRequest)`                       | Convert text to speech audio                         |
| `generateToFile(path, text, voiceId)`            | Generate speech and save it directly to a local file |
| `textToSpeechStream(TTSRequestStream, callable)` | Stream audio chunks via callback                     |
| `cloneVoice($audio, filename, name, model)`      | Create a custom voice via instant cloning            |
| `deleteVoice(string $voiceId)`                   | Delete a custom cloned voice                         |
| `getMySubscription()`                            | Get subscription info                                |
| `getVoices(?string $model)`                      | Get available voices (V1)                            |
| `getVoicesV2(?VoicesV2Filter)`                   | Get voices with metadata (V2)                        |
| `getVoiceV2(string $voiceId)`                    | Get a specific voice                                 |
