# transcriptor-ai Local, no-cloud meeting transcription for macOS. Captures system audio and microphone as two separate tracks, transcribes both live, and serves a live-updating transcript over HTTP (SSE). Everything runs on-device — no external API calls at runtime. ## How it works ``` audiotee (system audio + mic, 2 tracks) → VAD (speech segmentation, per track) → qwen-asr (speech-to-text, per track) → live transcript, served over SSE ``` Two tracks (system audio vs microphone) act as a cheap "me vs them" diarization: whatever you hear vs whatever you say, without needing a real speaker-diarization model. ## Prerequisites - macOS (Apple Silicon) - Go 1.26+ (`brew install go`) - **[audiotee](../audiotee)** — built and signed with a stable identity so its audio permissions survive rebuilds. Follow that repo's own README/CONTEXT.md first; you should end up with a working binary, e.g. at `~/bin/audiotee`. - **qwen-asr** — vendored as a git submodule (`third_party/qwen-asr`, pinned to a specific commit), built automatically by `scripts/build-dist.sh` below. You still need to download a model yourself (not part of the build — see "Models"), since that's a multi-GB download, not something to fetch on every build: ```bash git submodule update --init third_party/qwen-asr # if you haven't run build-dist.sh yet cd third_party/qwen-asr && ./download_model.sh --model large # or --model small ``` `llama.cpp` (`brew install llama.cpp`) will be needed once post-processing (glossary correction, LLM reread) is implemented, but isn't used yet — no need to install it today. ## Build ```bash git clone --recurse-submodules # or: git submodule update --init scripts/build-dist.sh ``` Builds `qwen_asr` (from the submodule) and `transcriptor-ai` into `dist/`. Also build `transcript-tail` directly, it's not part of `dist/` (that's for what `transcriptor-ui`, the future native app, embeds — see `CLAUDE.md`): ```bash go build -o transcript-tail ./cmd/transcript-tail ``` ## Usage Start the transcriber: ```bash ./dist/transcriptor-ai \ -asr-binary ./dist/qwen_asr \ -asr-model-dir ./third_party/qwen-asr/qwen3-asr-1.7b \ -transcript-file ~/Desktop/meeting-transcript.txt ``` In another terminal, follow the live transcript: ```bash ./transcript-tail ``` Output looks like: ``` [mic ] Bonjour, ceci est un test. [system…] Hello, this is a partial hypothesis that may still be revised ``` (no marker = a closed/final segment; `…` = a partial hypothesis, ASR-in-progress) Stop with Ctrl+C — shutdown is graceful (in-flight transcriptions finish before exiting). ### Flags `transcriptor-ai`: | Flag | Default | Description | |---|---|---| | `-audiotee-binary` | PATH, then `~/bin/audiotee` | Path to the `audiotee` binary | | `-asr-binary` | *(required)* | Path to the `qwen_asr` binary | | `-asr-model-dir` | *(required)* | Path to a qwen-asr model directory | | `-prompt` | *(empty)* | Glossary biasing text passed to qwen-asr (e.g. `"Preserve spelling: Kubernetes, PostgreSQL"`) | | `-http-addr` | `:8420` | Address to serve the live transcript SSE endpoint on | | `-transcript-file` | *(empty)* | Path to append the live transcript to as plain text, flushed to disk after every line. Not written if empty. | | `-capture-system` | `true` | Transcribe the system audio track. Note: audiotee's system tap always runs regardless of this flag — disabling it only stops *transcribing* that track, it doesn't skip the underlying capture (audiotee has no flag for that). | | `-capture-mic` | `true` | Capture and transcribe the microphone track. Unlike `-capture-system`, disabling this actually skips mic capture entirely (no `--capture-mic` passed to audiotee, no microphone permission requested). | At least one of `-capture-system`/`-capture-mic` must stay enabled. `transcript-tail`: | Flag | Default | Description | |---|---|---| | `-url` | `http://localhost:8420/events` | transcriptor-ai SSE endpoint to follow | ### Consuming the transcript programmatically The SSE endpoint (`http://localhost:8420/events` by default) streams one JSON object per transcript segment: ```json {"track": "system", "text": "...", "is_final": false, "timestamp": "2026-08-07T14:32:01.123Z"} ``` Any SSE client works, e.g. `curl -N http://localhost:8420/events`, or a browser's `EventSource`. ## Status Live transcription (capture → VAD → ASR → SSE) works end to end, tested with real speech (English + French, code-switching) through an actual microphone. Not yet implemented: post-processing (glossary fuzzy-matching, LLM reread) and real-time content analysis — see `CLAUDE.md` for what's deliberately deferred and why. ## Related - [audiotee](../audiotee) — the system/mic audio capture CLI this project depends on. - [antirez/qwen-asr](https://github.com/antirez/qwen-asr) — the speech-to-text engine used.