The official C/C++ library for the Typecast API. Convert text to lifelike speech using AI-powered voices.
Compatible with C11 and later versions. Works with CMake, manual compilation, and supports cross-platform development including Windows, Linux, macOS, and embedded systems.
Requirements
- CMake 3.14+
- libcurl (with SSL support)
- C11 compatible compiler
sudo apt-get install build-essential cmake libcurl4-openssl-dev
Installation
Clone the repository and build with CMake:
git clone https://github.com/neosapience/typecast-sdk.git
cd typecast-sdk/typecast-c
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
Build Options
| Option | Default | Description |
|---|---|---|
TYPECAST_BUILD_SHARED | ON | Build shared library (.dll/.so/.dylib) |
TYPECAST_BUILD_STATIC | OFF | Build static library |
TYPECAST_BUILD_EXAMPLES | ON | Build example programs |
TYPECAST_BUILD_TESTS | ON | Build test programs |
Quick Start
#include "typecast.h"
#include <stdio.h>
int main() {
// Initialize client
TypecastClient* client = typecast_client_create("YOUR_API_KEY");
if (!client) return 1;
// Convert text to speech
TypecastTTSRequest request = {0};
request.text = "Hello there! I'm your friendly text-to-speech agent.";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee"; /* Find voice IDs at https://studio.typecast.ai/developers/api/voices */
request.model = TYPECAST_MODEL_SSFM_V30;
request.language = "eng";
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
if (response) {
// Save audio file
FILE* fp = fopen("output.wav", "wb");
fwrite(response->audio_data, 1, response->audio_size, fp);
fclose(fp);
printf("Audio saved! Duration: %.2fs, Size: %zu bytes\n",
response->duration, response->audio_size);
typecast_tts_response_free(response);
}
// Clean up
typecast_client_destroy(client);
return 0;
}
Features
The Typecast C/C++ SDK provides powerful features for text-to-speech conversion:
- C and C++ Support: Pure C API with optional C++ wrapper for convenience
- Multiple Voice Models: Support for
ssfm-v30(latest) andssfm-v21AI voice models - Multi-language Support: 37 languages including English, Korean, Spanish, Japanese, Chinese, and more
- Emotion Control: Preset emotions (normal, happy, sad, angry, whisper, toneup, tonedown) or smart context-aware inference
- Audio Customization: Control loudness (LUFS -70 to 0), pitch (-12 to +12 semitones), tempo (0.5x to 2.0x), and format (WAV/MP3)
- Voice Discovery: V2 Voices API with filtering by model, gender, age, and use cases
- Instant Voice Cloning: Upload a WAV/MP3 sample and create a custom voice ID
- Cross-Platform: Windows, Linux, macOS, ARM (32/64-bit) support
- Embedded Ready: Optimized for minimal footprint, cross-compilation support
- Timestamp TTS: Word- and character-level alignment data for subtitles, karaoke, and lip-sync
- Unreal Engine Ready: Designed for easy integration with game engines
- Streaming: Real-time chunked audio delivery for low-latency playback
Voice Recommendations
Use typecast_recommend_voices when you know the desired style but not the exact voice_id.
TypecastRecommendedVoicesResponse* voices = typecast_recommend_voices(
client,
"warm female voice for a product tutorial",
3
);
if (voices) {
for (int i = 0; i < voices->count; i++) {
printf("%s %s %.3f\n",
voices->voices[i].voice_id,
voices->voices[i].voice_name,
voices->voices[i].score);
}
typecast_recommended_voices_response_free(voices);
}
Recommendation results contain only voice_id, voice_name, and score. Use typecast_get_voice or typecast_get_voices when you need detailed metadata such as supported models, emotions, gender, age, or use cases.
Configuration
Set your API key via environment variable or constructor:
#include <stdlib.h>
// Using environment variable
// export TYPECAST_API_KEY="your-api-key-here"
const char* api_key = getenv("TYPECAST_API_KEY");
TypecastClient* client = typecast_client_create(api_key);
// Or pass directly
TypecastClient* client = typecast_client_create("your-api-key-here");
// Or with custom base URL
TypecastClient* client = typecast_client_create_with_host(
"your-api-key-here",
"https://custom-api.example.com"
);
TypecastClient* client = typecast_client_create_with_host(
NULL,
"https://your-proxy.example.com"
);
Advanced Usage
Emotion Control (ssfm-v30)
ssfm-v30 offers two emotion control modes: Preset and Smart.
Let the AI infer emotion from context:
TypecastTTSRequest request = {0};
request.text = "Everything is going to be okay.";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
request.model = TYPECAST_MODEL_SSFM_V30;
request.language = "eng";
// Smart emotion with context
TypecastPrompt prompt = {0};
prompt.emotion_type = TYPECAST_EMOTION_TYPE_SMART;
prompt.previous_text = "I just got the best news!"; // Optional context
prompt.next_text = "I can't wait to celebrate!"; // Optional context
request.prompt = &prompt;
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
Audio Customization
Control loudness, pitch, tempo, and output format:
TypecastTTSRequest request = {0};
request.text = "Customized audio output!";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
request.model = TYPECAST_MODEL_SSFM_V30;
request.language = "eng";
// Configure output settings
TypecastOutput output = TYPECAST_OUTPUT_DEFAULT();
output.use_target_lufs = 1;
output.target_lufs = -14.0f; // Range: -70 to 0 (LUFS)
output.audio_pitch = 2; // Range: -12 to +12 semitones
output.audio_tempo = 1.2f; // Range: 0.5x to 2.0x
output.audio_format = TYPECAST_AUDIO_FORMAT_MP3; // Options: WAV, MP3
request.output = &output;
request.seed = 42; // Unsigned seed for reproducible results
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
if (response) {
const char* ext = (response->format == TYPECAST_AUDIO_FORMAT_MP3) ? "mp3" : "wav";
char filename[64];
snprintf(filename, sizeof(filename), "output.%s", ext);
FILE* fp = fopen(filename, "wb");
fwrite(response->audio_data, 1, response->audio_size, fp);
fclose(fp);
printf("Duration: %.2fs, Format: %s\n", response->duration, ext);
typecast_tts_response_free(response);
}
Generate audio to a file
Use typecast_generate_to_file when you want the SDK to synthesize speech and write the audio bytes directly to a local file. The model defaults to ssfm-v30, and .mp3 / .wav extensions infer the output format when no output format is set. Browse available voice IDs on the Voices page.
TypecastGenerateToFileRequest request = {0};
request.text = "Hello from Typecast.";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee"; /* Find voice IDs at https://studio.typecast.ai/developers/api/voices */
TypecastErrorCode code = typecast_generate_to_file(client, "output.mp3", &request);
if (code != TYPECAST_SUCCESS) {
fprintf(stderr, "Failed to generate audio: %s\n", typecast_error_string(code));
}
For C++ wrapper users:
typecast::GenerateToFileRequest request;
request.text = "Hello from Typecast.";
request.voiceId = "tc_672c5f5ce59fac2a48faeaee"; // Find voice IDs at https://studio.typecast.ai/developers/api/voices
auto response = client.generateToFile("output.mp3", request);
Text pauses
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.
TypecastSpeechComposer* composer = typecast_speech_composer_create(client);
TypecastComposerSettings defaults = {0};
defaults.voice_id = "tc_672c5f5ce59fac2a48faeaee";
defaults.model = TYPECAST_MODEL_SSFM_V30;
typecast_speech_composer_defaults(composer, &defaults);
typecast_speech_composer_say(
composer,
"Hello<|5s|>Nice to meet you<|1s|>Today<|2s|>how does the weather feel?",
NULL
);
TypecastTTSResponse* audio = typecast_speech_composer_generate(composer, TYPECAST_AUDIO_FORMAT_WAV);
typecast_tts_response_free(audio);
typecast_speech_composer_destroy(composer);
Multi-speaker composition
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.
TypecastSpeechComposer* composer = typecast_speech_composer_create(client);
TypecastComposerSettings defaults = {0};
defaults.voice_id = "tc_672c5f5ce59fac2a48faeaee";
defaults.model = TYPECAST_MODEL_SSFM_V30;
typecast_speech_composer_defaults(composer, &defaults);
typecast_speech_composer_say(composer, "Hello there", NULL);
typecast_speech_composer_pause(composer, 5.0f);
TypecastComposerSettings second = {0};
second.voice_id = "tc_60e5426de8b95f1d3000d7b5";
second.output.audio_pitch = 2;
typecast_speech_composer_say(composer, "Nice to meet you", &second);
typecast_speech_composer_pause(composer, 2.0f);
typecast_speech_composer_say(composer, "How does the weather feel?", NULL);
TypecastTTSResponse* audio = typecast_speech_composer_generate(composer, TYPECAST_AUDIO_FORMAT_WAV);
/* write audio->audio_data / audio->audio_len to conversation.wav */
typecast_tts_response_free(audio);
typecast_speech_composer_destroy(composer);
Voice Discovery (V2 API)
List and filter available voices with enhanced metadata:
// Get all voices
TypecastVoicesResponse* voices = typecast_get_voices(client, NULL);
// Or filter by criteria
TypecastModel model = TYPECAST_MODEL_SSFM_V30;
TypecastGender gender = TYPECAST_GENDER_FEMALE;
TypecastAge age = TYPECAST_AGE_YOUNG_ADULT;
TypecastVoicesFilter filter = {0};
filter.model = &model;
filter.gender = &gender;
filter.age = &age;
TypecastVoicesResponse* filtered = typecast_get_voices(client, &filter);
// Display voice info
if (voices) {
for (size_t i = 0; i < voices->count; i++) {
TypecastVoice* v = &voices->voices[i];
printf("ID: %s, Name: %s\n", v->voice_id, v->voice_name);
printf("Gender: %d, Age: %d\n", v->gender, v->age);
for (size_t j = 0; j < v->models_count; j++) {
printf("Model: %s, Emotions: ",
typecast_model_to_string(v->models[j].version));
for (size_t k = 0; k < v->models[j].emotions_count; k++) {
printf("%s ", v->models[j].emotions[k]);
}
printf("\n");
}
if (v->use_cases) {
printf("Use cases: ");
for (size_t k = 0; k < v->use_cases_count; k++) {
printf("%s ", v->use_cases[k]);
}
printf("\n");
}
}
typecast_voices_response_free(voices);
}
Multilingual Content
The SDK supports 37 languages with automatic language detection:
// Auto-detect language (recommended - omit language field)
TypecastTTSRequest request = {0};
request.text = "こんにちは。お元気ですか。";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
request.model = TYPECAST_MODEL_SSFM_V30;
// language is NULL, so it will be auto-detected
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
// Or specify language explicitly using ISO 639-3 code
TypecastTTSRequest korean_request = {0};
korean_request.text = "안녕하세요. 반갑습니다.";
korean_request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
korean_request.model = TYPECAST_MODEL_SSFM_V30;
korean_request.language = "kor"; // ISO 639-3 language code
TypecastTTSResponse* korean_response = typecast_text_to_speech(client, &korean_request);
Streaming
Stream audio chunks in real-time for low-latency playback:
// Extract raw PCM for real-time playback (skip 44-byte WAV header)
static int g_first = 1;
static int on_chunk(const uint8_t *data, size_t len, void *user_data) {
const uint8_t *pcm = data;
size_t pcm_len = len;
if (g_first) {
pcm += 44; // Skip WAV header
pcm_len -= 44;
g_first = 0;
}
// pcm is raw 16-bit mono PCM at 32000 Hz
// Feed to your audio output (e.g. PortAudio, ALSA)
play_audio(pcm, pcm_len); // your playback function
return 0;
}
Timestamp TTS
typecast_text_to_speech_with_timestamps() 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.
Basic Usage
#include "typecast.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
TypecastClient* client = typecast_client_create("YOUR_API_KEY");
if (!client) return 1;
TypecastTTSWithTimestampsRequest request = {0};
request.text = "Hello. How are you?";
request.voice_id = "tc_60e5426de8b95f1d3000d7b5";
request.model = TYPECAST_MODEL_SSFM_V30;
TypecastTTSWithTimestampsResponse* result =
typecast_text_to_speech_with_timestamps(client, &request);
if (result) {
FILE* fp = fopen("output.wav", "wb");
fwrite(result->audio_data, 1, result->audio_size, fp);
fclose(fp);
printf("Duration: %.3fs\n", result->audio_duration);
for (size_t i = 0; i < result->word_count; i++) {
printf(" [%.3fs – %.3fs] %s\n",
result->words[i].start_time,
result->words[i].end_time,
result->words[i].text);
}
typecast_tts_with_timestamps_response_free(result);
}
typecast_client_destroy(client);
return 0;
}
Granularity
Set request.granularity = TYPECAST_GRANULARITY_WORD (default) or TYPECAST_GRANULARITY_CHAR to control the alignment unit.
request.granularity = TYPECAST_GRANULARITY_CHAR; /* required for jpn / zho */
Subtitle Export
// Export SRT (caller must free the returned string)
char* srt = typecast_tts_with_timestamps_to_srt(result);
FILE* fp = fopen("output.srt", "w");
fputs(srt, fp);
fclose(fp);
free(srt);
// Export WebVTT
char* vtt = typecast_tts_with_timestamps_to_vtt(result);
// ... same pattern as above
free(vtt);
Instant Voice Cloning
Clone a custom voice from a short audio sample, then pass the returned uc_ voice ID directly to TTS.
TypecastCustomVoice voice;
TypecastErrorCode rc = typecast_clone_voice(
client,
audio_bytes,
audio_len,
"sample.wav",
"My Voice",
"ssfm-v30",
&voice
);
if (rc == TYPECAST_OK) {
TypecastTTSRequest request = {0};
request.voice_id = voice.voice_id;
request.text = "Hello from my cloned voice!";
request.model = TYPECAST_MODEL_SSFM_V30;
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
if (response) {
typecast_tts_response_free(response);
}
typecast_delete_voice(client, voice.voice_id);
}
Supported Languages
The SDK supports 37 languages with automatic language detection:
| Code | Language | Code | Language | Code | Language |
|---|---|---|---|---|---|
eng | English | jpn | Japanese | ukr | Ukrainian |
kor | Korean | ell | Greek | ind | Indonesian |
spa | Spanish | tam | Tamil | dan | Danish |
deu | German | tgl | Tagalog | swe | Swedish |
fra | French | fin | Finnish | msa | Malay |
ita | Italian | zho | Chinese | ces | Czech |
pol | Polish | slk | Slovak | por | Portuguese |
nld | Dutch | ara | Arabic | bul | Bulgarian |
rus | Russian | hrv | Croatian | ron | Romanian |
ben | Bengali | hin | Hindi | hun | Hungarian |
nan | Hokkien | nor | Norwegian | pan | Punjabi |
tha | Thai | tur | Turkish | vie | Vietnamese |
yue | Cantonese |
Error Handling
The SDK provides specific error codes for handling API errors:
#include "typecast.h"
TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
if (!response) {
const TypecastError* err = typecast_client_get_error(client);
switch (err->code) {
case TYPECAST_ERROR_UNAUTHORIZED:
// 401: Invalid API key
fprintf(stderr, "Invalid API key: %s\n", err->message);
break;
case TYPECAST_ERROR_PAYMENT_REQUIRED:
// 402: Insufficient credits
fprintf(stderr, "Insufficient credits: %s\n", err->message);
break;
case TYPECAST_ERROR_NOT_FOUND:
// 404: Resource not found
fprintf(stderr, "Voice not found: %s\n", err->message);
break;
case TYPECAST_ERROR_UNPROCESSABLE_ENTITY:
// 422: Validation error
fprintf(stderr, "Validation error: %s\n", err->message);
break;
case TYPECAST_ERROR_RATE_LIMIT:
// 429: Rate limit exceeded
fprintf(stderr, "Rate limit exceeded - please retry later\n");
break;
case TYPECAST_ERROR_INTERNAL_SERVER:
// 500: Server error
fprintf(stderr, "Server error: %s\n", err->message);
break;
default:
fprintf(stderr, "API error (%d): %s\n", err->code, err->message);
break;
}
}
Error Codes
| Error Code | Value | Description |
|---|---|---|
TYPECAST_OK | 0 | Success |
TYPECAST_ERROR_INVALID_PARAM | -1 | Invalid request parameters |
TYPECAST_ERROR_OUT_OF_MEMORY | -2 | Memory allocation failed |
TYPECAST_ERROR_CURL_INIT | -3 | Failed to initialize libcurl |
TYPECAST_ERROR_NETWORK | -4 | Network error |
TYPECAST_ERROR_JSON_PARSE | -5 | JSON parsing error |
TYPECAST_ERROR_BAD_REQUEST | 400 | Invalid request |
TYPECAST_ERROR_UNAUTHORIZED | 401 | Invalid or missing API key |
TYPECAST_ERROR_PAYMENT_REQUIRED | 402 | Insufficient credits |
TYPECAST_ERROR_NOT_FOUND | 404 | Resource not found |
TYPECAST_ERROR_UNPROCESSABLE_ENTITY | 422 | Validation error |
TYPECAST_ERROR_RATE_LIMIT | 429 | Rate limit exceeded |
TYPECAST_ERROR_INTERNAL_SERVER | 500 | Server error |
C++ Wrapper
For C++ projects, enable the optional C++ wrapper for a more idiomatic interface:
#define TYPECAST_CPP_WRAPPER
#include "typecast.h"
#include <fstream>
#include <iostream>
int main() {
try {
// Initialize client
typecast::Client client("YOUR_API_KEY");
// Convert text to speech
typecast::TTSRequest request;
request.text = "Hello there! I'm your friendly text-to-speech agent.";
request.voiceId = "tc_672c5f5ce59fac2a48faeaee";
request.model = typecast::Model::SSFM_V30;
request.language = "eng";
auto response = client.textToSpeech(request);
// Save audio file
std::ofstream file("output.wav", std::ios::binary);
file.write(reinterpret_cast<const char*>(response.audioData.data()),
response.audioData.size());
std::cout << "Audio saved! Duration: " << response.duration << "s\n";
} catch (const typecast::TypecastException& e) {
std::cerr << "Error (" << e.code << "): " << e.what() << "\n";
return 1;
}
return 0;
}
Platform Support
The SDK has been verified through automated E2E testing on the following platforms:
| Platform | Architecture | glibc | C Standard | Status |
|---|---|---|---|---|
| CentOS 6.9 | x86_64 | 2.12 | C99 | Verified |
| CentOS 7 | x86_64 | 2.17 | C11 | Verified |
| Amazon Linux 2 | x86_64 | 2.26 | C11 | Verified |
| Ubuntu 20.04 LTS | x86_64 | 2.31 | C11 | Verified |
| Debian Bullseye | x86_64 | 2.31 | C11 | Verified |
| Windows | x64 | N/A | C11 | Verified |
| macOS | x86_64 / arm64 | N/A | C11 | Verified |
Embedded Systems
This SDK can be integrated into embedded systems with network connectivity.
Cross-Compilation
mkdir build-arm && cd build-arm
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../cmake/arm-linux-gnueabihf.cmake \
-DTYPECAST_BUILD_STATIC=ON \
-DTYPECAST_BUILD_SHARED=OFF \
-DCMAKE_BUILD_TYPE=MinSizeRel
cmake --build .
Memory Requirements
| Component | Approximate Size |
|---|---|
| Static library (MinSizeRel) | ~50 KB |
| Runtime heap per client | ~8 KB |
| TTS response buffer | Variable (audio size) |
| JSON parsing buffer | ~4 KB |
Unreal Engine Integration
This SDK is designed for seamless integration with Unreal Engine 4.27+ and Unreal Engine 5.x.
Build the SDK Build as a static library:
mkdir build && cd build cmake .. -DTYPECAST_BUILD_STATIC=ON -DTYPECAST_BUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Release cmake --build . --config ReleaseCreate Plugin Structure Create a plugin in your Unreal project:
Plugins/ └── TypecastTTS/ ├── Source/TypecastTTS/ │ ├── Private/ │ ├── Public/ │ └── ThirdParty/Typecast/ │ ├── include/typecast.h │ └── lib/Win64/typecast_static.lib ├── TypecastTTS.uplugin └── TypecastTTS.Build.csConfigure Build.cs Add library linking to your
Build.cs:// Add include path PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "include")); PublicDefinitions.Add("TYPECAST_STATIC"); // Link static library (platform-specific) if (Target.Platform == UnrealTargetPlatform.Win64) { PublicAdditionalLibraries.Add( Path.Combine(LibPath, "Win64", "typecast_static.lib")); AddEngineThirdPartyPrivateStaticDependencies(Target, "libcurl"); }
API Reference
Client Functions
| Function | Description |
|---|---|
typecast_client_create(api_key) | Create client with API key |
typecast_client_create_with_host(api_key, host) | Create client with custom host |
typecast_client_destroy(client) | Destroy client and free resources |
typecast_client_get_error(client) | Get last error information |
Text-to-Speech Functions
| Function | Description |
|---|---|
typecast_text_to_speech(client, request) | Convert text to speech audio |
typecast_generate_to_file(client, path, request) | Generate speech and save it directly to a local file |
typecast_tts_response_free(response) | Free TTS response memory |
Voice Functions
| Function | Description |
|---|---|
typecast_get_voices(client, filter) | Get available voices (optionally filtered) |
typecast_get_voice(client, voice_id) | Get a specific voice by ID |
typecast_clone_voice(client, audio, audio_len, filename, name, model, out) | Create a custom voice via instant cloning |
typecast_delete_voice(client, voice_id) | Delete a custom cloned voice |
typecast_voices_response_free(response) | Free voices response memory |
typecast_voice_free(voice) | Free single voice memory |
Utility Functions
| Function | Description |
|---|---|
typecast_version() | Get library version string |
typecast_model_to_string(model) | Convert model enum to string |
typecast_emotion_to_string(emotion) | Convert emotion enum to string |
typecast_audio_format_to_string(format) | Convert format enum to string |
typecast_error_message(code) | Get error message for error code |
TypecastTTSRequest Fields
| Field | Type | Required | Description |
|---|---|---|---|
text | const char* | ✓ | Text to synthesize (max 2000 chars) |
voice_id | const char* | ✓ | Voice ID (format: tc_* or uc_*) |
model | TypecastModel | ✓ | TTS model (SSFM_V21 or SSFM_V30) |
language | const char* | ISO 639-3 code (auto-detected if NULL) | |
prompt | TypecastPrompt* | Emotion settings | |
output | TypecastOutput* | Audio output settings | |
seed | unsigned int | Unsigned integer seed for reproducibility (≥ 0) |
TypecastTTSResponse Fields
| Field | Type | Description |
|---|---|---|
audio_data | uint8_t* | Generated audio data |
audio_size | size_t | Size of audio data in bytes |
duration | float | Audio duration in seconds |
format | TypecastAudioFormat | Audio format (wav or mp3) |