Your invisible AI meeting assistant β Live captions and smart summaries, right in your browser.
Quick Start β’ How It Works β’ Features β’ API
ghostmeet silently captures audio from any browser tab β Google Meet, Zoom, Teams, or anything with sound β and transcribes it in real-time using Whisper. When the meeting ends, click Summarize and AI extracts key decisions, action items, and next steps.
It runs as a Chrome Extension side panel. Other participants can't see it. Like a ghost in your meeting. π»
- 100% local β audio never leaves your machine
- No accounts β no sign-up, no cloud, no subscriptions
- Works everywhere β any tab that plays audio
- ποΈ Real-time transcription β Whisper STT, updates every 10 seconds
- β±οΈ Built for long meetings β cost per pass stays flat, so a 4-hour session behaves like a 4-minute one
- π AI-powered summaries β Key decisions, action items, next steps
- πΎ Nothing is lost β transcripts are written to SQLite as they happen and survive a restart
- π Per-meeting language β pick the language in the side panel, or let Whisper detect it
- π Self-hosted β your audio stays on your machine, and the server listens on loopback only
- π³ One-command setup β
docker compose upand you're ready - π» Invisible β side panel UI, no one in the meeting knows
Browser Tab (Zoom / Meet / Teams)
β audio
βΌ
Chrome Extension
βββ service worker β asks Chrome for a tab stream id
βββ offscreen page β records it, and plays it back so you still hear the meeting
β
βΌ WebSocket (webm/opus, 1s chunks)
Local Backend (FastAPI)
βββ one demuxer per session βββ PCM appended to disk
βββ Whisper reads only the newest window, never the whole recording
βββ segments βββ SQLite + live captions in the side panel
βββ Claude API (on demand) βββ Meeting Summary
Everything runs on your machine. The only external call is to Claude API when you click Summarize (optional β transcription works without it).
Audio is decoded once as it arrives and kept on disk, and each transcription pass reads only a bounded window of it. That is what keeps a long meeting from getting slower and slower, and keeps memory flat no matter how long you record.
- Docker (recommended) or Python 3.10+
- Chrome browser
git clone https://github.com/Higangssh/ghostmeet.git
cd ghostmeet
# Copy and edit config (add your Anthropic API key for summaries)
cp .env.example .env
# Start with Docker
docker compose up -dBackend is ready when you see http://0.0.0.0:8877 in the logs.
Manual install (without Docker)
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python -m backendNote: First run downloads the Whisper model (~150MB for base).
- Open chrome://extensions in Chrome
- Enable Developer mode (toggle in top-right)
- Click Load unpacked
- Select the
extension/folder from this repo - Pin the π» icon in your toolbar
- Join a meeting β Open Google Meet, Zoom, Teams (or any tab with audio)
- Click π» β Side panel opens on the right
- Pick a language (optional) β or leave it on Auto-detect
- Click βΆ Start β Live captions appear as people speak. The tab stays audible.
- Click β Stop β The panel says "Transcription complete" once the last pass finishes
- Click π Summarize β AI generates a structured summary
Reopening the side panel mid-meeting brings the transcript so far back with it.
That's it. No sign-up, no config, no cloud.
Set these in .env or docker-compose.yml:
| Variable | Default | Description |
|---|---|---|
GHOSTMEET_MODEL |
base |
Whisper model size (tiny / base / small / medium / large) |
GHOSTMEET_DEVICE |
auto |
Compute device (auto / cpu / cuda) |
GHOSTMEET_COMPUTE_TYPE |
float32 |
Precision (int8 is much faster on CPU) |
GHOSTMEET_LANGUAGE |
auto-detect | Default language (en / ko / ja / etc.) β the side panel can override it per meeting |
GHOSTMEET_CHUNK_INTERVAL |
10 |
Seconds between transcription updates |
GHOSTMEET_ANTHROPIC_KEY |
β | Required for AI summaries |
GHOSTMEET_HOST |
127.0.0.1 |
Server bind address (loopback β the API has no auth) |
GHOSTMEET_PORT |
8877 |
Server port |
Model size guide:
tinyβ fastest, least accurate (~75MB)baseβ good balance (recommended, ~150MB)smallβ better accuracy, slower (~500MB)medium/largeβ best accuracy, needs GPU
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check + model info |
/api/sessions |
GET | List all sessions |
/api/sessions/{id} |
GET | Session details |
/api/sessions/{id}/transcript |
GET | Full transcript |
/api/sessions/{id}/summarize |
POST | Generate AI summary |
/api/sessions/{id}/summary |
GET | Get generated summary |
/ws/audio |
WS | Audio ingest (binary chunks; send stop as text to finish) |
/ws/transcript/{id} |
WS | Live transcript stream |
Sessions, transcripts and summaries are stored in recordings/ghostmeet.db, so every
endpoint above keeps working after the backend restarts.
python -m venv .venv
./.venv/Scripts/python.exe -m pip install -r requirements-dev.txt
./.venv/Scripts/python.exe -m pytest tests/ -q # backend suite
node --test tests/extension/shared.test.mjs # extension helpersThe suite needs no Whisper model and no network β real opus audio goes through the real decoder, and only inference is stubbed.
There is one thing tests cannot reach: chrome.tabCapture.getMediaStreamId() needs the
activeTab grant that only a real toolbar click produces. Everything after that point is
covered by node tests/extension/verify-capture.mjs, which drives the extension in a real
browser against a running backend (needs npm install playwright && npx playwright install chromium). To check the last step by hand: start a capture on a tab with audio and confirm
audio_bytes climbs in /api/sessions β and that you can still hear the tab.
ghostmeet/
βββ extension/ # Chrome MV3 Extension
β βββ manifest.json # permissions + side panel config
β βββ background.js # service worker: gets a tab stream id, drives capture
β βββ offscreen.html/js # hidden page that actually records β WebSocket
β βββ sidepanel.html/js # live captions, language picker, summaries
β βββ popup.html/js # start/stop controls
β βββ shared.js # pure helpers shared by the above
β βββ icons/
βββ backend/ # Python backend (FastAPI)
β βββ app.py # HTTP + WebSocket server
β βββ decoder.py # streaming webm/opus β PCM (one demuxer per session)
β βββ pcm_store.py # append-only audio on disk, windowed reads
β βββ incremental.py # bounded-window transcription, absolute timestamps
β βββ pipeline.py # receive / decode / transcribe, decoupled
β βββ transcriber.py # shared Whisper model + per-session language
β βββ store.py # SQLite: sessions, segments, summaries
β βββ summarizer.py # Claude API integration
β βββ models.py # session model
βββ tests/ # pytest suite + extension tests
βββ assets/ # logo, demo GIF
βββ docker-compose.yml # one-command deployment
βββ Dockerfile # backend container
βββ requirements.txt # Python dependencies
ghostmeet works as an OpenClaw skill. Control your meetings from chat.
# Install the skill
clawhub install ghostmeetThen just ask your AI assistant:
- "Summarize my last meeting" β generates AI summary from latest session
- "How many meetings did I have today?" β lists all sessions
- "What was discussed?" β fetches full transcript
- "Extract action items" β pulls tasks from the summary
The skill handles session listing, transcript retrieval, and summary generation via the ghostmeet API. Recording start/stop is done through the Chrome Extension.
- Real-time transcription (Whisper)
- Chrome Extension side panel UI
- AI meeting summaries (Claude)
- Long meetings β flat cost per pass, tested to 4h+ of audio
- Transcripts survive a restart (SQLite)
- Per-session language selection
- Meeting context input + file attach
- Speaker diarization (who said what)
- In-person meetings (microphone capture)
- Export to Markdown / PDF
- Agent Mode β AI speaks in the meeting for you

