Skip to main content
ClaudeWave

Local Whisper transcription + speaker diarization for Apple Silicon — who said what, fully offline and on-device

ToolsOfficial Registry5 stars0 forks● PythonMITUpdated today
ClaudeWave Trust Score
95/100
✓ Verified
Passed
  • ✓Open-source license (MIT)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Topics declared
  • ✓Documented (README)
Last scanned: 10/22/2026
Get started
Method: Clone
Terminal
git clone https://github.com/sblattj/whosaid
1. Clone the repository.
2. Follow the README for installation and usage instructions.
Use cases

Tools overview

# whosaid

<!-- mcp-name: io.github.sblattj/whosaid -->

Local, speaker-attributed transcription for Apple Silicon — who said what, on your Mac, nothing
leaves the machine.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
![Platform: macOS Apple Silicon](https://img.shields.io/badge/platform-macOS%20Apple%20Silicon-lightgrey.svg)

![whosaid demo — speaker-attributed transcription on the terminal](docs/demo.gif)

**whosaid** pairs **Whisper** speech-to-text with **speaker diarization** to turn a meeting,
interview, call, or podcast recording into a transcript that says *who spoke when* — running fully
**offline and on-device** on an Apple Silicon Mac, with no cloud service, no API keys, and no Hugging
Face token. Think of it as `whisper` + speaker labels + voice-based speaker recognition, in one
command.

**Example output** (`meeting.speakers.txt`):

```text
[00:00:04] Alice: Thanks for jumping on, I know it's late for you.
[00:00:11] SPEAKER_01: No problem at all, happy to make it work.
[00:00:19] Alice: Let's start with the roadmap for next quarter.
[00:00:27] SPEAKER_01: Sounds good, I've got a few updates on that.
```

## Why whosaid

- **Meetings, interviews, calls, podcasts** — get a transcript where every turn is attributed to a
  person, not just a wall of text.
- **Privacy by construction** — audio, text, and voice embeddings never leave your Mac. The only
  cloud step is one you opt into: `[summarizer] engine = "claude"` sends each transcript's text to
  Anthropic to draft action items. Leave it unset and nothing is sent.
- **Your name on your own lines** — a one-time ~45s voice enrollment teaches whosaid your voice, so
  your turns read as your name instead of `SPEAKER_00`.
- **Tells you how many people spoke** — the number of distinct speakers is auto-detected and
  reported up front, with per-speaker turn counts and talk time.
- **Speaker cards to identify who's who** — for every speaker, whosaid writes a card of that voice's
  most representative snippets, so you can read a few lines and know who was talking.
- **Remembers people you name** — identify a speaker once with `whosaid relabel`, and their
  voiceprint is saved to a private local registry so they're auto-named in every future transcript.
- **Fast on long recordings** — recordings over ~15 min are diarized in parallel windows and
  stitched back into consistent speakers by voiceprint, so an 80-minute meeting is minutes, not
  tens of minutes, recovering the same speakers as a single-pass run.
- **No accounts, no API keys, no Hugging Face token** — every model comes from an open, ungated
  source.
- **Search everything you have recorded.** `whosaid index` builds a local full-text (and,
  with Ollama, meaning) index over every transcript in a meeting workspace; `whosaid search`
  finds the turn, `whosaid context` shows the minute around it, and `whosaid graph` answers
  who committed to what, when. See [Search your meetings](#search-your-meetings).
- **Hands-free from Voice Memos.** `whosaid watch install` puts a launchd agent on the Voice
  Memos folder (or any folder): stop recording, and a few minutes later the meeting is
  transcribed, summarized, and searchable. See [Hands-free ingest](#hands-free-ingest-whosaid-watch).
- **Usable from an AI agent, too.** `whosaid mcp` exposes transcribe, relabel, doctor, and the
  read-only workspace search tools as MCP tools for Claude Code, Claude Desktop, Kiro, and other
  MCP clients, with the same local-only guarantee as the CLI.

## How it compares

**Looking for a MacWhisper, whisperX, or aTrain alternative?** If you want speaker-attributed
transcription that runs fully offline on Apple Silicon and can put real *names* on voices — not just
`SPEAKER_00` labels — that's the gap whosaid fills. Here's how it stacks up:

| | whosaid | whisperX | plain mlx-whisper | cloud transcription APIs |
|---|---|---|---|---|
| Speaker labels | Yes | Yes | No | Varies by provider |
| Names speakers by voice | Yes (enrollment) | No | No | No |
| Remembers speakers across meetings | Yes — persistent local voiceprint registry | No | No | No |
| Runs fully offline | Yes | Partial — needs a gated model download | Yes | No |
| Parallel diarization on long audio | Yes | No | — (no diarization) | Varies by provider |
| Needs an account / token | No | Yes — Hugging Face token for gated pyannote models | No | Yes — API key |
| Install weight | `ffmpeg` + `uv`, ephemeral environments | `torch` + `pyannote` + the full HF stack | `mlx-whisper` only | None (network client only) |

## Quickstart

```bash
git clone https://github.com/sblattj/whosaid && cd whosaid   # get the code
./bootstrap.sh                                                # check deps, download models, install ~/.local/bin/whosaid
whosaid enroll                                                # ~45s reading a printed passage — teaches whosaid your voice
whosaid path/to/meeting.m4a                                   # transcribe + diarize + label -> meeting.speakers.txt (and friends)
```

If `~/.local/bin` is not on your shell's `PATH`, add it or invoke the installed command by its
absolute path. `WHOSAID_INSTALL_DIR=/another/bin ./whosaid install` selects another install
directory. The installed command is a symlink to the checkout, so updating the checkout updates the
command without copying or duplicating the implementation.

whosaid's helper scripts need Python 3.11 or newer, because `whosaid.toml` is read with `tomllib`.
The launcher picks one interpreter: `$WHOSAID_PYTHON` if it is set, otherwise the first of `python3`,
`python3.13`, `python3.12` and `python3.11` on your `PATH` that is 3.11+, otherwise
`uv python find '>=3.11'`. It skips the stock macOS `python3` (3.9) automatically. If no interpreter
qualifies, commands that run Python stop with an error; `uv python install 3.13` fixes that.
`whosaid doctor` shows which interpreter was picked.

Homebrew is optional when `uv`, `ffmpeg`, and `ffprobe` are already installed. The launcher
and watcher search `~/.local/bin`, `~/bin`, and `~/homebrew/bin` as well as the usual system
prefixes. Setup can install a pinned, checksum-verified Apple Silicon `uv` archive into
`~/.local/bin`. Homebrew FFmpeg installation requires a bottle; a nonstandard prefix will not
silently trigger a source build.

For a Mac without Homebrew, or one where no bottle is available, use:

```bash
./bootstrap.sh --build-ffmpeg
```

This builds pinned FFmpeg source into user-local `ffmpeg` and `ffprobe` executables. It needs
Apple's Command Line Tools (`xcode-select --install` if missing), compilation time, and free
disk space, but no administrator-owned install prefix or GPG installation. The source archive
is checked with macOS `shasum` against a checksum verified from FFmpeg's signed release.
Existing usable tools are retained. Setup then warms the Python environments and downloads
the models as usual.

## Commands

| Command | What it does |
|---|---|
| `./bootstrap.sh [--yes] [--build-ffmpeg]` (also `whosaid setup`) | Capability check, dependency install, model pre-download, and command installation. `--build-ffmpeg` selects the verified user-local source build when FFmpeg tools are missing. Idempotent — safe to re-run. |
| `whosaid install [--force]` | Install/update the command symlink in `~/.local/bin` (or `WHOSAID_INSTALL_DIR`). Refuses to replace an unrelated command, and refuses (unless `--force`) to install from a checkout under `/tmp`, `/private/tmp`, `/var/tmp`, or `$TMPDIR` — that symlink would dangle once the OS cleans the temp directory up. |
| `whosaid enroll [Name]` | Records ~45s from the mic reading a printed passage, saves `voices/<Name>.wav`. See [Speaker identity: enrollment clips vs. the registry](#speaker-identity-enrollment-clips-vs-the-registry). |
| `whosaid enroll <Name> --from FILE [--ss T] [--t D\|--to T] [--force]` | Extracts a clip from an existing recording instead of the mic (extract → verify → save, no interaction). `--ss`/`--t`/`--to` accept seconds or `M:SS`/`H:MM:SS`; same ≥15s/non-silent bar as mic enrollment. |
| `whosaid record [--label L]` | Foreground mic capture to `recordings/<timestamp>[-label].m4a`, then transcribes automatically. |
| `whosaid record --app A [--no-mic] [--label L]` | Capture one app's audio (Zoom, a browser, ...) through ScreenCaptureKit, plus the mic, to a stereo `recordings/<timestamp>[-label].m4a` (left = mic, right = the app), then transcribe it. `A` is a bundle ID, an app name, or a unique part of either; `whosaid record --list-apps` lists them. Needs macOS 15+, Xcode Command Line Tools (a small Swift helper, `lib/record_app.swift`, is built on first use into `~/.cache/whosaid`) and Screen & System Audio Recording permission for your terminal. No virtual audio device. `--no-mic` records the app alone. With `--me NAME` (or `$WHOSAID_OWNER`), the voice heard only on the mic is named NAME and app-side voices never are. If macOS kills the capture it restarts in place. |
| `whosaid <audio>… [flags]` | The default command: transcribe + diarize + label one or more audio files. `--reuse-asr` skips Whisper when `<out>/<base>.json` already exists and re-diarizes only (errors if the json is missing; not valid with `--no-diarize`). `whosaid transcribe <audio>…` is the same command written explicitly (matching the `whosaid_transcribe` MCP tool name). |
| `whosaid relabel <base> SPEAKER_02=Jane …` | Put real names on clusters after reading the speaker cards. Rewrites the transcript + cards and saves each named voiceprint to the local registry for future transcripts — refusing (unless `--force`) to overwrite an existing registry entry the new cluster doesn't match (similarity below the match threshold, default 0.50). No re-transcription. |
| `whosaid relabel <base> SPEAKER_04=Alice --blend` | Average the cluster into Alice's saved print instead of replacing it, to strengthen the print from a new recording. Same similarity guard as a normal relabel. Se
apple-silicondiarizationmacosmeeting-transcriptionmlxmlx-whisperofflineon-deviceprivacypyannotesherpa-onnxspeaker-diarizationspeaker-identificationspeaker-recognitionspeech-to-texttranscriptionvoice-recognitionwhisperwhisper-diarization

What people ask about whosaid

What is sblattj/whosaid?

+

sblattj/whosaid is tools for the Claude AI ecosystem. Local Whisper transcription + speaker diarization for Apple Silicon — who said what, fully offline and on-device It has 5 GitHub stars and its last recorded update is dated 2026-10-22.

How do I install whosaid?

+

You can install whosaid by cloning the repository (https://github.com/sblattj/whosaid) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is sblattj/whosaid safe to use?

+

Our security agent has analyzed sblattj/whosaid and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains sblattj/whosaid?

+

sblattj/whosaid is maintained by sblattj. The last recorded GitHub activity is dated 2026-10-22, with 3 open issues.

Are there alternatives to whosaid?

+

Yes. On ClaudeWave you can browse similar tools at /categories/tools, sorted by popularity or recent activity.

Deploy whosaid to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: sblattj/whosaid
[![Featured on ClaudeWave](https://claudewave.com/api/badge/sblattj-whosaid)](https://claudewave.com/repo/sblattj-whosaid)
<a href="https://claudewave.com/repo/sblattj-whosaid"><img src="https://claudewave.com/api/badge/sblattj-whosaid" alt="Featured on ClaudeWave: sblattj/whosaid" width="320" height="64" /></a>

More Tools

whosaid alternatives
multica-ai
andrej-karpathy-skills
6mo ago

A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathy's observations on LLM coding pitfalls.

222k22.3k
ToolsInstall
nextlevelbuilder
ui-ux-pro-max-skill
today

An AI skill that provides design intelligence for building professional UI/UX across multiple platforms.

138.6k14.7kPython
Toolsai-skillsantigravityInstall
JuliusBrussee
caveman
today

🪨 why use many token when few token do trick. Viral skill + proxy for coding agents that cuts 65% of tokens by talking like a caveman.

114.2k6.6kGo
ToolsaianthropicInstall
Alishahryar1
free-claude-code
today

Use Claude Code, Codex, VSCode, Pi, and OpenCode (and 6 other harnesses) for free (1.3B+ free tokens) from your terminal, app, IDE, or phone, and now from the browser with native browser sessions (multi-harness + multi-model) like OpenClaw (voice supported + ToS friendly)

62.5k9.8kPython
ToolsInstall
BerriAI
litellm
today

The fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]

61.8k12.6kPython
Toolsai-gatewayanthropicInstall
router-for-me
CLIProxyAPI
today

Wrap Antigravity, ChatGPT Codex, Claude Code, Grok Build, Muse Code, Devin as an OpenAI/Gemini/Claude/Codex compatible API service, allowing you to enjoy the free Gemini Series, GPT Series, Grok Series, Claude model through API

55.9k8.5kGo
Toolsantigravityclaude-codeInstall