| Crates.io | tauri-plugin-tts |
| lib.rs | tauri-plugin-tts |
| version | 0.1.2 |
| created_at | 2025-12-18 14:29:00.034904+00 |
| updated_at | 2026-01-07 04:01:56.080146+00 |
| description | Native text-to-speech plugin for Tauri with multi-language and voice selection |
| homepage | https://github.com/brenogonzaga/tauri-plugin-tts |
| repository | https://github.com/brenogonzaga/tauri-plugin-tts |
| max_upload_size | |
| id | 1992493 |
| size | 275,624 |
Native Text-to-Speech plugin for Tauri 2.x applications. Provides cross-platform TTS functionality for desktop (Windows, macOS, Linux) and mobile (iOS, Android).
Add the plugin to your Cargo.toml:
[dependencies]
tauri-plugin-tts = "0.1"
Install the JavaScript guest bindings:
npm install tauri-plugin-tts-api
# or
yarn add tauri-plugin-tts-api
# or
pnpm add tauri-plugin-tts-api
In your Tauri app setup:
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_tts::init())
.run(tauri::generate_context!())
.expect("error while running application");
}
Add permissions to your capabilities/default.json:
{
"permissions": ["tts:default"]
}
For granular permissions, you can specify individual commands:
{
"permissions": [
"tts:allow-speak",
"tts:allow-stop",
"tts:allow-get-voices",
"tts:allow-is-speaking",
"tts:allow-preview-voice",
"tts:allow-pause-speaking",
"tts:allow-resume-speaking"
]
}
import { speak, stop, getVoices, isSpeaking } from "tauri-plugin-tts-api";
// Simple speech
await speak({ text: "Hello, world!" });
// With options
await speak({
text: "OlΓ‘, mundo!",
language: "pt-BR",
rate: 0.8, // 0.1 to 4.0 (1.0 = normal)
pitch: 1.2, // 0.5 to 2.0 (1.0 = normal)
volume: 1.0, // 0.0 to 1.0 (1.0 = full)
});
// Stop speaking
await stop();
// Get all voices
const voices = await getVoices();
// Get voices for a specific language
const englishVoices = await getVoices("en");
// Check if speaking
const speaking = await isSpeaking();
Control how new speech requests interact with ongoing speech:
// Default: interrupt current speech (flush)
await speak({ text: "First sentence" });
await speak({ text: "Second sentence" }); // Interrupts first
// Queue mode: add to queue
await speak({ text: "First sentence" });
await speak({ text: "Second sentence", queueMode: "add" }); // Waits for first
Preview voices before selecting them:
import { getVoices, previewVoice } from "tauri-plugin-tts-api";
// Get available voices
const voices = await getVoices("en");
// Preview a voice with default text
await previewVoice({ voiceId: voices[0].id });
// Preview with custom text
await previewVoice({
voiceId: voices[0].id,
text: "This is how I sound!",
});
import { speak, pauseSpeaking, resumeSpeaking } from "tauri-plugin-tts-api";
await speak({ text: "Long text to speak..." });
// Pause (iOS only)
const pauseResult = await pauseSpeaking();
if (pauseResult.success) {
console.log("Speech paused");
// Resume later
const resumeResult = await resumeSpeaking();
if (resumeResult.success) {
console.log("Speech resumed");
}
} else {
console.log("Pause not supported:", pauseResult.reason);
}
| Platform | Status | Engine |
|---|---|---|
| Windows | β Full support | SAPI |
| macOS | β Full support | AVSpeechSynthesizer |
| Linux | β Full support | speech-dispatcher |
| iOS | β Full support + pause/resume | AVSpeechSynthesizer |
| Android | β Full support | TextToSpeech |
| Feature | Windows | macOS | Linux | iOS | Android |
|---|---|---|---|---|---|
speak() |
β | β | β | β | β |
stop() |
β | β | β | β | β |
getVoices() |
β | β | β | β | β |
isSpeaking() |
β | β | β | β | β |
previewVoice() |
β | β | β | β | β |
queueMode |
β | β | β | β | β |
pauseSpeaking() |
β | β | β | β | β |
resumeSpeaking() |
β | β | β | β | β |
speak(options: SpeakOptions): Promise<void>Speak the given text.
Options:
text (required): The text to speaklanguage: Language/locale code (e.g., "en-US", "pt-BR")voiceId: Specific voice ID from getVoices() (takes priority over language)rate: Speech rate (0.1 to 4.0, where 1.0 = normal speed, 2.0 = double, 0.5 = half)pitch: Voice pitch (0.5 to 2.0, where 1.0 = normal, 2.0 = high, 0.5 = low)volume: Volume level (0.0 to 1.0, where 0.0 = silent, 1.0 = full)queueMode: "flush" (default, interrupts current speech) or "add" (queues after current)stop(): Promise<void>Stop any ongoing speech immediately.
getVoices(language?: string): Promise<Voice[]>Get available voices, optionally filtered by language.
Returns: Array of Voice objects with:
id: Unique voice identifiername: Display namelanguage: Language code (e.g., "en-US")isSpeaking(): Promise<boolean>Check if TTS is currently speaking.
previewVoice(options: PreviewVoiceOptions): Promise<void>Preview a voice with sample text.
Options:
voiceId (required): Voice ID to previewtext: Optional custom preview text (uses default if not provided)pauseSpeaking(): Promise<PauseResumeResponse> (iOS only)Pause the current speech.
Returns:
success: Whether pause succeededreason: Optional failure reason (e.g., "Not supported on this platform")resumeSpeaking(): Promise<PauseResumeResponse> (iOS only)Resume paused speech.
Returns: Same as pauseSpeaking()
Solution: Install speech-dispatcher:
# Debian/Ubuntu
sudo apt-get install speech-dispatcher
# Fedora
sudo dnf install speech-dispatcher
# Arch
sudo pacman -S speech-dispatcher
Solution: Ensure a TTS engine is installed:
Open Android Settings β Accessibility β Text-to-Speech
Install "Google Text-to-Speech" from Play Store if missing
Download language data for your desired languages
Solution: Download enhanced voices:
Note: Platform engines may have different interpretations:
Note: pauseSpeaking() and resumeSpeaking() are only supported on iOS. Other platforms will return { success: false, reason: "Not supported" }.
See the examples/tts-example directory for a complete working demo with React + Material UI.
# Build Rust
cargo build
# Build TypeScript
npm run build
# Run tests
cargo test
MIT