TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
자체 서버에서 동작하는 오픈소스 회의 비서 Corella, 통화 녹음·전사·요약을 실시간 AI가 지원
Corella — a self-hosted meeting assistant. Records, transcribes, and summarizes your calls with a live AI copilot, running entirely on your own servers. Open source, Apache 2.0.
생산성Python · TypeScriptGitHub @lucas-oma온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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.