Access the Typecast API with our official C/C++ SDK.
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.
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.
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 directlyTypecastClient* client = typecast_client_create("your-api-key-here");// Or with custom base URLTypecastClient* client = typecast_client_create_with_host( "your-api-key-here", "https://custom-api.example.com");
When requests go through your own proxy, pass the proxy host and omit the API key by passing NULL or an empty string. 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.
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.
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);
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);
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-detectedTypecastTTSResponse* response = typecast_text_to_speech(client, &request);// Or specify language explicitly using ISO 639-3 codeTypecastTTSRequest 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 codeTypecastTTSResponse* korean_response = typecast_text_to_speech(client, &korean_request);
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;}
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. Use TYPECAST_OUTPUT_STREAM_DEFAULT() for safe output defaults.
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.
// 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 WebVTTchar* vtt = typecast_tts_with_timestamps_to_vtt(result);// ... same pattern as abovefree(vtt);
Japanese / Chinese: Word-level segmentation is not meaningful for languages without whitespace delimiters (jpn, zho). Use TYPECAST_GRANULARITY_CHAR for these languages to get character-level alignment.