TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Self-hosted meeting assistant: live transcription, speaker diarization, AI copilot, live feedback and suggestions, and post-call coaching reports 🧠 runs on your own Docker stack.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A self-hosted meeting assistant: it records a call from your browser (or takes an upload), transcribes and speaker-labels it, keeps a live AI copilot grounded in your own documents, and turns the call into a searchable transcript plus a post-call summary and coaching report. Runs entirely on your own Linux box via Docker Compose — your own database, your own vector store, and (optionally) your own local LLM, with no required cloud dependency beyond whichever hosted LLM/STT provider you choose to connect.檢視完整 README ↗A self-hosted meeting assistant: it records a call from your browser (or takes an upload), transcribes and speaker-labels it, keeps a live AI copilot grounded in your own documents, and turns the call into a searchable transcript plus a post-call summary and coaching report. Runs entirely on your own Linux box via Docker Compose — your own database, your own vector store, and (optionally) your own local LLM, with no required cloud dependency beyond whichever hosted LLM/STT provider you choose to connect.
.caf) for the same pipeline, offline.faster-whisper by default (zero config), or Deepgram if you connect an API key — per-user, per-provider model overrides available in Settings.{Name} Org with you as owner; closed mode uses one instance org. Groups nest inside an org. Owner/admin/member are org roles; super_admin is an instance flag.API.md. A website can use packages/corella-live instead of speaking the WebSocket protocol by hand.flowchart TB
Browser["Browser\n(mic + tab audio)"] --> Web["web\nReact SPA (nginx)"]
Web -->|"REST + WebSocket"| API["api\nFastAPI"]
API --> Postgres[("postgres")]
API --> Redis[("redis\nqueue + pub/sub")]
Redis --> Worker["worker\nCelery: full diarize()\npipeline, embeddings"]
Worker --> Qdrant[("qdrant\nvector search\n(knowledge base +\nmeeting search)")]
faster-whisper directly for live transcription (torch-free, light enough for this process), and also loads pyannote.audio's speaker-embedding model directly (not gated, unlike the full diarization pipeline below) for the instant "does this match an already-confirmed voice" check on the hot live-recognition path — no worker round-trip for that. When a session's STT is Deepgram, its own native diarization (word-level speaker index) drives live same-room/same-tab speaker splitting entirely in this process too, with zero worker involvement while that stream stays healthy. Everything else torch-dependent (the full diarize() pipeline, offline transcription's diarize step) stays worker-only.diarize()-pipeline reconciliation pass live sessions use when their STT isn't Deepgram (or as a fallback if a Deepgram stream drops), voice-identity matching, knowledge-base/meeting-search embedding, report generation, and voice enrollment — so none of it blocks the API process or the live WebSocket loop.The copilot LLM and the speech-to-text engine are each pluggable per user: a per-user saved key takes priority, then an instance-wide .env fallback, then — for STT only — local faster-whisper, which needs no key at all. See BRANDING.md for the UI's visual language if you're touching web/, or docs/AUDIO_PIPELINE.md for a detailed look at the transcription/live-streaming/speaker-diarization pipeline — including the full decision flow and the real bugs that shaped it — if you're touching app/services/vad/, app/services/diarization/, app/services/asr/, app/ws/live_session.py, or app/workers/tasks.py.
| Backend | Python, FastAPI, SQLAlchemy 2 (async) + Alembic, Celery |
| Speech/ML | faster-whisper, Deepgram (optional), pyannote.audio (diarization + speaker embeddings), sentence-transformers / fastembed (KB + meeting search embeddings) |
| LLM clients | Hand-rolled httpx clients for Anthropic, OpenAI, Gemini, Ollama — no SDK dependency |
| Data | PostgreSQL, Qdrant (vectors), Redis (broker + pub/sub) |
| Frontend | React, TypeScript, Vite, Tailwind CSS, react-router |
| Infra | Docker Compose (CPU-first; optional NVIDIA override) |
corella/
server/
app/
api/ REST routers — auth, meetings, kb, settings, organizations, admin
ws/ WebSocket live-session handler
core/ config, security (JWT + secret encryption), db sessions
models/ SQLAlchemy models
schemas/ Pydantic request/response schemas
services/
asr/ faster-whisper + Deepgram clients, provider resolution
diarization/ pyannote.audio wrapper, online speaker clustering
alignment/ merges ASR output + diarization into labeled utterances
llm/ provider clients (anthropic/openai/gemini/ollama) + resolution
embeddings/ sentence-transformers/fastembed + Qdrant collections
copilot/ live suggestions, post-call report generation
admin/ cost-analytics aggregation
audio/ WAV I/O, channel mixing/windowing
vad/ speech/silence utterance detection
workers/ Celery task definitions
main.py
alembic/ DB migrations
web/
src/
routes/ one file per screen (Dashboard, Organization, Invite, Super admin, …)
components/ shared UI (AppShell, …)
lib/ typed API client, live-session WS client, auth context
public/
docker-compose.yml CPU-first stack
docker-compose.gpu.yml optional NVIDIA runtime override
.env.example
BRANDING.md UI visual language + component conventions
VERSIONING.md three-digit version guide — when to bump what
docs/
AUDIO_PIPELINE.md transcription/live-streaming/diarization deep dive
packages/
corella-live/ npm client for the live recording API
cp .env.example .env # fill in JWT_SECRET at minimum
docker compose up --build
WEB_PORT)API_PORT; docs at /docs)If you have an NVIDIA GPU + the NVIDIA Container Toolkit installed, layer on the GPU override for faster/larger transcription and diarization models:
docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build
docker compose build api worker web
docker compose up -d api worker web
Migrations run automatically on api startup. postgres/redis/qdrant don't need rebuilding for an app-code change.
See .env.example for the full, documented list. Highlights:
JWT_SECRET (required), CORS_ORIGINS, ENVIRONMENT, API_PORT / WEB_PORT (host-side published ports in docker-compose.yml, default 8090 / 8080), PUBLIC_APP_URL (identifies this instance in pre/post call-type API hooks — see API access; must match the web origin). Changing API_PORT without setting PUBLIC_API_URL is enough — the web image defaults to http://localhost:${API_PORT}. Changing WEB_PORT means updating CORS_ORIGINS and PUBLIC_APP_URL to the new origin.ALLOW_PUBLIC_REGISTRATION, MAX_ORGS_PER_USER, INVITE_EXPIRE_DAYS, optional RESEND_API_KEY / RESEND_FROM_EMAIL (email the invite link; copy-link still works without them), ADMIN_EMAIL/ADMIN_PASSWORD (bootstrap super_admin, see Access control below).DATABASE_URL, REDIS_URL, QDRANT_URL — defaults match docker-compose.yml's service names, only change these if you're pointing at externally-hosted stores.HF_TOKEN (diarization, see below), WHISPER_MODEL/WHISPER_COMPUTE_TYPE, optional DEEPGRAM_API_KEY/DEFAULT_MODEL_DEEPGRAM.AUDIO_STORAGE_PATH/MAX_AUDIO_UPLOAD_MB, KB_STORAGE_PATH/MAX_KB_UPLOAD_MB, EMBEDDING_MODEL.ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, OLLAMA_BASE_URL.Every credential (LLM and STT alike) follows the same precedence: the signed-in user's own saved key first, then the instance-wide .env value, and — for speech-to-text specifically — local faster-whisper as a final, always-available fallback that needs no key at all. A user can also pin an explicit provider/model/language override in Settings instead of relying on that automatic priority order.
Speaker diarization uses a gated pyannote.audio pipeline. A valid HF_TOKEN alone isn't enough — the Hugging Face account behind it must also individually accept the terms on each gated model page the pipeline depends on internally (a separate, one-time click-through per repo):
Skipping this doesn't break anything — transcription still works fine and the meeting still finishes, just without speaker labels for uploaded/offline recordings; the pipeline just fails per-file with a clear error in the worker logs instead of loading. Live, same-room/same-tab speaker splitting during a local-whisper (or Deepgram-dropped-mid-session) recording depends on this same gated pipeline for its periodic full diarization pass, so it's subject to the same requirement — a session without HF_TOKEN just skips live labeling there and keeps showing "Me"/"Them". (The instant per-segment recognition check uses pyannote/wespeaker-voxceleb-resnet34-LM, a separate, non-gated model — it works with no HF_TOKEN at all, it just has nothing to recognize against until the gated pipeline has labeled at least one speaker.)
Deepgram STT sidesteps all of the above for live diarization. When a session's speech-to-text is Deepgram (a connected key, per-user or instance-wide), same-room/same-tab speaker splitting uses Deepgram's own native diarization instead — no HF_TOKEN, no gated models, no worker involvement at all for that path. The tradeoff: Deepgram's speaker index is local to that one connection, so it doesn't feed Corella's cross-meeting/group voice-identity recognition (enrollment/name-spotting) the way the pyannote-embedding path does — a session on Deepgram gets instant "Speaker 1"/"Speaker 2" labels, but not recognized-by-name identities, this round.
Two ways to get a meeting transcribed, both going through the same pipeline downstream:
.caf), which is transcribed — and, if HF_TOKEN's terms are accepted, speaker-diarized — in the background. The meeting page polls and updates itself as processing finishes, and a summary report generates automatically once it's ready.Speech-to-text uses whichever engine is currently resolved for the recording user (Deepgram if configured, else local) — see Configuration above for the precedence, or Settings' "AI models in use" panel to see and change what's active.
Two deployment modes (ALLOW_PUBLIC_REGISTRATION, plus MAX_ORGS_PER_USER, default 1):
true): signup creates {full_name} Org and the user is its owner. They may create more orgs up to MAX_ORGS_PER_USER (counts owned orgs, not memberships) and invite others.false): no self-serve signup and no self-serve org create. Set ADMIN_EMAIL / ADMIN_PASSWORD — that account is created on first startup as super_admin and owner of one instance org (is_instance_org). Admin-created or invited users join that org as members and do not get a personal org.Flipping the flag later does not merge or split orgs; it only changes whether new signups and org-creates are allowed. ADMIN_EMAIL/ADMIN_PASSWORD only ever create the bootstrap account — changing them later and restarting won't touch an existing password.
Roles are two enums, never one:
User.is_super_admin — instance operator. Bootstrap account, and anyone a super admin promotes. Powers: Super admin console, cross-org support read (GET /api/meetings/all and /search/all), promote/demote super admins. Not implied by creating an org.OrganizationMembership.role — owner | admin | member.
The web app picks the active org (PUT /api/organizations/current); every browser request runs in that org. API keys do not switch — each key is bound to one org at creation.
Invites are copy-link tokens (INVITE_EXPIRE_DAYS, default 7). If RESEND_API_KEY and RESEND_FROM_EMAIL are set, creating or resending an invite also emails that link; a Resend failure is logged and the invite still works. Accepting works even when public registration is closed. A new email creates an account and joins that org (no auto-created personal org); an existing account adds a membership.
Writes (delete meeting, report, action-item edits) stay owner-only. Org owner/admin get today's instance-admin powers inside the active org (org-wide meeting list, full read, KB upload/delete, call types, secrets, org cost dashboard).
Corella can be integrated with an external system in three ways — full reference (auth, REST/WebSocket shapes, hook payloads, examples) in API.md. For a website that should stream a live conversation, use packages/corella-live (npm install corella-live) so you do not reimplement the WebSocket quirks (speaker labels in particular).
The three types:
X-Corella-App-Url, X-Corella-Meeting-Id, X-Corella-User-Id, X-Corella-Org-Id) that can't be overridden by custom header config.The UI follows a deliberate, documented visual language — see BRANDING.md for the full color/type/component reference before making frontend changes. In short: near-white/charcoal surfaces, a single navy accent, a serif for headlines only, border-first cards with minimal shadow.
Contributing? See CONTRIBUTING.md for setup, this project's conventions (credential handling, migrations, adding a new LLM/STT provider), and what a good PR looks like here — and VERSIONING.md for which digit to bump on a main → release cut.
Backend:
cd server
pip install -e ".[worker]"
alembic upgrade head
uvicorn app.main:app --reload
Frontend:
cd web
npm install
npm run dev
Type-check and build the frontend before committing:
cd web
npx tsc -b && npx vite build
A backend pytest suite (server/tests/) covers the highest-value logic — permission boundaries, credential/provider resolution, webhook templating, pricing math — not every endpoint; growing it is a welcome contribution. ruff and pytest are both required checks on any PR into main/release, and ruff alone runs on every push for fast feedback (.github/workflows/). Frontend correctness is still tsc -b + vite build, no component-test suite yet. Beyond what's covered by these, changes are verified by hand against a real, isolated Docker stack (see CONTRIBUTING.md and any recent commit message for the pattern) — several real bugs in this project's history were only ever caught that way, not by a unit test.
Actively developed. Done so far: organizations with owner/admin/member plus instance super_admin, copy-link invites, auth (open signup creates {Name} Org; closed mode uses one instance org), upload and live in-browser recording with speaker-labeled transcripts, pluggable LLM copilot (live suggestions/blockers/action items/coach score) and pluggable STT (local or Deepgram), knowledge-base ingestion and semantic meeting search, auto-generated post-call reports (summary/topics/sentiment/quotes/coach score) tuned by org-scoped call type, org-scoped voice recognition with live LLM name-spotting, live same-room and same-tab speaker separation, organization settings (people/groups/invites/secrets/call types/costs) plus a super-admin console, and per-call cost tracking against a real usage ledger.
Not yet built: post-call "polish" re-transcription with a larger model.
To report a vulnerability, see SECURITY.md. Do not open a public issue.