ovos-tts-server turns any OVOS TTS plugin into a microservice. It is a small, stateless FastAPI app that exposes text-to-speech over HTTP.
- Plugin-agnostic. Serve Piper, Coqui, Azure, or any OVOS TTS plugin behind one HTTP API.
- Cloud-API compatibility. The server also speaks the ElevenLabs, OpenAI, Coqui, Google, Amazon Polly, Azure, MaryTTS, Cartesia, Deepgram Aura, and PlayHT APIs, so existing clients and SDKs work unmodified. See API compatibility.
- Stateless. Each request loads nothing extra. This suits containers and horizontal scaling.
- Format conversion. The server returns WAV by default, or mp3/ogg/flac/... with the optional
[audio]extra.
pip install ovos-tts-server
# Optional: enable non-WAV output (mp3, ogg, flac, ...) via pydub
pip install "ovos-tts-server[audio]"You also need at least one TTS plugin, for example Piper:
pip install ovos-tts-plugin-piper# Start the server with the Piper plugin
ovos-tts-server --engine ovos-tts-plugin-piper
# Synthesize over HTTP
curl "http://localhost:9666/v2/synthesize?utterance=hello%20world" -o hello.wavovos-tts-server [-h] [--engine ENGINE] [--port PORT] [--host HOST] [--cache] [--lang LANG]
| Option | Default | Description |
|---|---|---|
--engine ENGINE |
none | TTS plugin to load (for example ovos-tts-plugin-piper) |
--port PORT |
9666 |
Port to bind |
--host HOST |
0.0.0.0 |
Host/interface to bind |
--cache |
off | Persist every synth to disk (cache across requests) |
--lang LANG |
en-us |
Default language reported by the plugin |
The plugin is configured exactly as it would be inside the assistant, through mycroft.conf:
{
"tts": {
"module": "ovos-tts-plugin-piper",
"ovos-tts-plugin-piper": {
"model": "alan-low"
}
}
}See docs/configuration.md for how voice and language flow from a request to the plugin.
The server can run OVOS transformer plugins around synthesis, on every endpoint (native, vendor-compat, websocket, MCP/UTCP). Dialog transformers rewrite the text before synthesis, and tts transformers post-process the audio. Enable them with the standard mycroft.conf sections:
{
"dialog_transformers": {
"ovos-dialog-transformer-openai-plugin": {"rewrite_prompt": "reply in a cheerful tone"}
},
"tts_transformers": {
"ovos-tts-transformer-sox-plugin": {"pitch": 300}
}
}Enabling a dialog transformer server-side means the server deliberately synthesizes different text than the client sent. Use it to set a tone or persona globally, across every device using this server. See docs/transformers.md for when to use server-side or device-side transformers, and how to avoid processing the text twice.
The native OVOS endpoints:
| Method | Path | Description |
|---|---|---|
| GET | /status |
Plugin name, supported languages, default voice/model |
| GET | /v2/synthesize?utterance=<text>[&lang=...][&voice=...] |
Primary synthesis endpoint. Returns a WAV file |
| GET | /synthesize/<utterance> |
Legacy path-based synthesis endpoint |
The server forwards any extra query parameter on the synthesis endpoints to the plugin as a synthesis option. CORS is enabled for all origins.
curl http://localhost:9666/status
# {"status": "ok", "plugin": "ovos-tts-plugin-piper", "langs": ["en-us"], ...}The server can also expose the same plugin behind drop-in compatibility endpoints for popular cloud TTS APIs. Each vendor lives under its own URL prefix, so every compat layer stays active at once with no path collisions. The server accepts auth tokens and API keys but ignores them silently; put real auth in a reverse proxy if you need it.
| Vendor | Prefix | Key endpoint |
|---|---|---|
| ElevenLabs | /elevenlabs |
POST /v1/text-to-speech/{voice_id} |
| OpenAI | /openai |
POST /v1/audio/speech |
| Coqui | /coqui |
GET /api/tts |
| Google Cloud TTS | /google-tts |
POST /v1/text:synthesize |
| Amazon Polly | /amazon-polly |
POST /v1/speech |
| Azure TTS | /azure-tts |
POST /cognitiveservices/v1 |
| MaryTTS | /marytts |
GET/POST /process (plus root aliases) |
| Cartesia | /cartesia |
POST /tts/bytes |
| Deepgram Aura | /deepgram |
POST /v1/speak?model=... |
| PlayHT | /playht |
POST /api/v2/tts/stream (plus pyht SDK auth) |
Kokoro / kokoro-fastapi clients are OpenAI-compatible and need no dedicated prefix. Point them at /openai/v1/audio/speech.
Most official SDKs accept a custom base URL. Point them at http://<host>:9666/<prefix> and they work unmodified. See docs/api-compatibility.md for per-vendor endpoints, parameters, SDK snippets, and curl examples.
from ovos_tts_server import start_tts_server
app, engine = start_tts_server("ovos-tts-plugin-piper", cache=False)
# `app` is a FastAPI instance: mount it, test it, or run it with uvicorncreate_app(tts_engine) is also available if you want to build and inject the TTSEngineWrapper yourself.
Build a small image that serves any plugin:
FROM python:3.11-slim
RUN pip install --no-cache-dir "ovos-tts-server[audio]" {PLUGIN_HERE}
ENTRYPOINT ["ovos-tts-server", "--engine", "{PLUGIN_HERE}", "--cache"]docker build . -t my_ovos_tts_plugin
docker run -p 8080:9666 my_ovos_tts_plugin
curl "http://localhost:8080/v2/synthesize?utterance=hello" -o hello.wavEach plugin can ship its own Dockerfile in its repository, using ovos-tts-server.
Consume this server from a voice assistant with the companion TTS plugin.
pip install -e ".[audio,test]"
pytest test/ -v- API compatibility reference: every vendor prefix, endpoint, and SDK snippet
- Voice & language configuration: how requests map to the plugin
- Transformer pipelines: dialog/tts transformer plugins around synthesis
- Audio format conversion:
convert_audio()and the[audio]extra - Architecture overview: classes, entry points, request flow
The server exposes a UTCP manual at GET /utcp. Any UTCP-aware agent, for example ovos-tool-adapters' UTCPToolBox, can point at this URL and auto-discover every synthesis endpoint without extra configuration.
GET /utcp needs no extra dependencies. It is always available.
Example response (abbreviated):
{
"utcp_version": "1.0.1",
"manual_version": "1.0.0",
"tools": [
{
"name": "tts_synthesize_v2",
"description": "Synthesize speech from text (OVOS v2 endpoint)...",
"inputs": {
"type": "object",
"properties": {
"utterance": {"type": "string"},
"voice": {"type": "string"},
"lang": {"type": "string"}
},
"required": ["utterance"]
},
"tool_call_template": {
"call_template_type": "http",
"url": "http://localhost:9666/v2/synthesize",
"http_method": "GET"
}
}
]
}ovos-tool-adapters config example:
{
"utcp_config": {
"providers": [
{
"provider_type": "http",
"name": "ovos-tts",
"url": "http://localhost:9666/utcp"
}
]
}
}The server can optionally expose a FastMCP server mounted at /mcp, providing a synthesize tool callable by any MCP-compatible agent (Claude Desktop, Claude Code, and others).
Install the extra:
pip install "ovos-tts-server[mcp]"Start with MCP enabled:
ovos-tts-server --engine ovos-tts-plugin-piper --mcpOr from Python:
from ovos_tts_server import start_tts_server
app, engine = start_tts_server("ovos-tts-plugin-piper", enable_mcp=True)The MCP server uses streamable HTTP transport (SSE-compatible) and mounts alongside the existing FastAPI app. No separate process is needed.
Claude Desktop claude_desktop_config.json example:
{
"mcpServers": {
"ovos-tts": {
"transport": "http",
"url": "http://localhost:9666/mcp"
}
}
}synthesize tool:
| Parameter | Type | Required | Description |
|---|---|---|---|
text |
string | yes | Text to synthesize |
voice |
string | no | Voice/speaker identifier |
lang |
string | no | BCP-47 language code (for example en-us) |
Returns a JSON object:
{
"mime_type": "audio/wav",
"data": "<base64-encoded WAV>",
"path": "/tmp/ovos_synth_abc123.wav",
"phonemes": null
}Developed by TigreGótico for OpenVoiceOS.
This project was funded through the NGI0 Commons Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 101135429.
