Skip to main content

TapScribe

Local transcription recorder and operator dashboard. TapScribe records one WAV per utterance per speaker over a WebSocket, runs Whisper / Voxtral / Parakeet batch transcription on demand, and supervises a WhisperLiveKit child process for live captions. Nothing leaves the machine.

Audio arrives via a bridge — usually a browser extension that taps the meeting platform's audio tracks and streams raw PCM to the /tap WebSocket. The included bridges/spacialchat-bridge/ targets spatial.chat; see bridges/README.md for the wire protocol.

Beyond record + transcribe: a hallucination filter (substring / exact: / re: rules; suppressed segments kept in an audit array), silence-stripping (trimmed copies in <session>/stripped/, originals untouched), summarization (bundled local model, operator CLI, or an OpenAI-compatible API), a People registry (cross-session speaker identity → display name, with merge/detach), and an end-of-meeting pipeline (strip → transcribe → summarize as one job a Bridge can trigger and poll with the tap token — no operator in the loop). CONTEXT.md has the domain model.

Dashboard

One operator console at / — the "Stages" UI. A slim left spine navigates the global views (Taps · Sessions · People · Settings) and the per-session journey (Capture → Recordings → Transcript → Summary); the active-taps rail follows you across views. Live captions stream in Capture; silence-stripping and the per-WAV files live in Recordings; the ▶ transcribe range button, the meeting-languages declaration (ADR-0011), and the merged transcript live in Transcript; the live and batch engine pickers live in Settings.

Merged session transcript

Captured live by the browser E2E test: the Apollo 11 fixture through the bridge and a real faster-whisper tiny.en. Bigger models clean up the self-flagged low-confidence output considerably.

Quick start (macOS / Linux)

bash start.sh             # localhost only
bash start.sh --lan       # bind 0.0.0.0

The script finds Python 3.12+, creates .venv, base-installs the package, and launches the recorder on port 8001. Pick transcription models in the browser at http://localhost:8001/setup (/ redirects there until a model is installed); /setup doubles as the manage-models surface. Other flags: --non-interactive (headless — install the saved/default model selection without the browser), --no-mlx (skip MLX on Apple Silicon; live and batch both use MLX there by default), --auto-live (boot with live captions running), --tls, --no-auth (dev only).

Live captions are off by default: start whisperlivekit-server from the dashboard. The recorder supervises it as a child on an ephemeral internal port (pin one with SX_PORT_WLK); child logs are prefixed [wlk]. Ctrl+C stops the recorder and any child.

On first run two secrets are generated and printed:

  • a dashboard password for HTTP Basic auth, persisted to .auth-password;
  • a /tap bearer token for bridges, persisted to .tap-token — paste it into the bridge popup along with host and port.

Rotate with .venv/bin/tapscribe --rotate-password / --rotate-tap-token. start.sh --tls serves https:// + wss:// with a self-signed cert generated on first boot (.tapscribe-cert.pem, .tapscribe-key.pem) and reused after; to supply your own, run tapscribe directly with --tls --cert <path> --key <path> (recorder flags, not start.sh flags).

Windows

Windows Bundle (no Python needed)

Download TapScribe-Setup-win-x64.exe from the latest release and run it. Per-user install (no admin prompt), carries its own interpreter; a tray icon starts the dashboard and its Copy password item gives you the generated login. The Bundle is unsigned, so SmartScreen warns — click More info → Run anyway. Program files land in %LOCALAPPDATA%\Programs\TapScribe; recordings, transcripts and settings live in %USERPROFILE%\TapScribe and survive uninstall; model weights cache in %USERPROFILE%\.cache\huggingface. See packaging/README.md and ADR-0015.

From a checkout (developers)

.\start.ps1        # flags mirror start.sh: -Lan, -NoMlx, -AutoLive, -Tls, -NonInteractive

Other installs

  • PyPI: pip install tapscribe, then tapscribe. Models still install via /setup.
  • Docker (CPU-only): docker run --rm -it -p 8001:8001 -v "$PWD/data:/data" ghcr.io/vortiago/tapscribe:latest

Configuration

Editable config files live under config/ and are re-read on every job; all are editable from the dashboard's Settings view (further knobs — chunk sizes, timeouts, model idle TTL — live under Settings → Advanced).

File Shapes
config/prompt.txt / live-prompt.txt Batch initial_prompt / live --init-prompt (independent). Prose under ~150 words.
config/hotwords.txt Batch hotwords — proper nouns; faster-whisper only.
config/hallucinations.txt Suppression rules: substring, exact:, or re:. Ships with common YouTube-trained Whisper hallucinations.
config/batch-model.txt / live-model.txt Default batch / live model ids.
config/languages.txt Candidate languages (ADR-0010); default da,no,en.
config/summarizer.json Default summarizer (source, command/model/base_url, prompt; api_key write-only).

Architecture

One backend, one supervised child, N bridges. Audio flows in over WebSocket; captions and recordings come out.

flowchart LR
    subgraph Meeting["Meeting platform (e.g. spatial.chat)"]
        Bridge["Bridge<br/>(browser extension<br/>or native helper)"]
    end

    subgraph Host["TapScribe host"]
        Backend["TapScribe backend<br/>FastAPI :8001<br/>/tap · /api · dashboard"]
        WLK["whisperlivekit-server<br/>(supervised child, internal port)"]
        WAVs[("recordings/<br/>&lt;session&gt;/*.wav")]
    end

    Operator["Operator browser<br/>(dashboard)"]

    Bridge -- "PCM 16k mono<br/>over WS /tap" --> Backend
    Backend -- "forwards PCM" --> WLK
    WLK -- "settled live captions" --> Backend
    Backend -- "one WAV per utterance" --> WAVs
    Operator <-- "HTTPS (500 ms /api/state poll)" --> Backend

One /tap WebSocket = one utterance. Each PCM frame is tee'd: appended to the per-utterance WAV on disk and relayed to the WhisperLiveKit child for live captions. The two sinks are independent — if WhisperLiveKit is down, recording still works. Bridges never talk to the child directly.

Backends

Family Models Backend Languages Notes
Whisper tiny(.en)/base(.en)/small(.en)/medium(.en), large-v3, large-v3-turbo mlx-whisper (AS) / faster-whisper English-only suffixes; else multilingual large-v3-turbo is the default generalist (ADR-0010).
NB-Whisper nb-whisper-tiny/base/small/medium/large faster-whisper on CT2 weights Norwegian Pulled from NbAiLab/nb-whisper-*/ct2/. No MLX.
Voxtral voxtral-mini mlx-voxtral (AS) / HF transformers EN/ES/FR/PT/HI/DE/NL/IT Batch-only. First load downloads ~6 GB.
Parakeet parakeet-tdt-0.6b-v3 parakeet-mlx (AS) / HF transformers 25 EU languages, no Norwegian Batch-only; replaced Canary (ADR-0006).
Moonshine moonshine-tiny/base mlx-audio (AS) / ONNX-CPU English Live-only low-latency captions. Extras [moonshine-mlx] / [moonshine-cpu].

Tests

pip install -e ".[dev]"
python -m pytest -q

Unit + route tests (backends stubbed, under 20 s), an HTTP pipeline E2E over real /tap WebSockets, a real-Whisper E2E on committed CC-licensed fixtures, a Playwright dashboard-UI E2E, and a headed bridge-extension E2E. See CONTRIBUTING.md for how to run each layer. GitHub Actions runs the suite and ruff on every push and PR across Python 3.12-3.14 on Ubuntu, macOS, and Windows.

License

MIT. See LICENSE.

Download files

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

Source Distribution

tapscribe-1.3.0.tar.gz (3.2 MB view details)

Uploaded Source

Built Distribution

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

tapscribe-1.3.0-py3-none-any.whl (2.8 MB view details)

Uploaded Python 3

File details

Details for the file tapscribe-1.3.0.tar.gz.

File metadata

  • Download URL: tapscribe-1.3.0.tar.gz
  • Upload date:
  • Size: 3.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tapscribe-1.3.0.tar.gz
Algorithm Hash digest
SHA256 4d7989248732161a447c9e1019fce32cc45245287e7a5779a74abe6647685f08
MD5 b849cd7ecde353110b01c8346aaaf68a
BLAKE2b-256 bd2078729bf0e69d4a7a69f047807bfc987d8311e53d59695c3ec1253a783914

See more details on using hashes here.

Provenance

The following attestation bundles were made for tapscribe-1.3.0.tar.gz:

Publisher: release.yml on Vortiago/TapScribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tapscribe-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: tapscribe-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 2.8 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for tapscribe-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 442465590870eb2f4393fee63d39b730ac28a65bb4b2381378e3f8637fa7ad88
MD5 3e780aa8aac566300570476bf16fa74f
BLAKE2b-256 52fc3cacbf660c0e6b2961ba18455359ae6e99e91477c2fdf9ddc8cf43b44ea1

See more details on using hashes here.

Provenance

The following attestation bundles were made for tapscribe-1.3.0-py3-none-any.whl:

Publisher: release.yml on Vortiago/TapScribe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 files

1.2.0

2 files

1.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page