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

# C#/.NET

> 공식 C# SDK로 타입캐스트 API에 액세스하세요.

[타입캐스트 API](https://typecast.ai)를 위한 공식 C# 라이브러리입니다. AI 기반 음성을 사용하여 텍스트를 생동감 있는 음성으로 변환하세요.

.NET Standard 2.0+, .NET 6+, Unity(NuGetForUnity를 통해), Blazor 애플리케이션을 지원합니다. 동기 대안과 함께 완전한 async/await를 지원합니다.

<CardGroup cols={2}>
  <Card title="패키지" icon="box" href="https://www.nuget.org/packages/typecast-csharp">
    NuGet의 Typecast C# SDK
  </Card>

  <Card title="소스 코드" icon="github" href="https://github.com/neosapience/typecast-sdk/tree/main/typecast-csharp">
    Typecast C# SDK 소스 코드
  </Card>
</CardGroup>

## 사전 요구 사항

### .NET SDK 설치

<Tabs>
  <Tab title="macOS">
    **Homebrew 사용 (권장)**

    ```bash theme={null}
    # .NET 8 SDK 설치
    brew install dotnet@8

    # PATH에 추가
    export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"

    # 설치 확인
    dotnet --version
    ```

    **공식 설치 프로그램 사용**

    [dotnet.microsoft.com/download](https://dotnet.microsoft.com/download)에서 다운로드하고 `.pkg` 설치 프로그램을 실행하세요.
  </Tab>

  <Tab title="Windows">
    **winget 사용**

    ```powershell theme={null}
    winget install Microsoft.DotNet.SDK.8
    dotnet --version
    ```

    **Chocolatey 사용**

    ```powershell theme={null}
    choco install dotnet-sdk
    dotnet --version
    ```

    또는 [dotnet.microsoft.com/download](https://dotnet.microsoft.com/download)에서 다운로드하세요.
  </Tab>

  <Tab title="Linux">
    ```bash theme={null}
    # Ubuntu/Debian
    wget https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    sudo apt-get update
    sudo apt-get install -y dotnet-sdk-8.0

    dotnet --version
    ```
  </Tab>
</Tabs>

## 설치

<Tabs>
  <Tab title=".NET CLI">
    ```bash theme={null}
    dotnet add package typecast-csharp
    ```
  </Tab>

  <Tab title="Package Manager">
    ```powershell theme={null}
    Install-Package typecast-csharp
    ```
  </Tab>

  <Tab title="Unity (NuGetForUnity)">
    1. [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity) 설치:
       * Package Manager 열기 (Window > Package Manager)
       * "+" 클릭 > "Add package from git URL"
       * 입력: `https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity`

    2. NuGet 창 열기 (NuGet > Manage NuGet Packages)

    3. "typecast-csharp" 검색 후 설치
  </Tab>
</Tabs>

<Warning>
  최신 등록 버전은 NuGet 기준 **0.3.7**입니다. `dotnet list package`로 확인할 수 있습니다. `dotnet add package typecast-csharp`로 최신 버전을 가져오세요.
</Warning>

## 빠른 시작

```csharp theme={null}
using Typecast;
using Typecast.Models;

// 클라이언트 초기화
using var client = new TypecastClient("YOUR_API_KEY");

// 텍스트를 음성으로 변환
var request = new TTSRequest(
    text: "안녕하세요! 저는 텍스트 음성 변환 에이전트입니다.",
    voiceId: "tc_672c5f5ce59fac2a48faeaee",
    model: TTSModel.SsfmV30
);

var response = await client.TextToSpeechAsync(request);

// 오디오 파일 저장
await response.SaveToFileAsync("output.wav");
Console.WriteLine($"Audio saved! Duration: {response.Duration}s, Format: {response.Format}");
```

## 기능

Typecast C# SDK는 텍스트 음성 변환을 위한 강력한 기능을 제공합니다:

* **다중 음성 모델**: `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
* **Unity 지원**: NuGetForUnity를 통해 Unity와 호환
* **Blazor 지원**: Blazor Server 및 WebAssembly와 함께 작동
* **타임스탬프 TTS**: 자막, 가라오케, 립싱크를 위한 단어·문자 단위 정렬 데이터
* **스트리밍**: 저지연 재생을 위한 실시간 청크 오디오 전송
* **Async/Sync API**: 동기 대안과 함께 완전한 async/await 지원

## 보이스 추천

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

```csharp theme={null}
var voices = await client.RecommendVoicesAsync(
    "warm female voice for a product tutorial",
    count: 3
);

foreach (var voice in voices)
{
    Console.WriteLine($"{voice.VoiceId} {voice.VoiceName} {voice.Score}");
}
```

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

## 구성

환경 변수 또는 생성자를 통해 API 키를 설정하세요:

```csharp theme={null}
// 환경 변수 사용 (TYPECAST_API_KEY)
using var client = new TypecastClient();

// 또는 직접 전달
using var client = new TypecastClient("your-api-key-here");

// 또는 구성 객체 사용
var config = new TypecastClientConfig
{
    ApiKey = "your-api-key-here",
    TimeoutSeconds = 60  // 선택 사항, 기본값: 30
};
using var client = new TypecastClient(config);
```

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

```csharp API 키 없는 프록시 theme={null}
var config = new TypecastClientConfig
{
    ApiHost = "https://your-proxy.example.com"
};
using var client = new TypecastClient(config);
```

## 고급 사용법

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

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

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

    ```csharp theme={null}
    var request = new TTSRequest("모든 것이 잘 될 거예요.", voiceId, TTSModel.SsfmV30)
    {
        Language = LanguageCode.Korean,
        Prompt = new SmartPrompt(
            previousText: "방금 최고의 소식을 들었어요!",
            nextText: "축하할 수 있어서 너무 기다려져요!"
        )
    };

    var response = await client.TextToSpeechAsync(request);
    ```
  </Tab>

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

    ```csharp theme={null}
    var request = new TTSRequest("이 기능들을 보여드리게 되어 정말 기대됩니다!", voiceId, TTSModel.SsfmV30)
    {
        Language = LanguageCode.Korean,
        Prompt = new PresetPrompt(
            emotionPreset: EmotionPreset.Happy,
            emotionIntensity: 1.5  // 범위: 0.0 ~ 2.0
        )
    };

    var response = await client.TextToSpeechAsync(request);
    ```
  </Tab>
</Tabs>

### 오디오 사용자 정의

라우드니스, 피치, 템포 및 출력 형식을 제어합니다:

```csharp theme={null}
var request = new TTSRequest("사용자 정의 오디오 출력!", voiceId, TTSModel.SsfmV30)
{
    Language = LanguageCode.Korean,
    Output = new Output(
        targetLufs: -14.0,          // 범위: -70 ~ 0 (LUFS)
        audioPitch: 2,            // 범위: -12 to +12 반음
        audioTempo: 1.2,          // 범위: 0.5x to 2.0x
        audioFormat: AudioFormat.Mp3  // 옵션: Wav, Mp3
    ),
    Seed = 42  // 재현 가능한 결과를 위해
};

var response = await client.TextToSpeechAsync(request);
await response.SaveToFileAsync($"output{response.FileExtension}");
Console.WriteLine($"Duration: {response.Duration}s, Format: {response.Format}");
```

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

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

```csharp theme={null}
await client.GenerateToFileAsync("output.mp3", new GenerateToFileRequest
{
    Text = "안녕하세요, 타입캐스트입니다.",
    VoiceId = "tc_672c5f5ce59fac2a48faeaee" // voice_id는 https://typecast.ai/developers/api/voices 에서 확인하세요.
});
```

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

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

```csharp theme={null}
var audio = await client.ComposeSpeech()
    .Defaults(new ComposerSettings { VoiceId = "tc_672c5f5ce59fac2a48faeaee", Model = TTSModel.SsfmV30 })
    .Say("안녕하세요<|5s|>반갑습니다<|1s|>오늘<|2s|>날씨는 어떤 것 같으세요?")
    .GenerateAsync();
```

### 다중 화자 합성

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

```csharp theme={null}
using Typecast;
using Typecast.Models;

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

var audio = await client.ComposeSpeech()
    .Defaults(new ComposerSettings { VoiceId = "tc_672c5f5ce59fac2a48faeaee", Model = TTSModel.SsfmV30 })
    .Say("Hello there")
    .Pause(5)
    .Say("Nice to meet you", new ComposerSettings { VoiceId = "tc_60e5426de8b95f1d3000d7b5", Output = new Output(audioPitch: 2) })
    .Say("Today")
    .Pause(2)
    .Say("How does the weather feel?")
    .GenerateAsync();

await audio.SaveToFileAsync("conversation.wav");
```

### 음성 탐색 (V2 API)

향상된 메타데이터로 사용 가능한 음성을 나열하고 필터링합니다:

```csharp theme={null}
// 모든 음성 가져오기
var voices = await client.GetVoicesV2Async();

// 기준으로 필터링
var filtered = await client.GetVoicesV2Async(new VoicesV2Filter
{
    Model = TTSModel.SsfmV30,
    Gender = GenderEnum.Female,
    Age = AgeEnum.YoungAdult
});

// 음성 정보 표시
foreach (var voice in voices)
{
    Console.WriteLine($"ID: {voice.VoiceId}, Name: {voice.VoiceName}");
    Console.WriteLine($"Gender: {voice.Gender}, Age: {voice.Age}");
    Console.WriteLine($"Models: {string.Join(", ", voice.Models.Select(m => m.Version))}");
    Console.WriteLine($"Use cases: {string.Join(", ", voice.UseCases ?? new List<string>())}");
}
```

### 스트리밍

저지연 재생을 위한 실시간 오디오 청크 스트리밍:

```csharp theme={null}
// 원시 PCM 추출 (44바이트 WAV 헤더 건너뛰기)
using var stream = await client.TextToSpeechStreamAsync(request);

var buffer = new byte[8192];
bool first = true;

while (true)
{
    int bytesRead = await stream.ReadAsync(buffer);
    if (bytesRead == 0) break;

    ReadOnlySpan<byte> pcm = buffer.AsSpan(0, bytesRead);
    if (first)
    {
        pcm = pcm[44..];  // WAV 헤더 건너뛰기
        first = false;
    }
    // pcm은 32000 Hz 16비트 모노 원시 PCM
    // 오디오 출력으로 전달 (예: NAudio)
}
```

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

## 타임스탬프 TTS

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

### 기본 사용법

```csharp theme={null}
using Typecast;
using Typecast.Models;

var client = new TypecastClient("YOUR_API_KEY");

var result = await client.TextToSpeechWithTimestampsAsync(new TTSRequestWithTimestamps {
    VoiceId = "tc_60e5426de8b95f1d3000d7b5",
    Text = "Hello. How are you?",
    Model = "ssfm-v30"
});

await File.WriteAllBytesAsync("output.wav", result.AudioBytes());
Console.WriteLine($"재생 시간: {result.AudioDuration:F3}초");

foreach (var word in result.Words) {
    Console.WriteLine($"  [{word.StartTime:F3}s – {word.EndTime:F3}s] {word.Text}");
}
```

### 정밀도(Granularity) 설정

`Granularity = Granularity.Word`(기본값) 또는 `Granularity = Granularity.Char`를 설정해 정렬 단위를 제어합니다.

```csharp theme={null}
// 문자 단위 정렬 — 일본어·중국어에 필수
var result = await client.TextToSpeechWithTimestampsAsync(new TTSRequestWithTimestamps {
    VoiceId = "tc_60e5426de8b95f1d3000d7b5",
    Text = "Hello. How are you?",
    Model = "ssfm-v30",
    Granularity = Granularity.Char
});
```

### 자막 내보내기

```csharp theme={null}
string srt = result.ToSrt();
await File.WriteAllTextAsync("output.srt", srt);

string vtt = result.ToVtt();
await File.WriteAllTextAsync("output.vtt", vtt);
```

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

## 지원 언어

SDK는 자동 언어 감지와 함께 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는 API 오류 처리를 위한 특정 예외 타입을 제공합니다:

```csharp theme={null}
using Typecast;
using Typecast.Exceptions;

try
{
    var response = await client.TextToSpeechAsync(request);
}
catch (UnauthorizedException)
{
    Console.WriteLine("Invalid or missing API key");
}
catch (PaymentRequiredException)
{
    Console.WriteLine("Insufficient credits");
}
catch (UnprocessableEntityException ex)
{
    Console.WriteLine($"Validation error: {ex.ResponseBody}");
}
catch (RateLimitException)
{
    Console.WriteLine("Rate limit exceeded - please try again later");
}
catch (TypecastException ex)
{
    Console.WriteLine($"API error ({ex.StatusCode}): {ex.Message}");
}
```

## 동기 API

async가 선호되지 않는 시나리오의 경우 동기 메서드를 사용하세요:

```csharp theme={null}
// 동기 텍스트 음성 변환
var response = client.TextToSpeech(request);
response.SaveToFile("output.wav");

// 동기 음성 목록
var voices = client.GetVoicesV2();
var voice = client.GetVoiceV2("voice_id");
```
