"Computer!" - a low latency tool capable voice assistant
  • Python 99.8%
  • Shell 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Troed Sångberg 9e6b9673a4
Some checks are pending
CI / pytest (push) Waiting to run
CI / package (push) Waiting to run
CI / Install smoke (linux) (push) Blocked by required conditions
CI / Install smoke (macos-arm64) (push) Blocked by required conditions
CI / ruff (push) Waiting to run
CI / mypy (push) Waiting to run
Native LLM STT fixes: kwargs, user messages, WAV wrapping (#6)
* Fix NativeLLMSTTHandler.setup() rejecting unexpected kwargs from faster-whisper args dict

* Fix native-llm: add user message to chat when transcript is empty but audio present

When --stt native-llm is used, transcript is empty but audio_bytes are present.
The _on_transcription_completed condition was 'if transcript' which skipped
adding a user message, causing:
  1. Audio injected into wrong message or not at all → stale responses
  2. Consecutive assistant messages at end of history → llama-server 400 error

Fix: use placeholder text '[audio]' when audio is present but transcript empty.
The _serialize() method then finds the user message and injects the input_audio
content part correctly.

* Fix native-llm audio: wrap raw PCM in WAV container before base64

llama-server requires a valid WAV file for input_audio, not bare int16 PCM
samples. Added _pcm_to_wav() helper that writes a RIFF/WAV header around the
raw PCM bytes (16kHz mono int16).

---------

Co-authored-by: troed <git@troed.se>
2026-07-31 17:08:56 +02:00
.github Bump the actions group with 2 updates 2026-07-17 23:14:18 +00:00
archive Add speculative turn revisions 2026-05-07 22:58:14 +02:00
assets chore: update star history chart [skip ci] 2026-07-15 08:57:52 +00:00
demo Add mic/speaker device selectors to the demo Settings UI. 2026-07-28 15:28:22 +01:00
docs/assets chore: remove docs/superpowers from source control 2026-07-30 09:25:30 +02:00
scripts Can run offline at startup & stability improvements regarding picking up its own spoken words as user commands (#1) 2026-07-30 11:55:27 +02:00
src/speech_to_speech Native LLM STT fixes: kwargs, user messages, WAV wrapping (#6) 2026-07-31 17:08:56 +02:00
tests Native LLM STT fixes: kwargs, user messages, WAV wrapping (#6) 2026-07-31 17:08:56 +02:00
.dockerignore Fix Docker image build 2026-07-03 16:23:25 +02:00
.DS_Store Release prep - typing, CI, folder layout, new uv entrypoint (#248) 2026-04-24 13:46:21 +02:00
.gitignore chore: remove docs/superpowers from source control 2026-07-30 09:31:12 +02:00
AGENTS.md Multi-client support, model singletons, native LLM audio STT, echo/barge-in fixes (#5) 2026-07-31 15:50:03 +02:00
client.sh.example Multi-client support, model singletons, native LLM audio STT, echo/barge-in fixes (#5) 2026-07-31 15:50:03 +02:00
docker-compose.yml Address README review nits 2026-07-03 14:42:00 +02:00
Dockerfile Fix Docker image build 2026-07-03 16:23:25 +02:00
Dockerfile.arm64 Fix Docker image build 2026-07-03 16:23:25 +02:00
LICENSE adding apache license 2024-08-22 17:40:13 +02:00
logo.png add logo 2024-08-19 11:45:38 +02:00
MANIFEST.in Prepare pip install release defaults 2026-05-04 10:56:22 +02:00
mcp.json.example Multi-client support, model singletons, native LLM audio STT, echo/barge-in fixes (#5) 2026-07-31 15:50:03 +02:00
mypy.ini OpenAI Realtime Server API support (#195) 2026-04-07 11:56:31 +02:00
pyproject.toml chore: add mcp>=2.0 SDK dependency 2026-07-29 20:58:24 +02:00
README.md Multi-client support, model singletons, native LLM audio STT, echo/barge-in fixes (#5) 2026-07-31 15:50:03 +02:00
server.sh.example Can run offline at startup & stability improvements regarding picking up its own spoken words as user commands (#1) 2026-07-30 11:55:27 +02:00
uv.lock chore: add mcp>=2.0 SDK dependency 2026-07-29 20:58:24 +02:00

"Computer!" - a low latency tool capable voice assistant

If you've ever watched Star Trek: The Next Generation and felt that you wanted your own Computer! - here you are. This started out as a fork of the huggingface/speech-to-speech project where every change and addition that has been made has had that goal in mind.

Notable functionality:

1. Wake word detection. The system only responds initially after hearing a configured wake word (e.g. "computer"). Uses openWakeWord — train a custom ONNX model at openwakeword.com/train. During the conversation that follows no wake word is needed until after a configurable cooldown period.

2. Audio chimes. Plays a WAV chime on wake word detection (signals the user can speak) and when a server-side tool/search returns (signals the answer is incoming).

3. Barge-in (interrupt). Speak over the assistant mid-response to interrupt TTS output. The system cancels in-flight generation, clears pending audio, plays a wake chime, and processes your speech as new input without requiring the wake word.

4. Dedicated WebSocket client(s). A standalone speech-to-speech-client CLI tool handles wake word detection, microphone input, and speaker output. One server can respond to multiple clients.

5. Can use multimodal LLM backend for STT. If the backing LLM is multimodal, like Gemma4 12B, no dedicated Speech-To-Text (STT) component is needed. This saves VRAM and helps allowing the full stack to run on regular consumer GPUs.

Caveat: For obvious reasons this project does not include the specific chimes and voice cloning data you might want to use.

Example configurations

Three stacked configurations using different amounts of GPU VRAM. Every option runs VAD (Silero VAD v5, ~6 MB), so it is not listed separately. The LLM (Gemma4 12B) runs as a separate llama-server process; all STT and TTS models are shared across pipeline units.

Option 1: faster-whisper + Qwen3-TTS

Component VRAM
faster-whisper tiny.en ~150 MB
Qwen3-TTS Q8_0 ~3.2 GB
Pipeline total ~3.4 GB
speech-to-speech \
    --stt faster-whisper --faster_whisper_stt_model_name tiny.en \
    --tts qwen3 --qwen3_tts_backend ggml --qwen3_tts_quant Q8_0 \
    --mode realtime

Option 2: Parakeet TDT + Qwen3-TTS

Component VRAM
Parakeet TDT 0.6B ~2 GB
Qwen3-TTS Q8_0 ~3.2 GB
Pipeline total ~5.2 GB
speech-to-speech \
    --stt parakeet-tdt \
    --tts qwen3 --qwen3_tts_backend ggml --qwen3_tts_quant Q8_0 \
    --mode realtime

Option 3: Native LLM audio (no STT) + Qwen3-TTS FP16

Drops the STT model entirely. Audio is transcribed by the multimodal LLM itself. Frees enough VRAM to run Qwen3-TTS at full FP16 precision.

Component VRAM
Qwen3-TTS FP16 ~3.6 GB
Pipeline total ~3.6 GB
speech-to-speech \
    --stt native-llm --llm_backend chat-completions \
    --tts qwen3 --qwen3_tts_backend ggml \
    --mode realtime

Reference server configuration

The file server.sh in the repository root is the author's daily-driver configuration:

  • LLM: Gemma4 12B QAT served by llama-server on another machine (--llm_backend responses-api, --responses_api_base_url http://192.168.0.2:11434).
  • STT: faster-whisper tiny.en (--stt faster-whisper, --faster_whisper_stt_model_name tiny.en).
  • TTS: Qwen3-TTS with voice cloning to a Star Trek TNG computer voice (--tts qwen3, --qwen3_tts_quant Q8_0, --qwen3_tts_ref_audio computer.wav).
  • System prompt: Star Trek TNG computer persona with tool-use instructions (--init_chat_prompt).
  • MCP tools: Home Assistant and web search via two MCP servers (--mcp-config mcp.json).
  • Two concurrent clients: (--num_pipelines 2).
  • Wake word: Wake word model handled on the client side; server plays chimes on wake (--wake_word_wake_chime here.wav) and after tool results (--wake_word_search_chime ready.wav).

Adjust --responses_api_base_url to point at your own llama-server, swap in your own --qwen3_tts_ref_audio and --qwen3_tts_instruct for voice cloning, and replace --init_chat_prompt with your desired persona.

Client configuration

A companion speech-to-speech-client CLI handles microphone, speaker, and optional local wake word:

speech-to-speech-client \
    --host 192.168.0.2 --port 8766 \
    --wake-word-model computer.onnx \
    --wake-inactivity-timeout 10

Connect multiple clients at the same time: the server pool (--num_pipelines) determines how many can talk simultaneously. Extra clients are rejected when the pool is full.

Model Setup

The pipeline uses several models (STT, VAD, TTS). These are never auto-downloaded — all network access is blocked at startup. There are two ways to get them:

One-time download (recommended):

uv run python scripts/download_models.py

Downloads all default models (NLTK data, Silero VAD, Parakeet TDT, Qwen3-TTS) into local caches. After this completes, the pipeline runs fully offline.

Realtime API

Realtime mode streams audio over a WebSocket using the OpenAI Realtime protocol, with live transcription and low-latency turn-taking. The server exposes /v1/realtime, and any OpenAI Realtime-compatible client can connect. A dedicated speech-to-speech-client CLI is included.

See src/speech_to_speech/api/openai_realtime/README.md for the supported event set, architecture, and design details.

License

Apache 2.0

Citations (from the upstream Speech-to-Speech project)

If you use this pipeline, please also cite the component models you run. The defaults are:

Gemma4

@misc{gemma4-2026,
  author = {Google DeepMind},
  title = {Gemma 4},
  year = {2026},
  publisher = {Hugging Face},
  howpublished = {\url{https://huggingface.co/google/gemma-4-12B-it}}
}

Silero VAD

@misc{SileroVAD,
  author = {Silero Team},
  title = {Silero VAD: pre-trained enterprise-grade Voice Activity Detector (VAD), Number Detector and Language Classifier},
  year = {2021},
  publisher = {GitHub},
  journal = {GitHub repository},
  howpublished = {\url{https://github.com/snakers4/silero-vad}},
  email = {hello@silero.ai}
}

Parakeet TDT

@misc{parakeet-tdt,
  author = {NVIDIA},
  title = {Parakeet TDT 0.6B v3},
  publisher = {Hugging Face},
  howpublished = {\url{https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3}}
}

Qwen3-TTS

@misc{qwen3-tts,
  author = {Qwen Team},
  title = {Qwen3-TTS},
  publisher = {Hugging Face},
  howpublished = {\url{https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice}}
}

Citations for optional backends such as Kokoro, Pocket TTS, ChatTTS, Whisper variants, Paraformer, and MMS live in the respective component READMEs.