Local FastAPI server for Higgs Audio v3 TTS 4B with native PyTorch MPS inference on Apple Silicon.
- add more logging for TTS performance (I have no idea which chunk is processed by backend, I would love to see some results)
- add logging of finished task
- reduce logging from GET status (there is a lot of get logs due to other side getting info about status) - maybe status should not be logged in non-debug level
- research quantizations of this model (float16 is heavy on compute on my old used M1 Max mac)
- (maybe) research some similar quality but faster to compute Polish TTS models
- macOS 13+ (Apple Silicon M1/M2/M3/M4)
- Python 3.11+ (managed by
uv) - 64 GB unified memory recommended (the 4B model in float16 uses ~8 GB)
- 15+ GB free disk space for model weights + cache
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.local/bin/envgit clone <your-repo-url>
cd tts_local_api
cp .env.example .env
uv syncuv run uvicorn app.main:app --host 127.0.0.1 --port 8000The API is available at http://127.0.0.1:8000.
Note: On first start, the model (~9.3 GB) downloads from HuggingFace Hub. This may take several minutes depending on your connection.
Edit .env (copy from .env.example):
| Variable | Default | Description |
|---|---|---|
MODEL_ID |
multimodalart/higgs-audio-v3-tts-4b-transformers |
HuggingFace model repo |
DEVICE |
mps |
Device: mps (Apple GPU) or cpu |
TTS_HOST |
127.0.0.1 |
Bind address |
TTS_PORT |
8000 |
Bind port |
mps(default): Uses Apple GPU. Faster for generation, but requires ~8-12 GB RAM for the model.cpu: Uses CPU with 16 threads. Slower but works on older Macs with <16 GB RAM.
Example — run on CPU:
DEVICE=cpu uv run uvicorn app.main:app --host 127.0.0.1 --port 8000| Method | Path | Description |
|---|---|---|
GET |
/ |
Serves the web UI |
GET |
/health |
Health check (returns {"status": "ok"}) |
POST |
/v1/audio/speech |
Generate speech from text (returns WAV) |
{
"text": "Hello world",
"language": "pl",
"voice": "default",
"emotion": "neutral"
}curl -X POST http://127.0.0.1:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"text": "Cześć, jak się masz?", "language": "pl"}' \
-o output.wavcurl -X POST http://127.0.0.1:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"text": "Hello, how are you?", "language": "en"}' \
-o output.wavRun unit tests (no model weights required, completes in <1s):
uv run python -m pytest tests/unit/ -vRun E2E tests (requires a running server with the model loaded):
HIGGS_TTS_E2E_ENABLED=1 uv run python -m pytest tests/e2e/ -v| Script | Description |
|---|---|
scripts/run_dev_server.sh |
Start dev server |
scripts/format.sh |
Format code (black + isort) |
scripts/lint.sh |
Lint code (ruff) |
- Missing weights: The model checkpoint may report
audio_head.weightasMISSING. This is expected for this community port and does not affect generation. - First-start download: The ~9 GB model download happens on first
load_model()call. Be patient — this is normal. - CPU fallback: If MPS loading fails, the server automatically falls back to CPU (float16, 16 threads).
Research / non-commercial use only.