Speech to text
Voice capture uses the browser's own speech recognition by default, and some browsers send that audio to their vendor. If you run a speech-to-text service yourself, people can choose This server's speech service instead. Each spoken phrase then goes from their browser to your OpenTodo server, on to your service, and back as text. Nothing leaves your network.
On this page
OpenTodo speaks the OpenAI-compatible POST /v1/audio/transcriptions request, so any service that implements it works:
- Speaches (formerly faster-whisper-server) runs in one container, on CPU or GPU, under the MIT licence;
- whisper.cpp's server is lighter, a single binary run with
--inference-path /v1/audio/transcriptions; - LocalAI or a hosted service also work if you prefer one.
Run Speaches with Docker Compose#
Add a service next to OpenTodo in your docker-compose.yml:
services:
speaches:
image: ghcr.io/speaches-ai/speaches:latest-cpu
restart: unless-stopped
volumes:
- speaches-models:/home/ubuntu/.cache/huggingface/hub
volumes:
speaches-models:
Download a model once with docker compose exec speaches curl -X POST http://localhost:8000/v1/models/Systran/faster-whisper-small. The small model needs about 1 GB of RAM and answers a short phrase in one to three seconds on four CPU cores. Systran/faster-whisper-base is faster on a small server, and Systran/faster-whisper-medium is more accurate if you have the memory.
Connect it#
In Settings → Server → Speech to text, enter the address (http://speaches:8000 from the same compose project), the model, and a key only if the service needs one. Press Test: OpenTodo sends one second of silence and shows the answer, or the step that failed. The service is on a private network, so also turn on Allow private network targets in Settings → Integrations → Webhooks. Otherwise OpenTodo refuses to reach it.
You can also set it with optional variables. A field set by a variable is read-only in Settings and names it:
| Variable | Meaning |
|---|---|
OPENTODO_STT_URL |
The service's address, http or https |
OPENTODO_STT_MODEL |
The model name the service expects |
OPENTODO_STT_KEY_FILE |
A file holding the key, if the service needs one |
A key typed in Settings is stored in <data>/secrets/stt.json. It is never in the database or in backups, and it is never shown again.
What passes through the server#
- A phrase is at most 60 seconds and 5 MB, recorded only while the microphone is on.
- The server holds the audio and the text in memory for the request, with a 30-second timeout. It writes neither to disk, the database, the logs or the audit log.
- Each person can send 30 phrases a minute.
- Requests go only to the configured host, with no redirects.
- For an end-to-end encrypted account, the statement people confirm says that the server and the service can read the phrase while the request runs.
People choose the recogniser per device in Settings → Capture → Voice capture (Voice).
whisper.cpp instead#
Build or download whisper.cpp's server with a model such as ggml-base.en.bin, then start it with whisper-server -m ggml-base.en.bin --host 0.0.0.0 --port 8080 --inference-path /v1/audio/transcriptions. Use its address and any model name in Settings. whisper.cpp ignores the model name and uses the model it loaded.