타입캐스트 API를 위한 공식 C# 라이브러리입니다. AI 기반 음성을 사용하여 텍스트를 생동감 있는 음성으로 변환하세요.
.NET Standard 2.0+, .NET 6+, Unity(NuGetForUnity를 통해), Blazor 애플리케이션을 지원합니다. 동기 대안과 함께 완전한 async/await를 지원합니다.
사전 요구 사항
.NET SDK 설치
Homebrew 사용 (권장)
# .NET 8 SDK 설치
brew install dotnet@8
# PATH에 추가
export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"
# 설치 확인
dotnet --version
공식 설치 프로그램 사용
dotnet.microsoft.com/download에서 다운로드하고 .pkg 설치 프로그램을 실행하세요.
설치
dotnet add package typecast-csharp
빠른 시작
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(quot;Audio saved! Duration: {response.Duration}s, Format: {response.Format}");
기능
Typecast C# SDK는 텍스트 음성 변환을 위한 강력한 기능을 제공합니다:
- 다중 음성 모델:
ssfm-v30(최신) 및ssfm-v21AI 음성 모델 지원 - 다국어 지원: 영어, 한국어, 스페인어, 일본어, 중국어 등 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를 사용합니다.
var voices = await client.RecommendVoicesAsync(
"warm female voice for a product tutorial",
count: 3
);
foreach (var voice in voices)
{
Console.WriteLine(quot;{voice.VoiceId} {voice.VoiceName} {voice.Score}");
}
추천 결과에는 VoiceId, VoiceName, Score만 포함됩니다. 지원 모델, 감정, 성별, 연령대, 사용 사례 같은 상세 메타데이터가 필요하면 GetVoiceV2Async 또는 GetVoicesV2Async로 추가 조회하세요.
구성
환경 변수 또는 생성자를 통해 API 키를 설정하세요:
// 환경 변수 사용 (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);
var config = new TypecastClientConfig
{
ApiHost = "https://your-proxy.example.com"
};
using var client = new TypecastClient(config);
고급 사용법
감정 제어 (ssfm-v30)
ssfm-v30은 두 가지 감정 제어 모드를 제공합니다: 프리셋 및 스마트.
AI가 문맥에서 감정을 추론하도록 합니다:
var request = new TTSRequest("모든 것이 잘 될 거예요.", voiceId, TTSModel.SsfmV30)
{
Language = LanguageCode.Korean,
Prompt = new SmartPrompt(
previousText: "방금 최고의 소식을 들었어요!",
nextText: "축하할 수 있어서 너무 기다려져요!"
)
};
var response = await client.TextToSpeechAsync(request);
오디오 사용자 정의
라우드니스, 피치, 템포 및 출력 형식을 제어합니다:
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(quot;output{response.FileExtension}");
Console.WriteLine(quot;Duration: {response.Duration}s, Format: {response.Format}");
파일로 바로 생성하기
GenerateToFileAsync는 음성 합성과 파일 저장을 한 번에 처리합니다. Model은 기본값으로 ssfm-v30을 사용하고, .mp3 또는 .wav 확장자로 출력 형식을 결정합니다.
await client.GenerateToFileAsync("output.mp3", new GenerateToFileRequest
{
Text = "안녕하세요, 타입캐스트입니다.",
VoiceId = "tc_672c5f5ce59fac2a48faeaee" // voice_id는 https://studio.typecast.ai/developers/api/voices 에서 확인하세요.
});
텍스트만으로 쉼 표현
한 voice로 읽는 문장 안에 쉼만 넣고 싶다면 텍스트에 pause markup을 직접 작성합니다. <|5s|>, <|1s|>, <|0.3s|>, <|0.34413s|>처럼 쓰며 값은 초 단위이고 반드시 s로 끝납니다. 별도 pause 함수를 호출하지 않아도 텍스트만 보고 쉼 위치를 확인할 수 있습니다.
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를 생성한 다음 앱 또는 서버 파이프라인에서 변환하세요.
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)
향상된 메타데이터로 사용 가능한 음성을 나열하고 필터링합니다:
// 모든 음성 가져오기
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(quot;ID: {voice.VoiceId}, Name: {voice.VoiceName}");
Console.WriteLine(quot;Gender: {voice.Gender}, Age: {voice.Age}");
Console.WriteLine(quot;Models: {string.Join(", ", voice.Models.Select(m => m.Version))}");
Console.WriteLine(quot;Use cases: {string.Join(", ", voice.UseCases ?? new List<string>())}");
}
스트리밍
저지연 재생을 위한 실시간 오디오 청크 스트리밍:
// 원시 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)
}
타임스탬프 TTS
TextToSpeechWithTimestampsAsync()는 POST /v1/text-to-speech/with-timestamps를 래핑하며, 오디오와 함께 단어·문자 단위 정렬 데이터를 반환합니다. 가라오케 하이라이트, 자막 생성, 립싱크 애플리케이션에 활용할 수 있습니다.
기본 사용법
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(quot;재생 시간: {result.AudioDuration:F3}초");
foreach (var word in result.Words) {
Console.WriteLine(quot; [{word.StartTime:F3}s – {word.EndTime:F3}s] {word.Text}");
}
정밀도(Granularity) 설정
Granularity = Granularity.Word(기본값) 또는 Granularity = Granularity.Char를 설정해 정렬 단위를 제어합니다.
// 문자 단위 정렬 - 일본어·중국어에 필수
var result = await client.TextToSpeechWithTimestampsAsync(new TTSRequestWithTimestamps {
VoiceId = "tc_60e5426de8b95f1d3000d7b5",
Text = "Hello. How are you?",
Model = "ssfm-v30",
Granularity = Granularity.Char
});
자막 내보내기
string srt = result.ToSrt();
await File.WriteAllTextAsync("output.srt", srt);
string vtt = result.ToVtt();
await File.WriteAllTextAsync("output.vtt", vtt);
지원 언어
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 | 광둥어 |
오류 처리
SDK는 API 오류 처리를 위한 특정 예외 타입을 제공합니다:
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(quot;Validation error: {ex.ResponseBody}");
}
catch (RateLimitException)
{
Console.WriteLine("Rate limit exceeded - please try again later");
}
catch (TypecastException ex)
{
Console.WriteLine(quot;API error ({ex.StatusCode}): {ex.Message}");
}
동기 API
async가 선호되지 않는 시나리오의 경우 동기 메서드를 사용하세요:
// 동기 텍스트 음성 변환
var response = client.TextToSpeech(request);
response.SaveToFile("output.wav");
// 동기 음성 목록
var voices = client.GetVoicesV2();
var voice = client.GetVoiceV2("voice_id");