1
0

feat: sovereign voice loop — timmy voice command

Adds fully local listen-think-speak voice interface.
STT: Whisper, LLM: Ollama, TTS: Piper. No cloud, no network.

- src/timmy/voice_loop.py: VoiceLoop with VAD, Whisper, Piper
- src/timmy/cli.py: new voice command
- pyproject.toml: voice extras updated
- 20 new tests
This commit is contained in:
2026-03-14 13:58:56 -04:00
parent d770d66150
commit dbadfc425d
4 changed files with 696 additions and 1 deletions

View File

@@ -248,5 +248,37 @@ def down():
subprocess.run(["docker", "compose", "down"], check=True)
@app.command()
def voice(
whisper_model: str = typer.Option(
"base.en", "--whisper", "-w", help="Whisper model: tiny.en, base.en, small.en, medium.en"
),
use_say: bool = typer.Option(False, "--say", help="Use macOS `say` instead of Piper TTS"),
threshold: float = typer.Option(
0.015, "--threshold", "-t", help="Mic silence threshold (RMS). Lower = more sensitive."
),
silence: float = typer.Option(1.5, "--silence", help="Seconds of silence to end recording"),
backend: str | None = _BACKEND_OPTION,
model_size: str | None = _MODEL_SIZE_OPTION,
):
"""Start the sovereign voice loop — listen, think, speak.
Everything runs locally: Whisper for STT, Ollama for LLM, Piper for TTS.
No cloud, no network calls, no microphone data leaves your machine.
"""
from timmy.voice_loop import VoiceConfig, VoiceLoop
config = VoiceConfig(
whisper_model=whisper_model,
use_say_fallback=use_say,
silence_threshold=threshold,
silence_duration=silence,
backend=backend,
model_size=model_size,
)
loop = VoiceLoop(config=config)
loop.run()
def main():
app()