typecast-csharp
0.3.5
See the version list below for details.
dotnet add package typecast-csharp --version 0.3.5
NuGet\Install-Package typecast-csharp -Version 0.3.5
<PackageReference Include="typecast-csharp" Version="0.3.5" />
<PackageVersion Include="typecast-csharp" Version="0.3.5" />
<PackageReference Include="typecast-csharp" />
paket add typecast-csharp --version 0.3.5
#r "nuget: typecast-csharp, 0.3.5"
#:package typecast-csharp@0.3.5
#addin nuget:?package=typecast-csharp&version=0.3.5
#tool nuget:?package=typecast-csharp&version=0.3.5
Typecast C# SDK
Official C# SDK for the Typecast Text-to-Speech API. This SDK supports .NET Standard 2.0+, .NET 6+, Unity (via NuGetForUnity), and Blazor applications.
Features
- Full support for Typecast TTS API v1 and v2
- Both synchronous and asynchronous methods
- Multiple TTS models (ssfm-v21, ssfm-v30)
- Emotion control (preset and smart modes)
- Audio customization (volume, pitch, tempo, format)
- Timestamp TTS: word and character alignment for SRT/WebVTT subtitle generation
- Voice discovery and filtering
- Unity and Blazor compatible
- Zero external dependencies for core functionality
Prerequisites
Installing .NET SDK
This SDK requires .NET 6.0 or later. Follow the instructions below for your operating system.
macOS
Option 1: Using Homebrew (Recommended)
# Install .NET 8 SDK
brew install dotnet@8
# Add to PATH (add to ~/.zshrc or ~/.bash_profile for persistence)
export PATH="/opt/homebrew/opt/dotnet@8/bin:$PATH"
export DOTNET_ROOT="/opt/homebrew/opt/dotnet@8/libexec"
# Verify installation
dotnet --version
Option 2: Using Official Installer
- Download the installer from dotnet.microsoft.com/download
- Run the
.pkginstaller - Verify installation:
dotnet --version
Windows
Option 1: Using winget (Windows Package Manager)
# Install .NET 8 SDK
winget install Microsoft.DotNet.SDK.8
# Verify installation
dotnet --version
Option 2: Using Official Installer
- Download the installer from dotnet.microsoft.com/download
- Run the
.exeinstaller - Restart your terminal/PowerShell
- Verify installation:
dotnet --version
Option 3: Using Chocolatey
# Install Chocolatey first if not installed
# Then install .NET SDK
choco install dotnet-sdk
# Verify installation
dotnet --version
Linux (Ubuntu/Debian)
# Add Microsoft package repository
wget https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
# Install .NET SDK
sudo apt-get update
sudo apt-get install -y dotnet-sdk-8.0
# Verify installation
dotnet --version
Verify Installation
After installation, verify that .NET SDK is properly installed:
# Check .NET SDK version
dotnet --version
# List installed SDKs
dotnet --list-sdks
# List installed runtimes
dotnet --list-runtimes
Installation
NuGet Package Manager
dotnet add package typecast-csharp
Or via Package Manager Console:
Install-Package typecast-csharp
Unity (via NuGetForUnity)
Install NuGetForUnity from the Unity Asset Store or via Git URL:
- Open Package Manager (Window > Package Manager)
- Click "+" > "Add package from git URL"
- Enter:
https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity
Open NuGet window (NuGet > Manage NuGet Packages)
Search for "typecast-csharp" and install
Quick Start
Basic Usage
using Typecast;
using Typecast.Models;
// Create client with API key
using var client = new TypecastClient("your-api-key");
// Or use environment variable TYPECAST_API_KEY
using var client = new TypecastClient();
// Synthesize text to speech
var request = new TTSRequest(
text: "Hello, world!",
voiceId: "your-voice-id",
model: TTSModel.SsfmV30
);
var response = await client.TextToSpeechAsync(request);
// Save audio to file
await response.SaveToFileAsync("output.wav");
// Or get audio as bytes
byte[] audioData = response.AudioData;
double duration = response.Duration;
Get Available Voices
// Get all voices
var voices = await client.GetVoicesV2Async();
foreach (var voice in voices)
{
Console.WriteLine($"{voice.VoiceId}: {voice.VoiceName}");
}
// Filter voices
var filter = new VoicesV2Filter
{
Model = TTSModel.SsfmV30,
Gender = GenderEnum.Female,
Age = AgeEnum.YoungAdult
};
var filteredVoices = await client.GetVoicesV2Async(filter);
Emotion Control
Preset Mode (explicit emotion)
var request = new TTSRequest("I'm so happy today!", voiceId, TTSModel.SsfmV30)
{
Language = LanguageCode.English,
Prompt = new PresetPrompt(EmotionPreset.Happy, emotionIntensity: 1.5)
};
Smart Mode (context-aware emotion)
var request = new TTSRequest("This is amazing!", voiceId, TTSModel.SsfmV30)
{
Language = LanguageCode.English,
Prompt = new SmartPrompt(
previousText: "I just heard some great news.",
nextText: "I can't believe it happened!"
)
};
Audio Customization
var request = new TTSRequest("Hello, world!", voiceId, TTSModel.SsfmV30)
{
Output = new Output(
volume: 120, // 0-200, default: 100
audioPitch: 2, // -12 to +12 semitones, default: 0
audioTempo: 1.2, // 0.5 to 2.0, default: 1.0
audioFormat: AudioFormat.Mp3 // Wav or Mp3, default: Wav
)
};
Instant cloning
Clone your own voice (or any voice sample) and use it for TTS with no separate contract.
The cloned voice ID carries a uc_ prefix and can be passed directly to TextToSpeechAsync.
using Typecast;
using Typecast.Models;
using var client = new TypecastClient("your-api-key");
// Clone from a local file
CustomVoice cloned = await client.CloneVoiceAsync(
audioFile: "my_voice_sample.wav", // WAV or MP3, max 25 MB
name: "My Cloned Voice", // 1–30 characters
model: "ssfm-v30"
);
Console.WriteLine($"Created: {cloned.VoiceId} — {cloned.Name}");
// Use the cloned voice for TTS immediately
var request = new TTSRequest(
text: "Hello from my cloned voice!",
voiceId: cloned.VoiceId, // "uc_..." prefix
model: TTSModel.SsfmV30
);
var ttsResponse = await client.TextToSpeechAsync(request);
await ttsResponse.SaveToFileAsync("cloned_output.wav");
// Delete the voice when no longer needed
await client.DeleteVoiceAsync(cloned.VoiceId);
Console.WriteLine("Voice deleted.");
You can also pass raw bytes instead of a file path:
byte[] audioBytes = await File.ReadAllBytesAsync("sample.wav");
CustomVoice cloned = await client.CloneVoiceAsync(
audio: audioBytes,
filename: "sample.wav",
name: "My Voice",
model: "ssfm-v30"
);
Constraints enforced client-side before any HTTP call:
| Field | Rule |
|---|---|
audio |
Must not exceed 25 MB |
name |
1–30 characters |
model |
Any valid TTS model string |
Timestamp TTS (Word / Character Alignment)
Use TextToSpeechWithTimestampsAsync to get audio together with word or character
timing data. The response includes helper methods to generate SRT and WebVTT subtitle
files directly.
using Typecast;
using Typecast.Models;
using var client = new TypecastClient("your-api-key");
var request = new TTSRequestWithTimestamps(
text: "Hello. How are you?",
voiceId: "your-voice-id",
model: TTSModel.SsfmV30
);
// Request both word and character alignment
var response = await client.TextToSpeechWithTimestampsAsync(request, granularity: "both");
// Save the audio file
await response.SaveAudioAsync("output.wav");
// Generate subtitles
string srt = response.ToSrt(); // SRT format (uses word segments if available)
string vtt = response.ToVtt(); // WebVTT format
await File.WriteAllTextAsync("subtitles.srt", srt);
await File.WriteAllTextAsync("subtitles.vtt", vtt);
Console.WriteLine($"Audio duration: {response.AudioDuration:F2}s");
Console.WriteLine($"Word segments: {response.Words?.Count}");
Console.WriteLine($"Character segments: {response.Characters?.Count}");
Granularity values:
| Value | Description |
|---|---|
"word" |
Word-level timestamps only |
"char" |
Character-level timestamps only |
"both" |
Both word and character timestamps |
null |
API default (typically both) |
Caption formatting rules:
ToSrt()/ToVtt()prefer word-level segments, fall back to character-level.- Cues are split automatically when duration exceeds 7 seconds or 42 codepoints.
- Sentence terminators (
. ? ! 。 ? !) trigger an immediate cue flush.
Configuration Options
var config = new TypecastClientConfig
{
ApiKey = "your-api-key", // Or use TYPECAST_API_KEY env var
ApiHost = "https://api.typecast.ai", // Optional, custom API host
TimeoutSeconds = 60, // HTTP timeout, default: 30
HttpClient = customHttpClient // Optional, use your own HttpClient
};
using var client = new TypecastClient(config);
Unity Integration
Basic Unity Example
using UnityEngine;
using Typecast;
using Typecast.Models;
using System.Threading.Tasks;
public class TypecastTTS : MonoBehaviour
{
private TypecastClient _client;
private AudioSource _audioSource;
void Start()
{
_client = new TypecastClient("your-api-key");
_audioSource = GetComponent<AudioSource>();
}
public async void SpeakText(string text, string voiceId)
{
try
{
var request = new TTSRequest(text, voiceId, TTSModel.SsfmV30)
{
Language = LanguageCode.English,
Output = new Output(audioFormat: AudioFormat.Wav)
};
var response = await _client.TextToSpeechAsync(request);
// Convert to Unity AudioClip
var audioClip = CreateAudioClipFromWav(response.AudioData);
_audioSource.clip = audioClip;
_audioSource.Play();
}
catch (TypecastException ex)
{
Debug.LogError($"TTS Error: {ex.Message}");
}
}
private AudioClip CreateAudioClipFromWav(byte[] wavData)
{
// Parse WAV header
int channels = wavData[22];
int sampleRate = System.BitConverter.ToInt32(wavData, 24);
int dataStart = 44; // Standard WAV header size
// Find data chunk
for (int i = 12; i < wavData.Length - 4; i++)
{
if (wavData[i] == 'd' && wavData[i+1] == 'a' &&
wavData[i+2] == 't' && wavData[i+3] == 'a')
{
dataStart = i + 8;
break;
}
}
int sampleCount = (wavData.Length - dataStart) / 2;
float[] samples = new float[sampleCount];
for (int i = 0; i < sampleCount; i++)
{
short sample = System.BitConverter.ToInt16(wavData, dataStart + i * 2);
samples[i] = sample / 32768f;
}
var audioClip = AudioClip.Create("TTS", sampleCount / channels, channels, sampleRate, false);
audioClip.SetData(samples, 0);
return audioClip;
}
void OnDestroy()
{
_client?.Dispose();
}
}
Unity UI Button Example
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Typecast;
using Typecast.Models;
public class TTSButton : MonoBehaviour
{
[SerializeField] private Button speakButton;
[SerializeField] private TMP_InputField textInput;
[SerializeField] private AudioSource audioSource;
[SerializeField] private string voiceId;
private TypecastClient _client;
private bool _isProcessing;
void Start()
{
_client = new TypecastClient("your-api-key");
speakButton.onClick.AddListener(OnSpeakClicked);
}
async void OnSpeakClicked()
{
if (_isProcessing || string.IsNullOrWhiteSpace(textInput.text))
return;
_isProcessing = true;
speakButton.interactable = false;
try
{
var request = new TTSRequest(textInput.text, voiceId, TTSModel.SsfmV30);
var response = await _client.TextToSpeechAsync(request);
// Play audio...
}
catch (TypecastException ex)
{
Debug.LogError($"TTS Error: {ex.Message}");
}
finally
{
_isProcessing = false;
speakButton.interactable = true;
}
}
void OnDestroy()
{
_client?.Dispose();
}
}
Unity WebGL Considerations
For WebGL builds, you may need to use JavaScript interop for audio playback:
#if UNITY_WEBGL && !UNITY_EDITOR
// Use JavaScript for audio in WebGL
PlayAudioViaJavaScript(response.AudioData);
#else
// Standard Unity audio
PlayAudioClip(response.AudioData);
#endif
Blazor Integration
Blazor Server Example
// Program.cs
builder.Services.AddSingleton<TypecastClient>(sp =>
new TypecastClient(builder.Configuration["Typecast:ApiKey"]));
// TTSService.cs
public class TTSService
{
private readonly TypecastClient _client;
public TTSService(TypecastClient client)
{
_client = client;
}
public async Task<byte[]> SynthesizeAsync(string text, string voiceId)
{
var request = new TTSRequest(text, voiceId, TTSModel.SsfmV30)
{
Output = new Output(audioFormat: AudioFormat.Mp3)
};
var response = await _client.TextToSpeechAsync(request);
return response.AudioData;
}
}
Blazor Component Example
@page "/tts"
@inject TTSService TTSService
@inject IJSRuntime JSRuntime
<h3>Text-to-Speech</h3>
<div class="mb-3">
<textarea @bind="Text" class="form-control" rows="4"
placeholder="Enter text to synthesize..."></textarea>
</div>
<div class="mb-3">
<select @bind="SelectedVoiceId" class="form-select">
@foreach (var voice in Voices)
{
<option value="@voice.VoiceId">@voice.VoiceName</option>
}
</select>
</div>
<button class="btn btn-primary" @onclick="SynthesizeAsync" disabled="@IsProcessing">
@(IsProcessing ? "Synthesizing..." : "Speak")
</button>
<audio id="ttsAudio" controls style="display: @(HasAudio ? "block" : "none")"></audio>
@code {
private string Text { get; set; } = "";
private string SelectedVoiceId { get; set; } = "";
private List<VoiceV2Response> Voices { get; set; } = new();
private bool IsProcessing { get; set; }
private bool HasAudio { get; set; }
protected override async Task OnInitializedAsync()
{
// Load voices...
}
private async Task SynthesizeAsync()
{
if (string.IsNullOrWhiteSpace(Text) || string.IsNullOrWhiteSpace(SelectedVoiceId))
return;
IsProcessing = true;
try
{
var audioData = await TTSService.SynthesizeAsync(Text, SelectedVoiceId);
var base64Audio = Convert.ToBase64String(audioData);
await JSRuntime.InvokeVoidAsync("playAudio", $"data:audio/mp3;base64,{base64Audio}");
HasAudio = true;
}
catch (TypecastException ex)
{
// Handle error
}
finally
{
IsProcessing = false;
}
}
}
Blazor JavaScript Interop
<script>
window.playAudio = function (src) {
var audio = document.getElementById("ttsAudio");
audio.src = src;
audio.play();
};
</script>
Blazor WebAssembly Example
// Program.cs
builder.Services.AddScoped(sp =>
{
var httpClient = new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) };
return new TypecastClient(new TypecastClientConfig
{
ApiKey = "your-api-key",
HttpClient = httpClient
});
});
Note: For Blazor WebAssembly, consider proxying API calls through your server to protect your API key.
Error Handling
The SDK throws specific exceptions for different error scenarios:
try
{
var response = await client.TextToSpeechAsync(request);
}
catch (UnauthorizedException)
{
// Invalid or missing API key (401)
}
catch (PaymentRequiredException)
{
// Insufficient credits (402)
}
catch (NotFoundException)
{
// Resource not found (404)
}
catch (UnprocessableEntityException)
{
// Validation error (422)
}
catch (RateLimitException)
{
// Too many requests (429)
}
catch (InternalServerException)
{
// Server error (5xx)
}
catch (TypecastException ex)
{
// Other API errors
Console.WriteLine($"Error {ex.StatusCode}: {ex.Message}");
}
Supported Languages
The SDK supports 37 languages with ISO 639-3 codes:
| Language | Code | Language | Code |
|---|---|---|---|
| Korean | kor |
English | eng |
| Japanese | jpn |
Chinese (Mandarin) | cmn |
| Spanish | spa |
French | fra |
| German | deu |
Italian | ita |
| Portuguese | por |
Russian | rus |
| Hindi | hin |
Vietnamese | vie |
| Thai | tha |
Indonesian | ind |
| Arabic | ara |
Dutch | nld |
| Polish | pol |
Swedish | swe |
| Turkish | tur |
Ukrainian | ukr |
| And more... |
API Reference
TypecastClient Methods
| Method | Description |
|---|---|
TextToSpeechAsync(TTSRequest) |
Synthesize text to speech (async) |
TextToSpeech(TTSRequest) |
Synthesize text to speech (sync) |
TextToSpeechWithTimestampsAsync(TTSRequestWithTimestamps, ...) |
Synthesize with word/character alignment timestamps |
GetVoicesV2Async(VoicesV2Filter?) |
Get available voices with metadata (async) |
GetVoicesV2(VoicesV2Filter?) |
Get available voices with metadata (sync) |
GetVoiceV2Async(string voiceId) |
Get a specific voice by ID (async) |
GetVoiceV2(string voiceId) |
Get a specific voice by ID (sync) |
CloneVoiceAsync(byte[], string, string, string) |
Clone a voice from raw audio bytes (async) |
CloneVoiceAsync(string, string, string) |
Clone a voice from a local file path (async) |
DeleteVoiceAsync(string voiceId) |
Delete a custom voice (async) |
Models
TTSRequest- Text-to-speech requestTTSRequestWithTimestamps- Text-to-speech request with timestamp alignmentTTSResponse- Contains audio data, duration, and formatTTSWithTimestampsResponse- Contains base64 audio, alignment segments, andToSrt()/ToVtt()helpersWordSegment/CharacterSegment- Alignment segment with text, start, and end timeOutput- Audio output settingsPrompt/PresetPrompt/SmartPrompt- Emotion controlVoiceV2Response- Voice information with metadataVoicesV2Filter- Voice filtering optionsCustomVoice- Cloned voice metadata (VoiceId,Name,Model)QuickCloningLimits- Constants:CloningMaxFileSize(25 MB),NameMinLength(1),NameMaxLength(30)
Enums
TTSModel- TTS model versions (SsfmV21, SsfmV30)LanguageCode- Supported languagesEmotionPreset- Emotion presetsAudioFormat- Output formats (Wav, Mp3)GenderEnum- Voice gender filterAgeEnum- Voice age category filter
Running Tests
Unit Tests
cd typecast-csharp
dotnet test tests/Typecast.Tests
E2E Tests
# Set up environment
cp tests/Typecast.E2E.Tests/.env.example tests/Typecast.E2E.Tests/.env
# Edit .env and add your API key
# Run E2E tests
dotnet test tests/Typecast.E2E.Tests
Building from Source
git clone https://github.com/neosapience/typecast-sdk.git
cd typecast-sdk/typecast-csharp
dotnet build
dotnet pack -c Release
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Support
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Bcl.AsyncInterfaces (>= 8.0.0)
- System.Net.Http.Json (>= 8.0.1)
- System.Text.Json (>= 8.0.5)
-
.NETStandard 2.1
- System.Text.Json (>= 8.0.5)
-
net10.0
- No dependencies.
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on typecast-csharp:
| Package | Downloads |
|---|---|
|
Shiny.Speech.Typecast
Shiny Speech - Cross-platform speech-to-text and text-to-speech for .NET MAUI |
GitHub repositories
This package is not used by any popular GitHub repositories.