The official C# library for the Typecast API. Convert text to lifelike speech using AI-powered voices.Supports .NET Standard 2.0+, .NET 6+, Unity (via NuGetForUnity), and Blazor applications. Full async/await support with synchronous alternatives.
Latest registered version: 0.3.7 on NuGet. You can check with dotnet list package. Update with dotnet add package typecast-csharp to get the latest version.
Use RecommendVoicesAsync when you know the desired style but not the exact voice_id.
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}");}
Recommendation results contain only VoiceId, VoiceName, and Score. Use GetVoiceV2Async or GetVoicesV2Async when you need detailed metadata such as supported models, emotions, gender, age, or use cases.
Set your API key via environment variable or constructor:
// Using environment variable (TYPECAST_API_KEY)using var client = new TypecastClient();// Or pass directlyusing var client = new TypecastClient("your-api-key-here");// Or use configuration objectvar config = new TypecastClientConfig{ ApiKey = "your-api-key-here", TimeoutSeconds = 60 // Optional, default: 30};using var client = new TypecastClient(config);
When requests go through your own proxy, set ApiHost 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.
Proxy without API key
var config = new TypecastClientConfig{ ApiHost = "https://your-proxy.example.com"};using var client = new TypecastClient(config);
ssfm-v30 offers two emotion control modes: Preset and Smart.
Smart Mode
Preset Mode
Let the AI infer emotion from context:
var request = new TTSRequest("Everything is going to be okay.", voiceId, TTSModel.SsfmV30){ Language = LanguageCode.English, Prompt = new SmartPrompt( previousText: "I just got the best news!", nextText: "I can't wait to celebrate!" )};var response = await client.TextToSpeechAsync(request);
Explicitly set emotion with preset values:
var request = new TTSRequest("I am so excited to show you these features!", voiceId, TTSModel.SsfmV30){ Language = LanguageCode.English, Prompt = new PresetPrompt( emotionPreset: EmotionPreset.Happy, emotionIntensity: 1.5 // Range: 0.0 to 2.0 )};var response = await client.TextToSpeechAsync(request);
Use GenerateToFileAsync when you want the SDK to synthesize speech and write the audio bytes directly to a local file. The model defaults to SsfmV30, and .mp3 / .wav extensions infer the output format when Output.AudioFormat is not set. Browse available voice IDs on the Voices page.
await client.GenerateToFileAsync("output.mp3", new GenerateToFileRequest{ Text = "Hello from Typecast.", VoiceId = "tc_672c5f5ce59fac2a48faeaee" // Find voice IDs at https://typecast.ai/developers/api/voices});
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.
var audio = await client.ComposeSpeech() .Defaults(new ComposerSettings { VoiceId = "tc_672c5f5ce59fac2a48faeaee", Model = TTSModel.SsfmV30 }) .Say("Hello<|5s|>Nice to meet you<|1s|>Today<|2s|>how does the weather feel?") .GenerateAsync();
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.
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");
The SDK supports 37 languages with automatic language detection:
// Auto-detect language (recommended)var request = new TTSRequest("こんにちは。お元気ですか。", voiceId, TTSModel.SsfmV30);var response = await client.TextToSpeechAsync(request);// Or specify language explicitlyvar koreanRequest = new TTSRequest("안녕하세요. 반갑습니다.", voiceId, TTSModel.SsfmV30){ Language = LanguageCode.Korean // ISO 639-3 language code};await response.SaveToFileAsync("output.wav");
Stream audio chunks in real-time for low-latency playback:
// Stream and extract raw PCM (skip 44-byte WAV header)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..]; // Skip WAV header first = false; } // pcm is raw 16-bit mono PCM at 32000 Hz // Feed to your audio output (e.g. NAudio)}
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.
TextToSpeechWithTimestampsAsync() 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.
using Typecast;using Typecast.Models;using var client = new TypecastClient("YOUR_API_KEY");var request = new TTSRequestWithTimestamps( text: "Hello. How are you?", voiceId: "tc_60e5426de8b95f1d3000d7b5", model: TTSModel.SsfmV30);var result = await client.TextToSpeechWithTimestampsAsync(request);await result.SaveToFileAsync("output.wav");Console.WriteLine($"Duration: {result.AudioDuration}s");foreach (var word in result.Words){ Console.WriteLine($" [{word.StartTime:F3}s – {word.EndTime:F3}s] {word.Text}");}
Set Granularity = Granularity.Word (default) or Granularity = Granularity.Char to control the alignment unit.
// Character-level alignment — required for Japanese / Chinesevar request = new TTSRequestWithTimestamps( text: "Hello. How are you?", voiceId: "tc_60e5426de8b95f1d3000d7b5", model: TTSModel.SsfmV30){ Granularity = Granularity.Char};
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.