Bedrud از LiveKit برای مدیریت ارتباط ویدیویی و صوتی بلادرنگ استفاده میکند. LiveKit media server SFU (واحد ارسال انتخابی) را ارائه میدهد، و Bedrud احراز هویت، مدیریت اتاق و کنترلهای مدیر را مدیریت میکند.
جاسازیشده در مقابل خارجی
Bedrud دو حالت استقرار LiveKit را پشتیبانی میکند:
۱. حالت جاسازیشده (پیشفرض): بکاند یک فرآیند سرور LiveKit را به صورت داخلی شروع و مدیریت میکند. هیچ زیرساخت اضافی مورد نیاز نیست - بکاند چرخه حیات فرآیند LiveKit را مدیریت میکند. ۲. حالت خارجی: Bedrud به یک سرور LiveKit جداگانه یا خوشه متصل میشود. این برای مقیاسافزایی افقی یا هنگام استفاده از نمونه ابری مدیریتشده LiveKit مفید است.
پیکربندی حالت خارجی
برای استفاده از یک سرور LiveKit خارجی، کلیدهای زیر را در config.yaml تنظیم کنید:
livekit:
host: "wss://livekit.example.com:7880" # Client WebSocket URL (ws:// or wss://)
internalHost: "https://livekit.example.com:7880" # Server-to-server API URL
apiKey: "your-api-key"
apiSecret: "your-api-secret"
external: true # Skip embedded LiveKit startup
skipTLSVerify: false # Set true if LiveKit uses self-signed certsوقتی embedded false است، Bedrud شروع باینری LiveKit جاسازیشده را رد میکند. کلید API و رمز باید با اعتبارنامههای سرور خارجی مطابقت داشته باشد.
برای تنظیم و پیکربندی خوشه LiveKit، به مستندات LiveKit ببینید.
پیکربندی Webhook (فقط خارجی)
هنگام استفاده از یک سرور LiveKit خارجی، باید webhookها را پیکربندی کنید تا LiveKit بتواند قطع ارتباط شرکتکنندگان و بسته شدن اتاقها را به Bedrud اطلاع دهد. بدون webhook، وضعیت پایگاه داده کهنه میشود.
نقطه پایان: https://<your-domain>/api/livekit/webhook
احراز هویت: از امضای JWT LiveKit استفاده میکند — همان apiKey/apiSecret که در بالا پیکربندی کردید. نیازی به رمز جداگانه نیست.
LiveKit Cloud: تنظیمات ← Webhookها ← ایجاد webhook جدید. URL نقطه پایان را وارد کرده و کلید API خود را انتخاب کنید.
LiveKit خودمیزبان: به پیکربندی YAML LiveKit خود (به عنوان مثال livekit.yaml) اضافه کنید:
webhook:
urls: ["https://bedrud.example.com/api/livekit/webhook"]
api_key: "your-api-key"بدون یک webhook به درستی پیکربندیشده، رویدادهای participant_disconnected و room_finished به Bedrud تحویل داده نمیشوند. داشبورد مدیریت ممکن است دادههای شرکتکننده کهنه را نشان دهد و اتاقها به طور خودکار پاکسازی نمیشوند.
سازگاری نسخه LiveKit
حالت LiveKit جاسازیشده Bedrud به طور خودکار یک پیکربندی سازگار تولید میکند. با این حال، اگر یک سرور LiveKit خارجی را خودمیزبان هستید، از تغییرات شکستدهنده در نسخههای LiveKit آگاه باشید:
- LiveKit v1.12+ فیلد سطح بالای
tlsرا از پیکربندی خود حذف کرده است. اگر ازtls:در YAML LiveKit خود استفاده میکردید، آن را حذف کنید. برایinternalHostازhttp://و برایhostدر پیکربندی Bedrud ازws://استفاده کنید. TURN TLS هنوز در بخشturn:پشتیبانی میشود. - LiveKit v1.11 و قدیمیتر از
tls:در سطح بالا پشتیبانی میکنند. برایinternalHostازhttps://و برایhostازwss://استفاده کنید.
در صورت تردید، نسخه سرور LiveKit خود را با livekit-server --version بررسی کنید و به یادداشتهای انتشار LiveKit مراجعه کنید.
تولید پیکربندی جاسازیشده (Embedded Config Generation)
وقتی TLS در حالت جاسازیشده فعال باشد، Bedrud یک پیکربندی YAML موقت برای LiveKit تولید میکند (/tmp/bedrud-livekit-*.yaml) با:
- TURN فعال،
domainبه طور خودکار ازserver.hostتنظیم شده،udp_port: 3478،tls_port: 5349، و گواهی TLS سرور برای TURN/TLS استفاده مجدد میشود node_ipاز طریقlivekit.nodeIP←server.host← تشخیص خودکار IP خروجی تعیین میشودbind_addressesحذف شده (LiveKit به طور پیشفرض به همه رابطها متصل میشود)
فایل موقت هنگام خروج فرآیند LiveKit پاک میشود. برای دور زدن تولید خودکار با یک پیکربندی ثابت، livekit.configPath یا LIVEKIT_CONFIG_PATH را تنظیم کنید.
نحوه کار
۱. ایجاد اتاق
وقتی یک کاربر در Bedrud اتاق ایجاد میکند، سرور بلافاصله یک اتاق LiveKit ایجاد نمیکند. اتاقهای LiveKit به صورت درخواستی هنگام پیوستن اولین شرکتکننده ایجاد میشوند.
۲. توکنهای پیوستن
وقتی یک کاربر به یک جلسه میپیوندد:
۱. فرانتاند درخواستی به /api/room/join میفرستد.
۲. بکاند تأیید میکند که کاربر اجازه پیوستن به آن اتاق را دارد.
۳. بکاند از کلید API و رمز خود برای تولید یک JWT امضاشده (توکن پیوستن) استفاده میکند.
۴. توکن شامل موارد زیر است:
- نام اتاق.
- هویت کاربر (نام نمایشی).
- مجوزها - برای مثال، اینکه آیا کاربر میتواند صدا را منتشر کند یا صفحه خود را به اشتراک بگذارد.
۵. فرانتاند این توکن را دریافت میکند و مستقیماً به پورت رسانه LiveKit (پیشفرض
7880) متصل میشود.
۳. کنترلهای اتاق (مدیر)
بکاند از LiveKit Go SDK برای انجام عملیات مدیریتی استفاده میکند:
- اخراج: یک شرکتکننده را قطع میکند.
- سکوت: میکروفون یک شرکتکننده را به اجبار سکوت میکند.
- مجوزها: آنچه یک شرکتکننده میتواند در زمان واقعی انجام دهد را تغییر میدهد.
معماری شبکه
- پورت API (8090/443): درخواستهای HTTP و سیگنالینگ WebSocket برای راهاندازی تماس را مدیریت میکند.
- پورت رسانه (7880): دادههای ویدیویی و صوتی را با استفاده از پروتکلهای WebRTC مدیریت میکند. بازگشت ICE/TCP از پورت 7881 وقتی UDP مسدود است استفاده میکند.
- پورت TURN (3478 UDP / 5349 TLS): رسانه را برای کلاینتهای پشت NAT یا فایروالهای محدود رله میکند. به راهنمای سرور TURN ببینید.
برای الزامات فایروال و پورت، به اتصال WebRTC ببینید.
Troubleshooting
Startup & Config Crashes
| Symptom | Cause | Fix |
|---|---|---|
Container crash-loops, logs could not resolve external IP | use_external_ip: true without explicit node_ip in Docker | Set node_ip: <lan-ip> under rtc: and use_external_ip: false |
LiveKit exits with TURN domain required on v1.12+ | turn.tls_port is set but no domain or TLS cert/key | Add domain: under turn:, provide cert_file/key_file, or remove tls_port for UDP-only TURN |
field tls not found on startup | LiveKit v1.12+ removed top-level tls: config field | Remove tls: block from LiveKit YAML; use http:// / ws:// in Bedrud config |
LIVEKIT_CONFIG env var not picked up | Entrypoint doesn’t parse env var (pre-v1.7 or custom entrypoint) | LiveKit reads LIVEKIT_CONFIG natively since v1.7 — verify version; pass via --config-body only if needed |
Docker: --config-body via sh -c fails with flag provided but not defined: -c | Image entrypoint is /livekit-server directly — command gets appended, not wrapped by shell | Don’t use a shell wrapper, LIVEKIT_CONFIG env var is supported natively by the binary |
Docker Compose: $LIVEKIT_CONFIG expands to empty string | Compose substitutes $VAR from host environment, not container | Use $$LIVEKIT_CONFIG to escape docker-compose variable substitution |
YAML parsing error from LIVEKIT_CONFIG | Incorrect YAML indentation or syntax | Validate: docker run --rm -e LIVEKIT_CONFIG livekit-server --config-body "$LIVEKIT_CONFIG" |
Connectivity
| Symptom | Cause | Fix |
|---|---|---|
| Admin dashboard shows “LiveKit disconnected” | Bedrud can’t reach LiveKit HTTP API | Verify internalHost in config; run curl http://<internalHost>/ from Bedrud host; check firewall |
| Token generated but client connection times out | LiveKit WebSocket unreachable from browser | Check host in livekit: config (must be reachable by clients); verify DNS/firewall; test with wscat |
| Embedded LiveKit not starting | Missing binary or permission | Ensure internal/livekit/bin/livekit-server exists (even empty file for build); check Bedrud server logs |
| Port 7880 already in use | Another process on same port | Change livekit.port or use different Docker port mapping |
| Redis connection fails in LiveKit logs | Redis unreachable or wrong address | Verify redis.address: in LiveKit YAML; check container network connectivity |
curl http://127.0.0.1:7880 returns connection refused | LiveKit crashed during startup | Check docker logs / journalctl; look for RTC/TURN validation errors near the bottom of the log |
| Token expired before client connected | Short JWT validity window | Request a fresh token via POST /api/room/join before each connection attempt |
Media & TURN
| Symptom | Cause | Fix |
|---|---|---|
| Participants join but no audio/video | UDP port range blocked or wrong node_ip | Open UDP 50000-60000; verify node_ip is the externally reachable address |
| Clients behind NAT can’t connect | TURN not configured or ports blocked | Enable TURN; open UDP 3478 (and TCP 5349 for TLS); verify TURN domain resolves |
Could not resolve external IP on startup (non-Docker) | No STUN internet access or DNS failure | Set explicit node_ip and use_external_ip: false |
| Self-signed cert errors with external LiveKit | Bedrud’s skipTLSVerify is false | Set skipTLSVerify: true in Bedrud’s livekit: config |
| Clients connect via relay unnecessarily | node_ip is a private IP behind NAT | Set node_ip to the public IP or use use_external_ip: true with STUN access |
| TURN relay not used by clients | Direct WebRTC path is working (expected) | Check chrome://webrtc-internals — srflx candidates = direct path, no TURN needed |
Webhook & State
| Symptom | Cause | Fix |
|---|---|---|
| Database shows stale active participants after disconnect | Webhook not configured for external LiveKit | Add webhook: block to LiveKit YAML with URL https://<domain>/api/livekit/webhook |
| Participants never marked inactive | Firewall blocking webhook delivery from LiveKit to Bedrud | Check LiveKit logs for webhook delivery errors; ensure port 443/8090 is reachable from LiveKit |
| Room not cleaned up after all leave | empty_timeout / departure_timeout too high | Reduce values in LiveKit YAML room: section |
Recording (Egress)
Bedrud uses LiveKit’s RoomCompositeEgress API to record rooms as MP4 files.
Prerequisites
-
Redis — LiveKit egress requires Redis for coordinating egress workers. Without Redis,
StartRoomCompositeEgressreturns permission errors. -
Egress S3 storage (external mode only) — For external LiveKit, you must configure an
egress:section in your LiveKit YAML so recordings are stored to durable S3-compatible storage. Otherwise theFileURLis a local path unreachable from Bedrud.egress: s3: access_key: "your-s3-access-key" secret_key: "your-s3-secret-key" endpoint: "http://minio:9000" bucket: "bedrud-recordings" region: "us-east-1" force_path_style: true
Troubleshooting: Recording
| Symptom | Cause | Fix |
|---|---|---|
twirp error unauthenticated: permissions denied when starting recording | Egress JWT missing Room field in grant | Update egressAuthContext to include Room: roomName in the VideoGrant |
twirp error unauthenticated: permissions denied even with valid API key | Redis not configured for LiveKit, or egress workers unavailable | Add redis: section to LiveKit YAML; ensure Redis is healthy |
Recording starts but FileURL is a local path (e.g., /tmp/...) | No egress: S3 config — LiveKit writes to worker temp dir | Add egress.s3: block to LiveKit YAML pointing to S3-compatible storage |
process_recording job fails to download | External LK’s file URL points to inaccessible local path | Configure egress S3 so LiveKit produces S3 URLs |
See also the TURN Server Guide for TURN-specific troubleshooting, WebRTC Connectivity for STUN/ICE/firewall debugging, and Installation Troubleshooting for port/perm/setup issues.
مشاهده همچنین
- راهنمای سرور TURN - معماری، پیکربندی، TLS و عیبیابی TURN
- اتصال WebRTC - پشته اتصال کامل STUN/ICE/TURN/SFU
- نمای کلی معماری - معماری کامل سیستم