Skip to main content

Local AI voice assistant for macOS — speaks in your cloned voice on live calls, fully on-device

Project description

Saymo — Local AI Voice Assistant

Fully local AI voice assistant for macOS. Speaks into any live call in your cloned voice — no cloud APIs required.

Saymo composes short, natural speech from optional data sources (tracker, notes, text files), synthesizes it with voice cloning, and routes audio into the active call through a virtual microphone. Everything — language model, speech-to-text, text-to-speech — runs on-device.

  • Local: Ollama + faster-whisper + Coqui XTTS v2 (or Piper / macOS say as fallback).
  • Voice cloning: 5-minute sample → your voice, fine-tuning optional.
  • Routing: BlackHole virtual mic → any browser-based call app.
  • Call automation: Chrome-driven mute/unmute for 8 providers (Glip, Zoom, Google Meet, MS Teams, Telegram, Yandex Telemost, VK Teams, MTS Link).
  • Listening mode: auto-detects when your name is called, answers questions from provided context.
  • User-configurable prompts and vocabulary — no source edits required.

Project status: early public alpha. Expect rough edges. Contributions welcome.


Requirements

  • macOS with Apple Silicon (M1/M2/M3/M4), arm64 terminal, not Rosetta
  • Python 3.11+
  • Homebrew
  • Google Chrome
  • ~10 GB free disk space

Quick install

git clone https://github.com/mshegolev/saymo && cd saymo
cp config.example.yaml config.yaml   # fill in your details
./install.sh

The installer handles brew deps, Python packages (via uv or pip), an Ollama check, a Piper voice model, and Chrome permissions.

First-time setup

saymo setup                        # Interactive wizard: name, devices, profiles
saymo record-voice -d 300          # Record a 5-minute voice sample
saymo test-devices                 # Verify audio devices
saymo test-tts "Привет, это тест"  # Check that TTS works

One-time audio routing

┌─────────────────────────────────────────────────────────────┐
│                   Audio MIDI Setup                          │
│  Create "Multi-Output Device":                              │
│    ✓ Your headphones   (master, no drift correction)        │
│    ✓ BlackHole 16ch    (drift correction ON)                │
│                                                             │
│  In your call app:                                          │
│    Microphone → BlackHole 2ch                               │
│    Speakers   → Multi-Output Device                         │
└─────────────────────────────────────────────────────────────┘

Daily usage

# Before the call: prepare text + cached audio
saymo prepare -p personal
saymo review                    # optional: check generated audio

# During the call
saymo speak --glip              # manual trigger, instant playback
saymo auto -p personal          # listen for your name, speak when called

# Extras
saymo dashboard                 # interactive TUI

Configurable prompts

All LLM prompts are templates loaded from config.yamlprompts.* at runtime, with sensible generic defaults in source. To customize voice/tone:

prompts:
  standup_ru: |
    Ты — помощник для ежедневных встреч. Составь отчёт на русском...
    {yesterday_notes}
    {today_notes}
  qa_system_ru: |
    Ты — {user_name}, {user_role}. Отвечай кратко, 1-3 предложения...

See config.example.yaml for all available keys and the default set.

Project-specific vocabulary

Adding your own abbreviations or fuzzy name expansions to the TTS normalizer is done through config, not source:

vocabulary:
  abbreviations:
    MYAPI: "май-эй-пи-ай"
    K8S: "кубернетес"
  fuzzy_expansions:
    Alex: ["Alex", "Алекс", "Саша", "Саня"]

Architecture

┌───────────────┐   ┌──────────────┐   ┌────────────────┐   ┌──────────────┐
│ Source plugin │──▶│ LLM composer │──▶│ Text normalizer│──▶│  TTS engine  │
│  (optional)   │   │   (Ollama)   │   │   (abbrevs,    │   │  (XTTS clone │
│               │   │              │   │    numbers)    │   │  / Piper)    │
└───────────────┘   └──────────────┘   └────────────────┘   └──────┬───────┘
                                                                   │
┌──────────────┐   ┌──────────────┐   ┌────────────────┐           │
│Call provider │◀──│ Auto trigger │◀──│  STT (Whisper) │       Audio bytes
│(mute/unmute) │   │(name detect) │   │ (capture call) │           │
└──────┬───────┘   └──────────────┘   └────────────────┘           │
       │                                                           │
       ▼                                                           ▼
  BlackHole 2ch ─────────────────────────────────────────── Audio output + monitor
  (virtual mic)

Details in docs/PRD.md and ADRs under docs/adr/.

Security & privacy

  • Everything runs on-device by default. Cloud TTS / STT providers are optional and disabled in the example config.
  • Voice samples and secrets are listed in .gitignore — they never leave your machine.
  • Prompts, vocabulary, trigger phrases are all in your config file — source stays generic.

License

MIT — see LICENSE.

Acknowledgements

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

saymo-0.7.1.tar.gz (111.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

saymo-0.7.1-py3-none-any.whl (130.7 kB view details)

Uploaded Python 3

File details

Details for the file saymo-0.7.1.tar.gz.

File metadata

  • Download URL: saymo-0.7.1.tar.gz
  • Upload date:
  • Size: 111.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.11.8

File hashes

Hashes for saymo-0.7.1.tar.gz
Algorithm Hash digest
SHA256 bbba7394e22388e0c69011de850359833acb0d8a38a327f36ad6741df0c0260a
MD5 8c3abde60d3f13fb430d5988e9e832f6
BLAKE2b-256 dea8f4100446d02d000ef7c393f1c00c2bf42cb3d901b4a4d38273e96760f2a4

See more details on using hashes here.

File details

Details for the file saymo-0.7.1-py3-none-any.whl.

File metadata

  • Download URL: saymo-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 130.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.11.8

File hashes

Hashes for saymo-0.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b0fae229537ec45084a61bccf26d3430775ac8d7f8c99992bcbc0f9a9336bc58
MD5 a11e116fb8c8b66c8a008fba262a408e
BLAKE2b-256 1102b6f725c376fb77ab7205682676b836e1d0f7c38e4865125dd7dff7b2fc19

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page