Meeting notes that never leave your machine. No backend, no account, no upload.
A private AI meeting notetaker that runs entirely in your browser. Open a tab, hit record, and it transcribes in real time, figures out who said what, and pulls out decisions, action items, key points, and open questions as they happen, all on-device, using speech and language models that run locally on your CPU and GPU. Nothing is ever sent to a server.
Top-5 Global Demo at AI Tinkerers.
▶ Try it now: silentnotetaker.com · nothing to install, runs entirely in your browser. Use Chrome or Edge; the first load downloads the models (a few hundred MB) into a browser-managed local cache, so give it a minute on the first visit. The browser may still evict that cache under storage pressure.
Every mainstream AI notetaker works the same way: it joins your call, streams your audio to someone else's servers, runs the AI there, and sends a summary back. The good ones are careful: encryption, SOC 2, "we delete the audio after transcription." Even the privacy-marketed ones (Granola, for example) still send your meeting to cloud LLMs and store it on their infrastructure. Their privacy is a promise, backed by a company.
Silent Notetaker makes the promise structurally unnecessary. The audio is captured, fed to the models, and consumed in-process. It is never serialized into a network request. This is privacy by architecture, not by policy, and you can verify it: open your browser's network panel and watch. The only things the app ever fetches are JavaScript runtimes and model weights (downloaded once, then cached). A Content-Security-Policy connect-src allowlist, enforced and not report-only, makes the browser itself refuse any connection outside that set.
There are whole categories of conversation (legal, medical, hiring, finance, M&A, journalism with sources) where "the audio left the building" is a non-starter. This is built for those.
- Live transcription: streaming speech-to-text as you talk.
- Speaker identification: labels each line by speaker (
S1,S2, …) using on-device voice embeddings. Click any tag to rename a speaker; the name propagates everywhere. - Automatic note extraction: sorts the conversation in real time into Decisions, Action Items, Key Points, and Open Questions.
- Live meeting outline & smart questions: a small on-device LLM builds an outline as you go and suggests a sharp question worth asking right now.
- Slide / screen capture: optionally grab tab audio and screenshots of shared slides.
- Local-first storage: every meeting is saved on your device. Nothing is uploaded.
- Clean export: copy the whole meeting as structured Markdown.
- Optional Claude bridge: connect to Claude for sharper summaries via a local server you run. Entirely optional; the app is fully functional without it.
The whole pipeline runs client-side, in your browser:
🎤 Microphone
│
▼
AudioWorklet @ 16 kHz mono
│ Float32 PCM
├───────────────────────┬───────────────────────────┐
▼ ▼ ▼
Nemotron ASR TitaNet diarization Qwen3 notes / outline
(CPU / WASM, (CPU / WASM, (CPU / WASM live,
streaming) speaker embeddings) WebGPU recap)
│ text │ speaker id │
└───────────┬───────────┘ │
▼ ▼
Note extraction (Rust) ───────────────▶ UI + local storage
(Rust/WASM, on-device)
(optional) ⇄ Claude bridge (ws://localhost:8765, a server you run)
The design splits work across silicon so nothing contends: the default ASR (Nemotron streaming) runs on CPU/WASM, which leaves the GPU free for on-device Qwen to generate notes and questions. Heavier engines like Voxtral take the GPU when selected. The application policy (engine selection, diarization, note triggers, question scheduling, storage, the recording state machine) is written in Rust, compiled to WebAssembly, driving a thin HTML/JS shell.
Requirements: Chrome or Edge (most complete WebGPU support), a microphone, and a few hundred MB of free disk for the first-run model cache.
Fastest, just open it: silentnotetaker.com. Same app, hosted on Cloudflare Pages with the cross-origin-isolation headers already set. Nothing is uploaded. The page only fetches JS runtimes and model weights (see Privacy statement). The first visit downloads the selected model; the large weights (the Nemotron encoder is ~880 MB) are then persisted on-device in the browser's private file system (OPFS), keyed to the pinned model revision, so repeat visits skip the download entirely and the app works offline. It's purely a local cache, and bumping the model pin auto-invalidates the old copy.
Run it locally (full source, same behavior):
git clone https://github.com/MikeSchirtzinger/silent-notetaker.git
cd silent-notetaker
./start.shstart.sh launches a local server with the right headers and opens the app at http://localhost:8080. Pick an engine, click Start, allow the mic, and talk. The first run downloads the selected model from Hugging Face and caches it on-device in the browser's private storage (OPFS), keyed to the model revision, so everyday repeat runs skip the download and work offline (bumping the pin re-fetches).
Why a server and not just opening the file? The on-device models use multithreaded WebAssembly, which the browser only enables when the page is "cross-origin isolated" (it needs
SharedArrayBuffer). That requires two HTTP headers (COOP+COEP) you can't set from afile://URL.start.shruns a tiny server that sends them: a Rust (axum) one if you havecargo, otherwise a dependency-free Python fallback (coi-server.py). A plainpython -m http.serverwill load the app but run single-threaded and several times slower.
Building the WebAssembly modules (only needed if you change the Rust crates):
./scripts/build-wasm.shThe app is fully static and deploys to Cloudflare Pages (the _headers file carries the isolation + CSP headers). There is no backend to deploy.
The UI shell (markup, styles, engine loaders, the inlined transcription worker) lives in index.html and a handful of small ES modules (nemotron-engine.js, diarization-engine.js, storage-engine.js, …). The application policy lives in Rust crates under crates/, compiled to WebAssembly:
| Crate | Responsibility |
|---|---|
silent-core |
Shared contracts, session state machine, exporters |
nemotron-asr |
Cache-aware RNN-T streaming ASR (native + wasm32) |
silent-diarization |
TitaNet speaker embeddings + speaker tracking |
silent-notes |
Note trigger extraction + Qwen smart-question scheduling |
silent-storage |
On-device storage schema + migrations |
silent-inference |
JS-host dispatch plus bounded streaming/backlog policy |
silent-audio |
Audio chunking policy |
silent-extension-sdk |
Sandboxed extension permission model |
silent-web |
The wasm-bindgen boundary that exposes all of the above to the UI |
Each ES-module engine loader is a thin wrapper that delegates every policy decision to its corresponding wasm surface. Full design notes, the complete network trust boundary, and the roadmap are in docs/ARCHITECTURE.md.
Everything runs client-side. The transcription engine is selectable in the UI.
| Role | Model | Runs on |
|---|---|---|
| Streaming ASR (default) | Nemotron streaming 0.6B (NVIDIA) | CPU / WASM |
| Streaming ASR (premium) | Voxtral Realtime 4B (Mistral) | WebGPU |
| Lightweight ASR | SenseVoice (FunAudioLLM), Moonshine (Useful Sensors) | WASM / WebGPU |
| ASR (familiar baseline) | Whisper large-v3-turbo / small / base (OpenAI) | WebGPU |
| Speaker embeddings | TitaNet-small (NVIDIA NeMo) | WASM (onnxruntime-web) |
| Notes & smart questions | Qwen3 0.6B / 1.7B (Alibaba) | WASM (live) + WebGPU (recap) |
Models are pulled from Hugging Face at runtime and cached locally.
Rust · WebAssembly · WebGPU · onnxruntime-web · Transformers.js · axum · vanilla JS (no framework, no bundler) · Cloudflare Pages
Audio is captured, turned into model inputs, and consumed on-device. It is never written to a network request. If Nemotron falls behind, bounded PCM segments may temporarily enter the browser's origin-private local storage and are deleted after use or stop. There is no analytics endpoint, no telemetry host, and no crash-reporting origin in the codebase. The complete list of origins the app can contact is the CSP connect-src allowlist (Hugging Face for weights, two CDNs for runtimes, and the optional localhost Claude bridge), generated from registry/models.toml and enforced by the browser. See docs/ARCHITECTURE.md for the full trust boundary.
See CONTRIBUTING.md. The core notetaker (capture, transcription, speaker ID, note extraction, smart questions, local storage) is free and stays free, and the source stays auditable.
- Brevity Meet: Brevity's agentic meeting infrastructure.
- brevity.ventures: what Brevity is building.
Code is MIT. Bundled and downloaded models retain their own upstream licenses. Models by NVIDIA, Mistral AI, OpenAI, Alibaba, FunAudioLLM, and Useful Sensors.
Built by Brevity Ventures. We build private, on-device AI.