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

> 공식 PHP SDK로 타입캐스트 API에 접근하세요.

타입캐스트 [API](https://typecast.ai/developers/api)를 위한 공식 PHP 라이브러리입니다. AI 음성을 사용하여 텍스트를 자연스러운 음성으로 변환합니다.

Guzzle 7 기반의 안정적인 HTTP 통신. PHP 8.1+ 및 Composer 필요.

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

  <Card title="소스 코드" icon="github" href="https://github.com/neosapience/typecast-sdk/tree/main/typecast-php">
    타입캐스트 PHP SDK 소스 코드
  </Card>
</CardGroup>

## 설치

Composer로 설치합니다:

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

<Warning>
  최신 등록 버전은 SDK Git 태그 기준 **typecast-php/v0.1.8**입니다. **PHP 8.1 이상** 및 Composer가 필요합니다. `php -v`로 버전을 확인하세요.
</Warning>

## 빠른 시작

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

// 클라이언트 초기화
$client = new TypecastClient(apiKey: 'YOUR_API_KEY');

// 텍스트를 음성으로 변환
$response = $client->textToSpeech(new TTSRequest(
    voiceId: 'tc_672c5f5ce59fac2a48faeaee',
    text: '안녕하세요! 타입캐스트 PHP SDK입니다.',
    model: 'ssfm-v30',
));

// 오디오 파일 저장
file_put_contents('output.wav', $response->audioData);

echo "재생 시간: {$response->duration}초, 포맷: {$response->format}\n";
```

## 기능

* **다중 음성 모델**: `ssfm-v30` (최신) 및 `ssfm-v21` AI 음성 모델 지원
* **다국어 지원**: 영어, 한국어, 스페인어, 일본어, 중국어 등 37개 언어
* **감정 제어**: 프리셋 감정 (normal, happy, sad, angry, whisper, toneup, tonedown) 또는 스마트 문맥 인식 추론
* **오디오 커스터마이징**: 음량 (LUFS -70 to 0), 피치 (-12 to +12 세미톤), 템포 (0.5x to 2.0x), 포맷 (WAV/MP3) 제어
* **보이스 탐색**: V2 Voices API로 모델, 성별, 나이, 용도별 필터링
* **타임스탬프 TTS**: 자막, 가라오케, 립싱크를 위한 단어·문자 단위 정렬 데이터
* **스트리밍**: 저지연 재생을 위한 실시간 청크 오디오 전송 (콜백 기반)
* **Guzzle 7**: 업계 표준 HTTP 클라이언트
* **타입 안전성**: 타입 프로퍼티와 네임드 아규먼트 (PHP 8.1+)

## 보이스 추천

원하는 스타일은 알지만 정확한 `voice_id`를 모를 때 `recommendVoices`를 사용합니다.

```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";
}
```

추천 결과에는 `voiceId`, `voiceName`, `score`만 포함됩니다. 지원 모델, 감정, 성별, 연령대, 사용 사례 같은 상세 메타데이터가 필요하면 `getVoiceV2` 또는 `getVoicesV2`로 추가 조회하세요.

## 설정

환경변수 또는 직접 API 키를 전달할 수 있습니다:

<CodeGroup>
  ```bash 환경변수 theme={null}
  export TYPECAST_API_KEY="your-api-key-here"
  ```

  ```php 환경변수에서 읽기 theme={null}
  use Neosapience\Typecast\TypecastClient;

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

  ```php 직접 전달 theme={null}
  use Neosapience\Typecast\TypecastClient;

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

<Info>
  자체 프록시를 통해 요청하는 경우 `baseUrl`을 프록시 엔드포인트로 설정하고 `apiKey`를 생략할 수 있습니다. API 키가 비어 있거나 없으면 SDK는 `X-API-KEY` 헤더를 보내지 않습니다. 기본 Typecast 호스트로 요청할 때는 API 키가 계속 필요합니다.
</Info>

```php API 키 없는 프록시 theme={null}
$client = new TypecastClient(
    baseUrl: 'https://your-proxy.example.com',
);
```

## 고급 사용법

### 감정 제어 (ssfm-v30)

ssfm-v30은 두 가지 감정 제어 모드를 제공합니다: **프리셋** 및 **스마트**.

<Tabs>
  <Tab title="스마트 모드">
    AI가 문맥에서 감정을 추론합니다:

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

    $response = $client->textToSpeech(new TTSRequest(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: '모든 것이 잘 될 거예요.',
        model: 'ssfm-v30',
        prompt: new SmartPrompt(
            previousText: '방금 최고의 소식을 들었어요!',
            nextText: '축하하고 싶어요!',
        ),
    ));
    ```
  </Tab>

  <Tab title="프리셋 모드">
    프리셋 값으로 감정을 명시적으로 설정합니다:

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

    $response = $client->textToSpeech(new TTSRequest(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: '이 기능들을 보여드리게 되어 정말 기쁩니다!',
        model: 'ssfm-v30',
        prompt: new PresetPrompt(
            emotionPreset: 'happy',
            emotionIntensity: 1.5,
        ),
    ));
    ```
  </Tab>
</Tabs>

### 오디오 커스터마이징

음량, 피치, 템포, 출력 포맷을 제어합니다:

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

$response = $client->textToSpeech(new TTSRequest(
    voiceId: 'tc_672c5f5ce59fac2a48faeaee',
    text: '커스터마이징된 오디오 출력!',
    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);
```

### 파일로 바로 생성하기

`generateToFile`은 음성 합성과 파일 저장을 한 번에 처리합니다. `model`은 기본값으로 `ssfm-v30`을 사용하고, `.mp3` 또는 `.wav` 확장자로 출력 형식을 결정합니다.

```php theme={null}
$client->generateToFile(
    'hello.mp3',
    '안녕하세요, 타입캐스트입니다.',
    'tc_672c5f5ce59fac2a48faeaee' // voice_id는 https://typecast.ai/developers/api/voices 에서 확인하세요.
);
```

### 텍스트만으로 쉼 표현

한 voice로 읽는 문장 안에 쉼만 넣고 싶다면 텍스트에 pause markup을 직접 작성합니다. `<|5s|>`, `<|1s|>`, `<|0.3s|>`, `<|0.34413s|>`처럼 쓰며 값은 초 단위이고 반드시 `s`로 끝납니다. 별도 pause 함수를 호출하지 않아도 텍스트만 보고 쉼 위치를 확인할 수 있습니다.

```php theme={null}
$audio = $client->composeSpeech()
    ->defaults(new ComposerSettings(voiceId: 'tc_672c5f5ce59fac2a48faeaee', model: 'ssfm-v30'))
    ->say('안녕하세요<|5s|>반갑습니다<|1s|>오늘<|2s|>날씨는 어떤 것 같으세요?')
    ->generate();
```

### 다중 화자 합성

한 파일 안에서 서로 다른 voice나 구간별 pitch, tempo, prompt, seed 같은 옵션을 조합해야 할 때 사용합니다. composer는 각 구간을 WAV로 생성하고 앞뒤 무음 PCM 샘플을 trim한 뒤 합성합니다. MP3가 필요하면 먼저 WAV를 생성한 다음 앱 또는 서버 파이프라인에서 변환하세요.

```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);
```

### 보이스 탐색 (V2 API)

향상된 메타데이터와 함께 사용 가능한 보이스를 조회합니다:

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

// 모든 보이스 조회
$voices = $client->getVoicesV2();

// 필터링
$filtered = $client->getVoicesV2(new VoicesV2Filter(
    model: 'ssfm-v30',
    gender: 'female',
    age: 'young_adult',
));

foreach ($voices as $voice) {
    echo "ID: {$voice->voiceId}, 이름: {$voice->voiceName}\n";
}

// 특정 보이스 조회
$voice = $client->getVoiceV2('tc_672c5f5ce59fac2a48faeaee');
```

### 스트리밍

콜백을 통해 실시간으로 오디오 청크를 스트리밍합니다:

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

$first = true;
$client->textToSpeechStream(
    new TTSRequestStream(
        voiceId: 'tc_672c5f5ce59fac2a48faeaee',
        text: '이 텍스트를 실시간으로 오디오로 스트리밍합니다.',
        model: 'ssfm-v30',
    ),
    function (string $chunk) use (&$first): void {
        if ($first) {
            $chunk = substr($chunk, 44); // 44바이트 WAV 헤더 건너뛰기
            $first = false;
        }
        // $chunk는 32000 Hz 16비트 모노 원시 PCM
        // 오디오 출력으로 전달 또는 ffplay로 파이핑
    },
);
```

<Note>
  **WAV 스트리밍 형식:** 32000 Hz, 16비트, 모노 PCM. 첫 번째 청크에 44바이트 WAV 헤더(size = `0xFFFFFFFF`)가 포함되며, 이후 청크는 원시 PCM 데이터만 포함합니다. MP3 형식: 320 kbps, 44100 Hz, 각 청크는 독립적으로 디코딩 가능합니다.
</Note>

## 타임스탬프 TTS

`textToSpeechWithTimestamps()`는 `POST /v1/text-to-speech/with-timestamps`를 래핑하며, 오디오와 함께 단어·문자 단위 정렬 데이터를 반환합니다. 가라오케 하이라이트, 자막 생성, 립싱크 애플리케이션에 활용할 수 있습니다.

### 기본 사용법

```php theme={null}
<?php
require 'vendor/autoload.php';

use Typecast\TypecastClient;
use Typecast\Models\TTSRequestWithTimestamps;

$client = new TypecastClient('YOUR_API_KEY');

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

file_put_contents('output.wav', $result->audioBytes());
printf("재생 시간: %.3f초\n", $result->audioDuration);

foreach ($result->words as $word) {
    printf("  [%.3fs – %.3fs] %s\n", $word->startTime, $word->endTime, $word->text);
}
```

### 정밀도(Granularity) 설정

`'granularity' => 'word'`(기본값) 또는 `'granularity' => 'char'`를 설정해 정렬 단위를 제어합니다.

```php theme={null}
// 문자 단위 정렬 — 일본어·중국어에 필수
$result = $client->textToSpeechWithTimestamps(new TTSRequestWithTimestamps([
    'voice_id'    => 'tc_60e5426de8b95f1d3000d7b5',
    'text'        => 'Hello. How are you?',
    'model'       => 'ssfm-v30',
    'granularity' => 'char',
]));
```

### 자막 내보내기

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

$vtt = $result->toVtt();
file_put_contents('output.vtt', $vtt);
```

<Note>
  **일본어·중국어:** 공백 구분자가 없는 언어(jpn, zho)는 단어 단위 세그먼트가 의미를 갖지 않습니다. 해당 언어에는 `'granularity' => 'char'`를 사용해 문자 단위 정렬 데이터를 얻으세요.
</Note>

## 지원 언어

37개 언어를 지원하며 자동 언어 감지 기능을 제공합니다:

| 코드    | 언어    | 코드    | 언어     | 코드    | 언어     |
| ----- | ----- | ----- | ------ | ----- | ------ |
| `eng` | 영어    | `jpn` | 일본어    | `ukr` | 우크라이나어 |
| `kor` | 한국어   | `ell` | 그리스어   | `ind` | 인도네시아어 |
| `spa` | 스페인어  | `tam` | 타밀어    | `dan` | 덴마크어   |
| `deu` | 독일어   | `tgl` | 타갈로그어  | `swe` | 스웨덴어   |
| `fra` | 프랑스어  | `fin` | 핀란드어   | `msa` | 말레이어   |
| `ita` | 이탈리아어 | `zho` | 중국어    | `ces` | 체코어    |
| `pol` | 폴란드어  | `slk` | 슬로바키아어 | `por` | 포르투갈어  |
| `nld` | 네덜란드어 | `ara` | 아랍어    | `bul` | 불가리아어  |
| `rus` | 러시아어  | `hrv` | 크로아티아어 | `ron` | 루마니아어  |
| `ben` | 벵골어   | `hin` | 힌디어    | `hun` | 헝가리어   |
| `nan` | 민난어   | `nor` | 노르웨이어  | `pan` | 펀자브어   |
| `tha` | 태국어   | `tur` | 터키어    | `vie` | 베트남어   |
| `yue` | 광둥어   |       |        |       |        |

<Info>
  언어를 지정하지 않으면 입력 텍스트에서 자동으로 감지됩니다.
</Info>

## 에러 처리

SDK는 HTTP 에러별 구체적인 예외를 발생시킵니다:

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

try {
    $response = $client->textToSpeech($request);
} catch (UnauthorizedException $e) {
    echo "유효하지 않은 API 키: {$e->getMessage()}\n";
} catch (PaymentRequiredException $e) {
    echo "크레딧 부족\n";
} catch (RateLimitException $e) {
    echo "요청 한도 초과 - 잠시 후 재시도\n";
} catch (TypecastException $e) {
    echo "에러: {$e->getMessage()}\n";
}
```

| 예외                             | 상태 코드 | 설명                 |
| ------------------------------ | ----- | ------------------ |
| `BadRequestException`          | 400   | 잘못된 요청 파라미터        |
| `UnauthorizedException`        | 401   | 유효하지 않거나 누락된 API 키 |
| `PaymentRequiredException`     | 402   | 크레딧 부족             |
| `NotFoundException`            | 404   | 리소스를 찾을 수 없음       |
| `UnprocessableEntityException` | 422   | 유효성 검사 오류          |
| `RateLimitException`           | 429   | 요청 한도 초과           |
| `InternalServerException`      | 500   | 서버 오류              |

## API 레퍼런스

### TypecastClient 메서드

| 메서드                                              | 설명                    |
| ------------------------------------------------ | --------------------- |
| `textToSpeech(TTSRequest)`                       | 텍스트를 음성 오디오로 변환       |
| `generateToFile(path, text, voiceId)`            | 음성을 생성하고 로컬 파일로 바로 저장 |
| `textToSpeechStream(TTSRequestStream, callable)` | 콜백을 통한 오디오 청크 스트리밍    |
| `getMySubscription()`                            | 구독 정보 조회              |
| `getVoices(?string $model)`                      | 사용 가능한 보이스 조회 (V1)    |
| `getVoicesV2(?VoicesV2Filter)`                   | 메타데이터와 함께 보이스 조회 (V2) |
| `getVoiceV2(string $voiceId)`                    | 특정 보이스 조회             |
