The MediaPipe Text-to-Speech task lets you synthesize natural-sounding speech audio from
text directly on-device using open-weight neural text-to-speech
models (Kokoro-82M, PocketTTS 100M, or Phonon 31M), each packaged in
a single .litertlm bundle. The task operates as a headless PCM audio
generator, returning normalized 24 kHz mono 32-bit floating-point (float32)
audio samples that your application can play through platform audio APIs, save
as WAV files, or pass to downstream audio pipelines.
Quickstart
Install the SDK for your platform, initialize the task with a model, and synthesize full clips or streaming audio chunks.
Web
Full clip
import { FilesetResolver, TextToSpeech } from "@mediapipe/tasks-audio"; const audio = await FilesetResolver.forAudioTasks( "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm" ); // Use Kokoro-82M ("kokoro_int8_gpu_fp16.litertlm", delegate: "GPU") or Phonon 31M ("phonon_int8.litertlm", ~87 MB CPU). const tts = await TextToSpeech.createFromOptions(audio, { baseOptions: { modelAssetPath: "kokoro_int8_gpu_fp16.litertlm", delegate: "GPU", }, defaultVoiceId: "af_heart", cacheDirectory: ":nocache", }); // Synthesize a 24 kHz mono clip const audioResult = await tts.synthesize("Hello from MediaPipe Text to Speech in the browser!"); enqueuePcmPlayback(audioResult.samples, audioResult.sampleRateHz);
Audio stream
import { FilesetResolver, TextToSpeech } from "@mediapipe/tasks-audio"; const audio = await FilesetResolver.forAudioTasks( "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm" ); const tts = await TextToSpeech.createFromOptions(audio, { baseOptions: { modelAssetPath: "kokoro_int8_gpu_fp16.litertlm", delegate: "GPU", }, defaultVoiceId: "af_heart", cacheDirectory: ":nocache", }); // Clause-by-clause streaming (or pass finishInput = false and call stream.pushText(delta) // + stream.finishInput() to pipe live LLM tokens into speech) const stream = await tts.synthesizeStream( "First sentence plays right away. Second sentence vocodes while the first plays." ); for await (const chunk of stream) { enqueuePcmPlayback(chunk.samples, chunk.sampleRateHz); }
Android (Kotlin)
Full clip
import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeech import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeechOptions import com.google.mediapipe.tasks.core.BaseOptions import com.google.mediapipe.tasks.core.Delegate val options = TextToSpeechOptions( baseOptions = BaseOptions.builder() .setModelAssetPath("${context.filesDir}/kokoro_int8_gpu_fp16.litertlm") .setDelegate(Delegate.GPU) .build(), defaultVoiceId = "af_heart", cacheDirectory = context.cacheDir.absolutePath, ) val tts = TextToSpeech.create(options) // Suspending unary call: returns one complete 24 kHz AudioResult. // Call it from a coroutine (for example, lifecycleScope.launch { speak(...) }). suspend fun speak(text: String) { val audioResult = tts.synthesizeAsync(text) audioTrackPlayer.write(audioResult.samples, audioResult.sampleRateHz) }
Audio stream
import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeech import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeechOptions import com.google.mediapipe.tasks.core.BaseOptions import com.google.mediapipe.tasks.core.Delegate val options = TextToSpeechOptions( baseOptions = BaseOptions.builder() .setModelAssetPath("${context.filesDir}/kokoro_int8_gpu_fp16.litertlm") .setDelegate(Delegate.GPU) .build(), defaultVoiceId = "af_heart", cacheDirectory = context.cacheDir.absolutePath, ) val tts = TextToSpeech.create(options) // Clause-by-clause Flow<AudioChunk>: playback starts after the first clause // (or call tts.openStream() -> stream.pushText(delta) -> stream.finishInput() for live LLM tokens). suspend fun speakStreaming(text: String) { tts.synthesizeStream(text).collect { chunk -> audioTrackPlayer.write(chunk.samples, chunk.sampleRateHz) } }
Android (Java)
Full clip
import com.google.mediapipe.tasks.audio.texttospeech.AudioResult; import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeech; import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeechOptions; import com.google.mediapipe.tasks.core.BaseOptions; import com.google.mediapipe.tasks.core.Delegate; BaseOptions baseOptions = BaseOptions.builder() .setModelAssetPath(context.getFilesDir() + "/kokoro_int8_gpu_fp16.litertlm") .setDelegate(Delegate.GPU) .build(); TextToSpeechOptions options = new TextToSpeechOptions( baseOptions, "af_heart", null, 1.0f, 64, context.getCacheDir().getAbsolutePath() ); TextToSpeech tts = TextToSpeech.create(options); // Synchronous unary call on a worker thread: returns complete 24 kHz AudioResult AudioResult audioResult = tts.synthesize("Hello from MediaPipe Text to Speech on Android!");
Audio stream
import com.google.mediapipe.tasks.audio.texttospeech.AudioChunk; import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeech; import com.google.mediapipe.tasks.audio.texttospeech.TextToSpeechOptions; import com.google.mediapipe.tasks.audio.texttospeech.TtsStream; import com.google.mediapipe.tasks.core.BaseOptions; import com.google.mediapipe.tasks.core.Delegate; BaseOptions baseOptions = BaseOptions.builder() .setModelAssetPath(context.getFilesDir() + "/kokoro_int8_gpu_fp16.litertlm") .setDelegate(Delegate.GPU) .build(); TextToSpeechOptions options = new TextToSpeechOptions( baseOptions, "af_heart", null, 1.0f, 64, context.getCacheDir().getAbsolutePath() ); TextToSpeech tts = TextToSpeech.create(options); // Pull-based streaming using TtsStream: play each clause chunk as soon as ready try (TtsStream stream = tts.openStream( "First sentence plays right away. Second sentence follows seamlessly.", null, /* finishInput= */ true )) { AudioChunk chunk; while ((chunk = stream.readNext()) != null) { audioTrackPlayer.write(chunk.getSamples(), chunk.getSampleRateHz()); } }
iOS
Full clip
import Foundation import MediaPipeTasksAudio guard let modelPath = Bundle.main.path(forResource: "kokoro_int8_gpu_fp16", ofType: "litertlm") else { return } let cacheDir = FileManager.default.temporaryDirectory.appendingPathComponent("mediapipe_tts_cache").path let options = TextToSpeechOptions( baseOptions: TTSBaseOptions(modelAssetPath: modelPath, delegate: .gpu), defaultVoiceId: "af_heart", cacheDirectory: cacheDir ) let tts = try TextToSpeech(options: options) // Non-blocking unary call: returns one concatenated 24 kHz AudioResult let audioResult = try await tts.synthesizeAsync("Hello from MediaPipe Text to Speech on Apple platforms!")
Audio stream
import Foundation import MediaPipeTasksAudio guard let modelPath = Bundle.main.path(forResource: "kokoro_int8_gpu_fp16", ofType: "litertlm") else { return } let cacheDir = FileManager.default.temporaryDirectory.appendingPathComponent("mediapipe_tts_cache").path let options = TextToSpeechOptions( baseOptions: TTSBaseOptions(modelAssetPath: modelPath, delegate: .gpu), defaultVoiceId: "af_heart", cacheDirectory: cacheDir ) let tts = try TextToSpeech(options: options) // AsyncThrowingStream<AudioChunk, Error>: play each clause as soon as vocoded for try await chunk in tts.synthesizeStream( "First sentence plays right away. Second sentence streams seamlessly." ) { audioPlayer.scheduleSamples(chunk.samples, sampleRate: chunk.sampleRateHz) }
Python
Full clip
import os import tempfile import mediapipe as mp BaseOptions = mp.tasks.BaseOptions TextToSpeech = mp.tasks.audio.TextToSpeech TextToSpeechOptions = mp.tasks.audio.TextToSpeechOptions options = TextToSpeechOptions( base_options=BaseOptions( model_asset_path="kokoro_int8_gpu_fp16.litertlm", delegate=BaseOptions.Delegate.GPU, ), default_voice_id="af_heart", cache_directory=os.path.join(tempfile.gettempdir(), "mediapipe_tts_cache"), ) with TextToSpeech.create_from_options(options) as tts: result = tts.synthesize("Hello from MediaPipe Text to Speech!")
Audio stream
import os import tempfile import mediapipe as mp BaseOptions = mp.tasks.BaseOptions TextToSpeech = mp.tasks.audio.TextToSpeech TextToSpeechOptions = mp.tasks.audio.TextToSpeechOptions options = TextToSpeechOptions( base_options=BaseOptions( model_asset_path="kokoro_int8_gpu_fp16.litertlm", delegate=BaseOptions.Delegate.GPU, ), default_voice_id="af_heart", cache_directory=os.path.join(tempfile.gettempdir(), "mediapipe_tts_cache"), ) with TextToSpeech.create_from_options(options) as tts: # Or use tts.start_stream() -> stream.push_text(delta) -> stream.finish_input() for LLM tokens for chunk in tts.synthesize_stream( "First sentence plays right away. Subsequent clauses synthesize in the background." ): play(chunk.samples, chunk.sample_rate_hz)
Task details
This section describes the capabilities, inputs, outputs, and configuration options of this task.
Features
- Single-file
.litertlmdeployment - Packages each model's weights, text-processing data, and voice embeddings into a single.litertlmbundle. - Low-latency streaming synthesis - Streams
AudioChunkbuffers clause by clause (synthesizeStream/synthesize_stream) so playback starts after the first clause, and accepts incremental text input (synthesizeStreamon Web withfinishInput = false,openStreamon Android and iOS, orstart_streamin Python withpushTextandfinishInput) for LLM-to-speech pipelines. - Per-utterance voice switching - Switches between bundled voices per
utterance using
SynthesisOptionswithout reloading the model (under 1 ms with Kokoro-82M). - Automatic sentence chunking - Splits multi-sentence paragraphs at clause
and sentence boundaries (
.,!,?,;,:,\n) so long inputs stay within the model's context window. - Immediate cancellation - Thread-safe
cancel()aborts in-flight unary or streaming synthesis within milliseconds when a user interrupts.
- UTF-8 text: a single sentence, a multi-sentence paragraph, or incremental text deltas pushed using
TtsStream - Optional per-utterance
SynthesisOptions(voice_idandlocalekeyword arguments in Python)
AudioResult(TextToSpeechResulton Web,TtsAudioResultin Python) for unary calls- A stream of
AudioChunk(TextToSpeechAudioChunkon Web) buffers withchunkIndexandisFinalmetadata for streaming calls - Normalized 32-bit float mono PCM samples in
[-1.0, 1.0]at 24,000 Hz, plus optionalwordTimestampswhen produced by the model
Configuration options
This task has the following configuration options:
Web
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
baseOptions.modelAssetPath |
Path (or URL / modelAssetBuffer as a Uint8Array or ReadableStreamDefaultReader on Web) to a supported .litertlm model bundle (see Models). Keep the original filename, which the task uses to detect the model type. |
String / Path | Required |
baseOptions.delegate |
Hardware acceleration delegate used by the LiteRT runtime. When set to GPU, the Kokoro acoustic stage executes on CPU (XNNPACK) and the neural vocoder executes on GPU (OpenCL/Metal/WebGPU) with CPU fallback. PocketTTS and Phonon run on CPU. |
{CPU, GPU} |
CPU |
speakingRate |
Speaking rate multiplier applied to synthesized audio (1.0 represents normal speaking speed). |
Float (0.0, 4.0] |
1.0 |
targetBucket |
Target sequence-length bucket for the Kokoro acoustic/vocoder graph (for example, 64, 128, or 256 tokens). Smaller buckets reduce synthesis latency for short sentences; 0 uses the model's default capacity. PocketTTS and Phonon ignore this option. |
0, 64, 128, 256 |
0 |
defaultVoiceId |
Default voice ID (for example, "af_heart" for Kokoro-82M, "alba" for PocketTTS, or "freya" for Phonon). Can be overridden per utterance using SynthesisOptions. |
String (Optional) | The model's default voice |
defaultLocale |
Optional default BCP 47 language tag (for example, "en-US", "es", "zh-CN"). When omitted, the task automatically infers the language from the selected voice. |
BCP 47 String (Optional) | Inferred from voice ("en-US" in Python) |
cacheDirectory |
Writable directory path used to persist unpacked phonetic dictionary assets and LiteRT XNNPACK weight caches across runs for faster cold starts (Kokoro-82M). On Web, set this to ":nocache" to turn caching off, as the browser's virtual file system does not persist caches across page loads. |
Directory Path (Optional) | "" |
Per-utterance options (SynthesisOptions):
| Option Name | Description | Default Value |
|---|---|---|
voiceId |
Overrides the voice profile for a single synthesize call (for example, switching from "af_heart" to "ef_dora" in under 1 ms without reloading model weights). |
null (uses task default) |
locale |
Optional BCP 47 locale override for a single utterance. Leave unset when switching voices so the engine automatically resolves the target language from voiceId. |
null (inferred from voiceId) |
Android
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
baseOptions.modelAssetPath |
Path (or URL / modelAssetBuffer as a Uint8Array or ReadableStreamDefaultReader on Web) to a supported .litertlm model bundle (see Models). Keep the original filename, which the task uses to detect the model type. |
String / Path | Required |
baseOptions.delegate |
Hardware acceleration delegate used by the LiteRT runtime. When set to GPU, the Kokoro acoustic stage executes on CPU (XNNPACK) and the neural vocoder executes on GPU (OpenCL/Metal/WebGPU) with CPU fallback. PocketTTS and Phonon run on CPU. |
{CPU, GPU} |
CPU |
speakingRate |
Speaking rate multiplier applied to synthesized audio (1.0 represents normal speaking speed). |
Float (0.0, 4.0] |
1.0 |
targetBucket |
Target sequence-length bucket for the Kokoro acoustic/vocoder graph (for example, 64, 128, or 256 tokens). Smaller buckets reduce synthesis latency for short sentences; 0 uses the model's default capacity. PocketTTS and Phonon ignore this option. |
0, 64, 128, 256 |
0 |
defaultVoiceId |
Default voice ID (for example, "af_heart" for Kokoro-82M, "alba" for PocketTTS, or "freya" for Phonon). Can be overridden per utterance using SynthesisOptions. |
String (Optional) | The model's default voice |
defaultLocale |
Optional default BCP 47 language tag (for example, "en-US", "es", "zh-CN"). When omitted, the task automatically infers the language from the selected voice. |
BCP 47 String (Optional) | Inferred from voice ("en-US" in Python) |
cacheDirectory |
Writable directory path used to persist unpacked phonetic dictionary assets and LiteRT XNNPACK weight caches across runs for faster cold starts (Kokoro-82M). On Web, set this to ":nocache" to turn caching off, as the browser's virtual file system does not persist caches across page loads. |
Directory Path (Optional) | "" |
Per-utterance options (SynthesisOptions):
| Option Name | Description | Default Value |
|---|---|---|
voiceId |
Overrides the voice profile for a single synthesize call (for example, switching from "af_heart" to "ef_dora" in under 1 ms without reloading model weights). |
null (uses task default) |
locale |
Optional BCP 47 locale override for a single utterance. Leave unset when switching voices so the engine automatically resolves the target language from voiceId. |
null (inferred from voiceId) |
iOS
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
baseOptions.modelAssetPath |
Path (or URL / modelAssetBuffer as a Uint8Array or ReadableStreamDefaultReader on Web) to a supported .litertlm model bundle (see Models). Keep the original filename, which the task uses to detect the model type. |
String / Path | Required |
baseOptions.delegate |
Hardware acceleration delegate used by the LiteRT runtime. When set to GPU, the Kokoro acoustic stage executes on CPU (XNNPACK) and the neural vocoder executes on GPU (OpenCL/Metal/WebGPU) with CPU fallback. PocketTTS and Phonon run on CPU. |
{CPU, GPU} |
CPU |
speakingRate |
Speaking rate multiplier applied to synthesized audio (1.0 represents normal speaking speed). |
Float (0.0, 4.0] |
1.0 |
targetBucket |
Target sequence-length bucket for the Kokoro acoustic/vocoder graph (for example, 64, 128, or 256 tokens). Smaller buckets reduce synthesis latency for short sentences; 0 uses the model's default capacity. PocketTTS and Phonon ignore this option. |
0, 64, 128, 256 |
0 |
defaultVoiceId |
Default voice ID (for example, "af_heart" for Kokoro-82M, "alba" for PocketTTS, or "freya" for Phonon). Can be overridden per utterance using SynthesisOptions. |
String (Optional) | The model's default voice |
defaultLocale |
Optional default BCP 47 language tag (for example, "en-US", "es", "zh-CN"). When omitted, the task automatically infers the language from the selected voice. |
BCP 47 String (Optional) | Inferred from voice ("en-US" in Python) |
cacheDirectory |
Writable directory path used to persist unpacked phonetic dictionary assets and LiteRT XNNPACK weight caches across runs for faster cold starts (Kokoro-82M). On Web, set this to ":nocache" to turn caching off, as the browser's virtual file system does not persist caches across page loads. |
Directory Path (Optional) | "" |
Per-utterance options (SynthesisOptions):
| Option Name | Description | Default Value |
|---|---|---|
voiceId |
Overrides the voice profile for a single synthesize call (for example, switching from "af_heart" to "ef_dora" in under 1 ms without reloading model weights). |
null (uses task default) |
locale |
Optional BCP 47 locale override for a single utterance. Leave unset when switching voices so the engine automatically resolves the target language from voiceId. |
null (inferred from voiceId) |
Python
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
base_options.model_asset_path |
Path (or URL / modelAssetBuffer as a Uint8Array or ReadableStreamDefaultReader on Web) to a supported .litertlm model bundle (see Models). Keep the original filename, which the task uses to detect the model type. |
String / Path | Required |
base_options.delegate |
Hardware acceleration delegate used by the LiteRT runtime. When set to GPU, the Kokoro acoustic stage executes on CPU (XNNPACK) and the neural vocoder executes on GPU (OpenCL/Metal/WebGPU) with CPU fallback. PocketTTS and Phonon run on CPU. |
{CPU, GPU} |
CPU |
speaking_rate |
Speaking rate multiplier applied to synthesized audio (1.0 represents normal speaking speed). |
Float (0.0, 4.0] |
1.0 |
target_bucket |
Target sequence-length bucket for the Kokoro acoustic/vocoder graph (for example, 64, 128, or 256 tokens). Smaller buckets reduce synthesis latency for short sentences; 0 uses the model's default capacity. PocketTTS and Phonon ignore this option. |
0, 64, 128, 256 |
0 |
default_voice_id |
Default voice ID (for example, "af_heart" for Kokoro-82M, "alba" for PocketTTS, or "freya" for Phonon). Can be overridden per utterance using SynthesisOptions. |
String (Optional) | The model's default voice |
default_locale |
Optional default BCP 47 language tag (for example, "en-US", "es", "zh-CN"). When omitted, the task automatically infers the language from the selected voice. |
BCP 47 String (Optional) | Inferred from voice ("en-US" in Python) |
cache_directory |
Writable directory path used to persist unpacked phonetic dictionary assets and LiteRT XNNPACK weight caches across runs for faster cold starts (Kokoro-82M). On Web, set this to ":nocache" to turn caching off, as the browser's virtual file system does not persist caches across page loads. |
Directory Path (Optional) | "" |
Per-utterance keyword arguments on synthesize / synthesize_stream:
| Option Name | Description | Default Value |
|---|---|---|
voice_id |
Overrides the voice profile for a single synthesize call (for example, switching from "af_heart" to "ef_dora" in under 1 ms without reloading model weights). |
None (uses task default) |
locale |
Optional BCP 47 locale override for a single utterance. Leave unset when switching voices so the engine automatically resolves the target language from voice_id. |
None (inferred from voice_id) |
Task output
Unary calls (synthesize) return a complete AudioResult (TextToSpeechResult on Web, TtsAudioResult in Python), and streaming calls (synthesizeStream / synthesize_stream) yield AudioChunk buffers as each clause is vocoded:
| Field | Type / Range | Description |
|---|---|---|
samples |
Float32Array ([-1.0, 1.0]) |
Synthesized mono PCM audio samples. |
sampleRateHz |
int (Hz) |
Output audio sample rate, such as 24000 Hz for Kokoro (sample_rate_hz in Python). |
wordTimestamps |
WordTimestamp[] (seconds) |
Optional word-level alignment intervals (word, startTimeSec, endTimeSec). |
chunkIndex |
int |
Zero-based clause sequence index yielded on each streaming AudioChunk (chunk_index in Python). |
isFinal |
boolean |
true on the final streaming AudioChunk of an utterance (is_final in Python). |
Example TextToSpeechResult payload
The following example shows synthesized 24 kHz mono PCM audio with word-level alignment timestamps:
{
sampleRateHz: 24000,
samples: Float32Array(57600) [-0.0012, 0.0045, 0.0118 /* ... 2.4s mono PCM */],
wordTimestamps: [
{ word: "Hello", startTimeSec: 0.04, endTimeSec: 0.38 },
{ word: "world", startTimeSec: 0.40, endTimeSec: 0.82 }
]
}
Models
The MediaPipe Text-to-Speech task requires a speech synthesis model in the LiteRT-LM
(.litertlm) format. Models aren't included in the MediaPipe Tasks libraries.
Download one of the following pre-packaged model bundles from Hugging Face,
store it on the device, and pass the local path to
BaseOptions.modelAssetPath (model_asset_path in Python).
| Model | Model Bundle | Size | Quantization | Delegate | License | Supported Locales | Recommended Use Case |
|---|---|---|---|---|---|---|---|
| Kokoro-82M | kokoro_int8_gpu_fp16.litertlm |
~295 MB | INT8 acoustic + FP16 GPU vocoder | GPU | Apache 2.0 | All nine locales (en-US, en-GB, es, fr-FR, it, pt-BR, hi, cmn, ja) |
Multilingual on-device speech synthesis across mobile, desktop, and web. |
| PocketTTS 100M | pocket_tts_int8.litertlm |
~760 MB | INT8 | CPU | CC BY 4.0 | Seven locales (en-US, fr-FR, de-DE, es-ES, it-IT, pt-BR, nl-NL) |
Multilingual speech synthesis on CPU. |
| PocketTTS 100M (English) | pocket_tts_en_int8.litertlm |
~163 MB | INT8 | CPU | CC BY 4.0 | en-US |
English speech synthesis on CPU with a smaller download. |
| Phonon 31M | phonon_int8.litertlm |
~87 MB | INT8 | CPU | Apache 2.0 | en-US |
English speech synthesis with the smallest download. |
Supported languages and voices
Each model bundle includes its own set of voices. You can enumerate the voices
in the loaded .litertlm bundle at runtime using listVoices() /
list_voices().
Kokoro-82M voices
Kokoro-82M includes 54 pre-packaged voice embeddings across nine locales
(eight languages). Each voice ID uses a two-letter prefix
<lang_char><gender_char>_<name> (for example, af_heart = American English
Female "Heart", ef_dora = Spanish Female "Dora").
| Language | BCP 47 Language Tag | Prefix | Bundled Voice IDs (54 Total) |
|---|---|---|---|
| English (American) | en-US |
af_, am_ |
Female (11): af_alloy, af_aoede, af_bella, af_heart (default), af_jessica, af_kore, af_nicole, af_nova, af_river, af_sarah, af_skyMale (9): am_adam, am_echo, am_eric, am_fenrir, am_liam, am_michael, am_onyx, am_puck, am_santa |
| English (British) | en-GB |
bf_, bm_ |
Female (4): bf_alice, bf_emma, bf_isabella, bf_lilyMale (4): bm_daniel, bm_fable, bm_george, bm_lewis |
| Spanish | es |
ef_, em_ |
Female (1): ef_doraMale (2): em_alex, em_santa |
| French | fr-FR |
ff_ |
Female (1): ff_siwis |
| Hindi | hi |
hf_, hm_ |
Female (2): hf_alpha, hf_betaMale (2): hm_omega, hm_psi |
| Italian | it |
if_, im_ |
Female (1): if_saraMale (1): im_nicola |
| Portuguese (Brazilian) | pt-BR |
pf_, pm_ |
Female (1): pf_doraMale (2): pm_alex, pm_santa |
| Mandarin Chinese | zh-CN / cmn |
zf_, zm_ |
Female (4): zf_xiaobei, zf_xiaoni, zf_xiaoxiao, zf_xiaoyiMale (4): zm_yunjian, zm_yunxi, zm_yunxia, zm_yunyang |
| Japanese | ja |
jf_, jm_ |
Female (4): jf_alpha, jf_gongitsune, jf_nezumi, jf_tebukuroMale (1): jm_kumo |
PocketTTS 100M voices
Each PocketTTS voice speaks one language. The multilingual bundle
(pocket_tts_int8.litertlm) includes all of the following voices, and the
English bundle (pocket_tts_en_int8.litertlm) includes only English voices.
| Language | BCP 47 Language Tag | Voice IDs |
|---|---|---|
| English | en-US |
alba (default), azelma, cosette, eponine, fantine, javert, jean, marius |
| French | fr-FR |
estelle |
| German | de-DE |
juergen |
| Spanish | es-ES |
lola |
| Italian | it-IT |
giovanni |
| Portuguese (Brazilian) | pt-BR |
rafael |
| Dutch | nl-NL |
daan |
As with Kokoro-82M, set only voiceId (voice_id in Python) when you switch
voices. If you also set a locale that doesn't match the voice's language, the
task uses the default voice for that locale instead.
Phonon 31M voices
Phonon 31M speaks English (en-US) only. It includes five voices:
freya (default), claire, lucas, lukas, and sofia.
Model license and attribution
Kyutai publishes PocketTTS under the Creative Commons Attribution 4.0 (CC-BY-4.0) license. If you distribute an app that uses a PocketTTS model, give appropriate credit to Kyutai, for example in your app's open source notices.
How it works
For Kokoro-82M, the MediaPipe Text-to-Speech task runs a multi-stage pipeline:
- Sentence segmentation: Multi-sentence input text (or incremental text
pushed using
TtsStream) is split at punctuation boundaries to fit the acoustic model's token capacity. - Grapheme-to-phoneme (G2P) frontend: Converts normalized text into phoneme token IDs using the phonetic dictionaries bundled in the model for each supported language.
- Acoustic stage: Runs the LiteRT acoustic model, conditioned on the selected voice's style embedding, to predict duration, pitch, and energy contours together with the acoustic features.
- Neural vocoder stage: Runs the ISTFTNet-based LiteRT vocoder model (on
CPU using XNNPACK, or hybrid CPU+GPU) to convert the acoustic features into
a 24 kHz mono
float32PCM waveform. During streaming synthesis, each clause'sAudioChunkis emitted as soon as it is vocoded; unary synthesis concatenates all chunks into a singleAudioResult.
PocketTTS 100M and Phonon 31M use a different architecture: a Flow-LM transformer generates audio latents, and a Mimi neural audio decoder converts them into 24 kHz audio. Both models run on CPU.