English · Português · Live demo · Contributing
Open-source white-label videoconferencing — your brand on every room, self-hosted LiveKit SFU, live captions, and an AI copilot that turns meetings into summaries and outbound webhooks.
Public branch: clone and follow
release(default).mainanddevare protected integration branches.
- True white-label — logo, palette, typography, and CSS tokens per room
- Self-hosted media — LiveKit SFU on your infrastructure, no seat tax
- Meeting recording — browser or LiveKit Egress; local disk or S3-compatible
- AI that closes the loop — live STT + post-meeting summary + tasks via webhooks / external tools
- Auth modes — local accounts and optional OIDC;
DEPLOYMENT_MODE=server|platform - Multilingual UI — English, Português, Español, Français, Deutsch (
messages/*.json) - Browser-only — WebRTC, no plugins
- Next.js 15 (App Router) on port
3332 - LiveKit SFU — signaling, media, TURN
- Postgres + Drizzle ORM
- Python copilot — LiveKit Agents + Deepgram
git clone https://github.com/IrvingSamuel/openmeet.git
cd openmeet
cp .env.example .env # fill in secrets
cd infra && docker compose up -d && cd ..
npm install
npm run db:push
npm run build
# or: npm run devOptional agent (needs DEEPGRAM_API_KEY):
cd agent
python3 -m venv venv
./venv/bin/pip install -r requirements.txt| Variable | Purpose |
|---|---|
DEPLOYMENT_MODE |
server (self-host) or platform |
ALLOW_SIGNUP |
Allow local email/password registration |
OIDC_* |
Optional OIDC issuer / client for SSO |
Local auth works out of the box; OIDC is optional for enterprise SSO.
Enable in /admin → Recording:
| Setting | Options |
|---|---|
| Engine | browser (MediaRecorder) or egress (LiveKit Room Composite) |
| Control | manual or auto |
| Storage | local (RECORDINGS_DIR) or s3 |
Hosts and moderators can stream a meeting to YouTube, or to any RTMP destination, from a spectator's point of view. The stream shows only the camera grid, the room audio and a fixed caption strip at the bottom: no sidebars, toolbar or buttons. The YouTube stream key is pasted per meeting and is never stored.
The add-on runs on LiveKit Egress, which uses headless Chrome and about 4 vCPU per stream. It is disabled by default. When Egress is offline, /admin → Live stream shows these same steps and room hosts cannot start a stream.
Install
-
Create the Egress config. Set
api_key/api_secretto the same values aslivekit.yaml(LIVEKIT_API_KEY/LIVEKIT_API_SECRETin.env) and keephealth_port: 9187. If you change that port, it must not be used by anything else, andEGRESS_HEALTH_URLmust match it:cp infra/egress.yaml.example infra/egress.yaml
-
Start the container. It needs Docker and uses
network_mode: host:docker compose -f infra/docker-compose.egress.yml up -d
-
Allow outbound TCP 1935 (
rtmp://), or 443 forrtmps://. -
Optional, for real-time status: add this app's webhook to
livekit.yamland restart LiveKit. Without it, the app polls Egress for status.webhook: api_key: <LIVEKIT_API_KEY> urls: - http://127.0.0.1:3332/api/livekit/webhook
-
Optional, in
.env(restart the app afterwards):Variable Default Purpose LIVE_VIEW_BASE_URLNEXT_PUBLIC_APP_URLURL Egress' Chrome uses to open /<locale>/live-view/<meetingId>EGRESS_HEALTH_URLhttp://127.0.0.1:9187/Egress health check ( nonedisables the check) -
In
/admin→ Live stream, confirm the service shows online, tick Live streaming enabled and pick 720p or 1080p.
In a meeting, the host opens More → Go live, pastes the key from YouTube Studio, and everyone sees a LIVE badge. Details are in docs/05-live-stream.md (PT).
Do not run npm run build over the live .next while PM2 is serving it: until the build finishes the server answers with Cannot find module './chunks/…', and anyone in a meeting gets the "Something went wrong in the meeting" screen. Build into a separate folder and swap at the end:
git pull && npm ci
NEXT_DIST_DIR=.next-staging npm run build
rm -rf .next-prev && mv .next .next-prev && mv .next-staging .next
pm2 reload openmeetTabs opened before the update that request an old chunk reload themselves, at most once a minute. Avoid updating during live events.
Meeting crashes caught in the browser are reported to the server and logged to stderr as [openmeet:client-error] (message, stack, component stack, user agent). Disconnects are logged as [openmeet:disconnect].
| Branch | Purpose |
|---|---|
release |
Default. Stable public surface & GitHub Releases |
main |
Protected integration trunk (PR only) |
dev |
Protected active development (PR only) |
See CONTRIBUTING.md.
Locale-prefixed routes (/en/..., /pt/..., …) via next-intl. Edit catalogs under messages/.
npm run verify # typecheck + lint + tests
npm run test:watch
npm run test:coverage- Vision & scope (PT)
- Requirements (PT)
- Architecture (PT)
- Roadmap (PT)
- Live streaming (PT)
- ADRs in
docs/adr/
- Outbound webhooks in
/admin(signed withX-OpenMeet-*headers) - Instant meetings API:
POST /api/v1/instant-meetings— Redoc at/api-docs
MIT — contributions welcome. If OpenMeet helps you, a ⭐ on GitHub goes a long way.