Instructions to use litert-community/pocket-tts with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use litert-community/pocket-tts with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Pocket-TTS
How to use litert-community/pocket-tts with Pocket-TTS:
from pocket_tts import TTSModel import scipy.io.wavfile tts_model = TTSModel.load_model("litert-community/pocket-tts") voice_state = tts_model.get_state_for_audio_prompt( "hf://kyutai/tts-voices/alba-mackenna/casual.wav" ) audio = tts_model.generate_audio(voice_state, "Hello world, this is a test.") # Audio is a 1D torch tensor containing PCM data. scipy.io.wavfile.write("output.wav", tts_model.sample_rate, audio.numpy()) - Notebooks
- Google Colab
- Kaggle
PocketTTS 100M — MediaPipe & LiteRT
Self-contained .litertlm packages of Kyutai PocketTTS (100M-parameter continuous FlowLM + Mimi neural audio codec, 24 kHz mono PCM output) quantized to INT8 for on-device speech synthesis with the MediaPipe Text-to-Speech (TextToSpeech) Task and LiteRT across Android, iOS, macOS, Python, Web, and C++.
Each .litertlm bundle packages the INT8 LiteRT subgraphs (text conditioner, 6-layer stateful autoregressive FlowLM backbone, 2-step Euler LSD flow-matching network, and stateful Mimi streaming neural codec decoder), the SentencePiece tokenizer, and pre-encoded voice conditioning embeddings into a single memory-mapped file.
Available Model Bundles
| File | Size | Languages | Bundled Voices | Recommended Use Case |
|---|---|---|---|---|
pocket_tts_en_int8.litertlm ⭐ |
156 MB | English (en-US) |
All 8 English voices (alba, marius, javert, jean, fantine, cosette, eponine, azelma) |
Recommended for English applications on mobile, desktop, and web. |
pocket_tts_int8.litertlm |
725 MB | All 7 languages (en-US, fr-FR, de-DE, es-ES, it-IT, pt-BR, nl-NL) |
All 14 voices across 7 languages | Single-file multilingual deployment with sub-millisecond cross-lingual voice switching. |
pocket_tts_fr_int8.litertlm |
122 MB | French (fr-FR) |
estelle (default), alba |
Standalone French bundle or companion file alongside pocket_tts_en_int8.litertlm. |
pocket_tts_de_int8.litertlm |
121 MB | German (de-DE) |
juergen (default), alba |
Standalone German bundle or companion file alongside pocket_tts_en_int8.litertlm. |
pocket_tts_es_int8.litertlm |
121 MB | Spanish (es-ES) |
lola (default), alba |
Standalone Spanish bundle or companion file alongside pocket_tts_en_int8.litertlm. |
pocket_tts_it_int8.litertlm |
120 MB | Italian (it-IT) |
giovanni (default), alba |
Standalone Italian bundle or companion file alongside pocket_tts_en_int8.litertlm. |
pocket_tts_pt_int8.litertlm |
121 MB | Portuguese (pt-BR) |
rafael (default), alba |
Standalone Portuguese bundle or companion file alongside pocket_tts_en_int8.litertlm. |
pocket_tts_nl_int8.litertlm |
120 MB | Dutch (nl-NL) |
daan (default), alba |
Standalone Dutch bundle or companion file alongside pocket_tts_en_int8.litertlm. |
Modular Companion Language Loading: If you load
pocket_tts_en_int8.litertlmand place any per-languagepocket_tts_<lang>_int8.litertlmfile in the same directory, MediaPipeTextToSpeechautomatically discovers and loads the companion language model on demand when you request that language or voice—allowing you to ship only the languages your users download.
Supported Languages & Voices
| Language | BCP 47 Tag | Bundled Voice IDs |
|---|---|---|
| English | en-US |
alba (default), marius, javert, jean, fantine, cosette, eponine, azelma |
| French | fr-FR |
estelle (default for fr) |
| German | de-DE |
juergen (default for de) |
| Spanish | es-ES |
lola (default for es) |
| Portuguese | pt-BR |
rafael (default for pt) |
| Italian | it-IT |
giovanni (default for it) |
| Dutch | nl-NL |
daan (default for nl) |
You can query all voices packaged inside the loaded .litertlm bundle at runtime using listVoices() / list_voices(). When switching voices via SynthesisOptions, setting voiceId automatically infers the matching language if locale is omitted.
MediaPipe Text-to-Speech Task Capabilities
When loaded with the MediaPipe TextToSpeech Task, PocketTTS supports:
- Single-file
.litertlmdeployment: Produces normalized 24 kHz mono 32-bit floating-point (float32) PCM audio in[-1.0, 1.0]with zero external phonemizer or Python dependencies. - Low-latency streaming speech synthesis (
synthesizeStream/synthesize_stream): StreamsAudioChunkbuffers as latent frames are generated and decoded by the stateful Mimi codec, using adaptive first-chunk scheduling (1 frame on step 0, 2 frames on steps 1–4, 4 frames thereafter) for ~45–60 ms Time-To-First-Audio (TTFA). - Real-time LLM-to-TTS token streaming (
openStream/start_stream): Push incremental text deltas (pushText/push_text) directly from an on-device LLM stream and callfinishInput/finish_inputwhen done. Speech synthesis begins immediately once the first clause or word-boundary threshold arrives. - Word-level timestamp alignment (
wordTimestamps/word_timestamps): Both unaryAudioResultand streamingAudioChunkresults include pause-awareWordTimestampentries (word,startChar,endChar,startSec,endSec) mapped directly to character offsets in the input string for real-time read-along text highlighting. - Sub-millisecond voice & language switching: Switch voices or languages per utterance using
SynthesisOptionsin< 1 mswithout reloading model weights. - Built-in text normalization & smart clause chunking: Automatically verbalizes numbers, decimals, ordinals (
1st,2nd), years, currencies ($,€,£), percentages, and times, and segments multi-sentence paragraphs at clause boundaries while guarding common abbreviations (Dr.,Mr.,U.S.,e.g.), decimal numbers (3.14), and numbered lists. - Speaking rate control & lock-free barge-in cancellation: Adjust
speakingRate((0.1, 4.0], default1.0) via pitch-preserving WSOLA time-scale modification, and abort in-flight synthesis within milliseconds viacancel()or native Kotlin Coroutine / SwiftTaskcancellation.
Download
pip install -U huggingface_hub
# English-only bundle (156 MB, 8 voices)
hf download litert-community/pocket-tts pocket_tts_en_int8.litertlm --local-dir .
# Multilingual 7-language bundle (725 MB, 14 voices)
hf download litert-community/pocket-tts pocket_tts_int8.litertlm --local-dir .
Usage with MediaPipe Text-to-Speech Task
1. Android (Kotlin)
See the MediaPipe Text-to-Speech Android Guide and Android Sample App for a complete project setup.
Add the Gradle dependency
Add the MediaPipe Audio Tasks dependency to your module's build.gradle.kts (minSdk = 26, arm64-v8a):
dependencies {
implementation("com.google.mediapipe:tasks-audio:latest.release")
}
Initialize the task and list voices
import com.google.mediapipe.tasks.audio.texttospeech.SynthesisOptions
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("/data/user/0/com.example.app/files/pocket_tts_en_int8.litertlm")
.setDelegate(Delegate.CPU)
.build(),
defaultVoiceId = "alba",
speakingRate = 1.0f,
cacheDirectory = context.cacheDir.absolutePath,
)
val tts = TextToSpeech.create(options)
// Enumerate bundled voices at runtime:
for (voice in tts.listVoices()) {
println("${voice.voiceId} (${voice.displayName}) - locale=${voice.locale}, ${voice.sampleRateHz} Hz")
}
Unary synthesis & word-level timestamps
// Non-blocking coroutine synthesis (or use tts.synthesize(...) on a background thread):
val result = tts.synthesizeAsync(
"Hello from PocketTTS running on-device with MediaPipe Text to Speech!",
SynthesisOptions(voiceId = "marius"),
)
// result.samples: FloatArray (24 kHz mono float32 PCM in [-1.0, 1.0])
// result.sampleRateHz: 24000
// result.durationSeconds: Float
// Word-level timestamps for synchronized read-along UI highlighting:
for (wt in result.wordTimestamps) {
println("Word '${wt.word}' chars=[${wt.startChar}, ${wt.endChar}) time=${wt.startSec}s..${wt.endSec}s")
}
Streaming synthesis & incremental LLM-to-TTS streaming
// 1. Streaming a multi-sentence prompt clause-by-clause / chunk-by-chunk:
tts.synthesizeStream(
"Streaming synthesis plays the first audio chunk in ~50 ms. Subsequent chunks arrive while audio plays.",
SynthesisOptions(voiceId = "alba"),
).collect { chunk ->
streamingAudioTrack.write(chunk.samples, 0, chunk.samples.size, AudioTrack.WRITE_BLOCKING)
// chunk.wordTimestamps provides word timing offsets for the current chunk
}
// 2. Incremental token-by-token streaming from an on-device LLM:
tts.openStream(options = SynthesisOptions(voiceId = "alba")).use { stream ->
stream.pushText("Hello from an ")
stream.pushText("on-device LLM! ")
stream.pushText("Audio starts streaming before generation finishes.")
stream.finishInput()
while (true) {
val chunk = stream.readNext() ?: break
streamingAudioTrack.write(chunk.samples, 0, chunk.samples.size, AudioTrack.WRITE_BLOCKING)
}
}
// Release native resources when done:
tts.close()
2. iOS & macOS (Swift)
See the MediaPipe Text-to-Speech iOS Guide and iOS Sample App.
Add the Swift Package
In Xcode, select File > Add Package Dependencies..., enter https://github.com/google-ai-edge/mediapipe, and add the MediaPipeTasksAudio library to your target.
Initialize and synthesize speech
import Foundation
import MediaPipeTasksAudio
let modelPath = Bundle.main.path(forResource: "pocket_tts_en_int8", ofType: "litertlm")!
let cacheDir = FileManager.default.temporaryDirectory
.appendingPathComponent("mediapipe_tts_cache").path
let options = TextToSpeechOptions(
baseOptions: TTSBaseOptions(
modelAssetPath: modelPath,
delegate: .cpu
),
defaultVoiceId: "alba",
speakingRate: 1.0,
cacheDirectory: cacheDir
)
let tts = try createTextToSpeech(options: options)
// Enumerate bundled voices:
for voice in try tts.listVoices() {
print("\(voice.voiceId) - locale=\(voice.locale), \(voice.sampleRateHz) Hz")
}
// 1. Async unary synthesis with word-level timestamps:
let result = try await tts.synthesizeAsync(
"Hello from PocketTTS on Apple platforms!",
options: SynthesisOptions(voiceId: "alba")
)
for wt in result.wordTimestamps {
print("\(wt.word) [\(wt.startChar)..<\(wt.endChar)]: \(wt.startSec)s - \(wt.endSec)s")
}
// 2. Low-latency streaming synthesis:
for try await chunk in tts.synthesizeStream(
"Streaming synthesis emits 24 kHz PCM chunks as soon as each latent group decodes.",
options: SynthesisOptions(voiceId: "cosette")
) {
// Schedule chunk.samples (24 kHz mono Float) onto AVAudioPlayerNode
}
// 3. Incremental LLM-to-TTS streaming:
let stream = try tts.openStream(options: SynthesisOptions(voiceId: "alba"))
defer { stream.close() }
try stream.pushText("Streaming tokens from ")
try stream.pushText("an on-device language model.")
try stream.finishInput()
while let chunk = try stream.readNext() {
// Play chunk.samples & highlight chunk.wordTimestamps
}
3. Python
import soundfile as sf
from mediapipe.tasks.python.audio import text_to_speech
from mediapipe.tasks.python.core import base_options
options = text_to_speech.TextToSpeechOptions(
base_options=base_options.BaseOptions(
model_asset_path="pocket_tts_en_int8.litertlm"
),
default_voice_id="alba",
speaking_rate=1.0,
)
with text_to_speech.TextToSpeech.create_from_options(options) as tts:
# List bundled voices
for voice in tts.list_voices():
print(f"{voice.voice_id}: locale={voice.locale}, {voice.sample_rate_hz} Hz")
# 1. Unary synthesis + word-level timestamps
result = tts.synthesize(
"Hello from PocketTTS running on-device with MediaPipe in Python!",
voice_id="marius",
)
sf.write("output.wav", result.samples, result.sample_rate_hz)
for wt in result.word_timestamps:
print(f"{wt.word} [{wt.start_char}:{wt.end_char}] {wt.start_sec:.2f}s - {wt.end_sec:.2f}s")
# 2. Streaming synthesis
for chunk in tts.synthesize_stream(
"First sentence streams right away. Second sentence follows seamlessly.",
voice_id="alba",
):
print(f"Chunk {chunk.chunk_index}: {len(chunk.samples)} samples (final={chunk.is_final})")
# 3. Incremental LLM token streaming
with tts.start_stream(voice_id="alba") as stream:
stream.push_text("Streaming tokens ")
stream.push_text("directly into PocketTTS.")
stream.finish_input()
for chunk in stream:
pass # Play chunk.samples in real time
4. Web (JavaScript / TypeScript)
import { FilesetResolver, TextToSpeech } from "@mediapipe/tasks-audio";
const wasmFileset = await FilesetResolver.forAudioTasks(
"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm"
);
const tts = await TextToSpeech.createFromOptions(wasmFileset, {
baseOptions: {
modelAssetPath: "pocket_tts_en_int8.litertlm",
delegate: "CPU",
},
defaultVoiceId: "alba",
speakingRate: 1.0,
});
// List bundled voices
const voices = await tts.listVoices();
console.log("Available voices:", voices);
// 1. Unary synthesis
const result = await tts.synthesize(
"Hello from PocketTTS in the browser via MediaPipe WebAssembly!",
{ voiceId: "alba" }
);
// result.samples: Float32Array, result.sampleRateHz: 24000, result.wordTimestamps
// 2. Streaming synthesis
const stream = await tts.synthesizeStream(
"Streaming speech directly to the Web Audio API.",
{ voiceId: "marius" }
);
for await (const chunk of stream) {
// Schedule chunk.samples (Float32Array at chunk.sampleRateHz) on AudioContext
}
// 3. Incremental LLM token streaming (finishInput = false)
const llmStream = await tts.synthesizeStream("", { voiceId: "alba" }, /* finishInput= */ false);
await llmStream.pushText("Streaming tokens ");
await llmStream.pushText("from WebGPU LLM into PocketTTS.");
await llmStream.finishInput();
for await (const chunk of llmStream) {
// Play chunk.samples and highlight chunk.wordTimestamps
}
tts.close();
5. C++
#include "mediapipe/tasks/cc/audio/text_to_speech/text_to_speech.h"
using ::mediapipe::tasks::audio::text_to_speech::SynthesisOptions;
using ::mediapipe::tasks::audio::text_to_speech::TextToSpeech;
using ::mediapipe::tasks::audio::text_to_speech::TextToSpeechOptions;
auto options = std::make_unique<TextToSpeechOptions>();
options->base_options.model_asset_path = "pocket_tts_en_int8.litertlm";
options->default_voice_id = "alba";
options->speaking_rate = 1.0f;
ABSL_ASSIGN_OR_RETURN(auto tts, TextToSpeech::Create(std::move(options)));
// Unary synthesis:
SynthesisOptions synth_opts{.voice_id = "alba"};
ABSL_ASSIGN_OR_RETURN(auto result, tts->Synthesize("Hello from C++!", synth_opts));
// result.samples (std::vector<float>), result.sample_rate_hz (24000), result.word_timestamps
// Streaming synthesis:
ABSL_ASSIGN_OR_RETURN(auto stream, tts->SynthesizeStream("Streaming from C++.", synth_opts));
while (true) {
ABSL_ASSIGN_OR_RETURN(auto chunk, stream->ReadNext());
if (!chunk.has_value()) break;
// Consume chunk->samples and chunk->word_timestamps
}
Configuration Options Reference
TextToSpeechOptions
| Option (Kotlin / Swift / JS) | Option (Python / C++) | Description | Default |
|---|---|---|---|
baseOptions.modelAssetPath |
base_options.model_asset_path |
Path (or URL on Web) to the .litertlm model bundle. |
Required |
baseOptions.delegate |
base_options.delegate |
Execution delegate (CPU recommended for PocketTTS XNNPACK inference). |
CPU |
defaultVoiceId |
default_voice_id |
Default voice identifier (e.g. "alba", "marius", "estelle"). |
"alba" |
defaultLocale |
default_locale |
Default BCP 47 language tag (e.g. "en-US", "fr-FR"). Automatically inferred from voice ID when omitted. |
Inferred from voice |
speakingRate |
speaking_rate |
Speaking speed multiplier in (0.1, 4.0]. |
1.0 |
cacheDirectory |
cache_directory |
Writable directory path to persist XNNPACK weight caches across runs. | "" |
SynthesisOptions (per-utterance override)
| Option (Kotlin / Swift / JS) | Option (Python / C++) | Description | Default |
|---|---|---|---|
voiceId |
voice_id |
Overrides the voice profile for a single synthesis or streaming call in < 1 ms. |
Task default |
locale |
locale |
Optional BCP 47 locale override (e.g. "fr-FR", "de-DE"). Inferred from voiceId if unset. |
Inferred from voiceId |
License & Attribution
- Original model architecture, weights, and voice embeddings by Kyutai (kyutai/tts-voices), released under CC-BY-4.0.
- Converted and quantized for MediaPipe and LiteRT using litert-torch.
- Downloads last month
- -
Model tree for litert-community/pocket-tts
Base model
kyutai/tts-voices