Jibri Recording Setup
Wiring Jitsi Broadcasting Infrastructure for live class recording
OptiLearn supports recording live classes via Jibri (Jitsi Broadcasting Infrastructure). The OptiLearn side is already wired — host UI, start/stop endpoints, webhook verification, recording-ready notification fan-out. What's left as ops work is provisioning Jibri itself in your Coolify Jitsi deployment.
If Jibri isn't configured, hosts will see a friendly "contact your administrator" message when they try to record. The rest of the live class system works fine.
What needs to happen
- Add the Jibri sidecar to your Coolify Jitsi deployment
- Configure Jibri to upload recordings to a reachable URL (R2 / S3 / any public storage)
- Configure Jibri's webhook plugin to call back to OptiLearn
- Set the two OptiLearn env vars
The actual Jibri setup steps are out of scope for this doc — they vary by Jitsi distribution and Coolify version. Use the official docs as your primary reference:
OptiLearn-side environment variables
Set both on the OptiLearn web service (and copy to the worker, though the worker doesn't read them directly):
| Variable | Purpose |
|---|---|
JITSI_RECORDING_API_TOKEN | Bearer token used by startJibriRecording / stopJibriRecording to call the Jibri-enabled meet server. Must match what Jibri's API is configured to accept. |
JITSI_RECORDING_WEBHOOK_SECRET | HMAC secret for verifying inbound Jibri callbacks. Must match the secret configured in Jibri's webhook plugin. |
If JITSI_RECORDING_API_TOKEN is unset (or the meet server returns 404 on the recording endpoint), POST /api/live-sessions/[id]/recording/start returns 503 with a friendly message. The host UI can show "contact your administrator" without surfacing a generic 500.
If JITSI_RECORDING_WEBHOOK_SECRET is unset, the webhook endpoint refuses every inbound request with 503. This refuses-rather-than-defaults posture exists so anyone on the public internet can't post arbitrary recording URLs while you're mid-deploy.
The webhook endpoint
Jibri must be able to reach this URL with a public callback:
POST https://learn.opticrm.app/api/webhooks/jitsi-recording
Configure Jibri's webhook plugin to:
- POST to that URL on
recording_uploadedandrecording_failedevents - Sign the body with HMAC-SHA256 using the same secret as
JITSI_RECORDING_WEBHOOK_SECRET - Send the signature in either
X-Jibri-Signature: <hex>orX-Jibri-Signature: sha256=<hex>(both accepted)
Expected payload shape — see Recording API.
Local testing
Jibri must reach OptiLearn's webhook URL. For local dev you need a tunnel:
# Example with cloudflared
cloudflared tunnel --url http://localhost:3001
# → https://abc-def.trycloudflare.com
# Set NEXTAUTH_URL to the tunnel URL so Jibri's callback header is right
NEXTAUTH_URL=https://abc-def.trycloudflare.com npm run dev -- -p 3001
Then point Jibri's webhook config at https://abc-def.trycloudflare.com/api/webhooks/jitsi-recording.
End-to-end flow
Host clicks "Record"
→ POST /api/live-sessions/[id]/recording/start
→ OptiLearn flips status to PENDING, calls Jibri API
→ Jibri starts capturing, OptiLearn flips to RECORDING
Host clicks "Stop"
→ POST /api/live-sessions/[id]/recording/stop
→ OptiLearn flips status to PROCESSING, calls Jibri API
→ Jibri finishes, uploads to storage
Jibri callback
→ POST /api/webhooks/jitsi-recording (signature-verified)
→ OptiLearn stores recordingUrl, flips to READY
→ Fans LIVE_CLASS_RECORDING_READY out to enrolled students
Verifying setup
- Schedule a live session with a small test cohort
- Start the session, click Record (host only)
- Check OptiLearn's
LiveSessionrow —recordingStatus = PENDING, thenRECORDING - Stop after ~30s —
recordingStatus = PROCESSING - Wait for Jibri to upload and call back —
recordingStatus = READY,recordingUrlset - Enrolled students should receive
LIVE_CLASS_RECORDING_READY - The recording link appears under the session detail
If anything stalls, check:
- OptiLearn logs for the start/stop request and webhook receipt
- Jibri logs for the upload result
- That the webhook URL is publicly reachable (use
curl -X POSTfrom outside) - That HMAC signatures match (most common cause of 401 on the webhook)
Status state machine
See Recording API — Status state machine for the full diagram.
Related
- Recording API — endpoint shapes + webhook details
- Notifications System —
LIVE_CLASS_RECORDING_READYfan-out - Jibri docs