LiveKit Integration for Video Conferencing on Your Website
LiveKit — an open-source WebRTC server with SFU architecture that provides low latency and scaling to thousands of participants. You get full control over data and interface, with no participant limits or hidden fees. However, on real projects we encounter typical problems: incorrect ICE server configuration, NAT issues, and suboptimal SFU architecture choices, leading to latency spikes of 5–10 seconds. Our experience with over 50 WebRTC integrations shows that proper LiveKit configuration solves these issues at the core.
How to Reduce Video Call Latency with LiveKit
SFU (Selective Forwarding Unit) architecture ensures latency below 200 ms even on weak channels. Unlike Jitsi, LiveKit uses optimized codecs (VP9, H.264) and adaptive bitrate. With 50 participants, latency difference reaches 3–5 times in favor of LiveKit. Moreover, you pay no licensing fees: the server cost for 1000 users is minimal.
How to Integrate LiveKit: Case Study of an Educational Platform
We recently implemented LiveKit for a client — an educational platform with 5000 users. The original architecture used Jitsi, but after migrating to LiveKit, latency dropped from 800 ms to 150 ms, and server costs decreased by 40%. We used LiveKit Server 1.5 on Docker, Node.js backend with LiveKit SDK, and React 18 frontend with @livekit/components-react.
Installing LiveKit Server
# docker-compose.yml
services:
livekit:
image: livekit/livekit-server:latest
command: --dev
ports:
- "7880:7880"
- "7881:7881"
- "7882:7882/udp"
environment:
LIVEKIT_KEYS: "APIkey: APIsecret"
For production, use a config with external IP and TURN servers:
# livekit.yaml
port: 7880
rtc:
tcp_port: 7881
udp_port: 7882
use_external_ip: true
keys:
APIkey: APIsecret
How to Integrate LiveKit into a React App?
Backend: token generation
import { AccessToken, RoomServiceClient } from 'livekit-server-sdk';
const roomService = new RoomServiceClient(
process.env.LIVEKIT_URL,
process.env.LIVEKIT_API_KEY,
process.env.LIVEKIT_API_SECRET
);
await roomService.createRoom({
name: `room-${meetingId}`,
maxParticipants: 50,
emptyTimeout: 10 * 60
});
function generateToken(roomName: string, participant: Participant): string {
const at = new AccessToken(
process.env.LIVEKIT_API_KEY,
process.env.LIVEKIT_API_SECRET,
{ identity: participant.id, name: participant.name, ttl: '2h' }
);
at.addGrant({ roomJoin: true, room: roomName, canPublish: true, canSubscribe: true, canPublishData: true });
return at.toJwt();
}
app.post('/api/meetings/:id/join', authenticate, async (req, res) => {
const meeting = await meetingRepo.findById(req.params.id);
if (!meeting) return res.status(404).json({ error: 'Meeting not found' });
const token = generateToken(`room-${meeting.id}`, { id: req.user.id, name: req.user.displayName });
res.json({ token, serverUrl: process.env.LIVEKIT_URL });
});
Client (React)
import { LiveKitRoom, VideoConference, RoomAudioRenderer } from '@livekit/components-react';
function VideoRoom({ roomId }) {
const [token, setToken] = useState(null);
const [serverUrl, setServerUrl] = useState('');
useEffect(() => {
fetch(`/api/meetings/${roomId}/join`, { method: 'POST' })
.then(r => r.json())
.then(({ token, serverUrl }) => { setToken(token); setServerUrl(serverUrl); });
}, [roomId]);
if (!token) return <div>Connecting...</div>;
return (
<LiveKitRoom token={token} serverUrl={serverUrl} connect video audio>
<VideoConference />
<RoomAudioRenderer />
</LiveKitRoom>
);
}
This is the minimal set. For a custom interface, use useTracks and GridLayout.
Recording Meetings
import { EgressClient, EncodedFileType } from 'livekit-server-sdk';
const egressClient = new EgressClient(
process.env.LIVEKIT_URL,
process.env.LIVEKIT_API_KEY,
process.env.LIVEKIT_API_SECRET
);
const egress = await egressClient.startRoomCompositeEgress(
`room-${meetingId}`,
{ file: { fileType: EncodedFileType.MP4, s3: { accessKey: process.env.AWS_ACCESS_KEY, secret: process.env.AWS_SECRET, bucket: 'recordings', key: `meetings/${meetingId}/${Date.now()}.mp4` } } }
);
Comparison of LiveKit with Alternatives
| Parameter | LiveKit | Jitsi | Daily.co |
|---|---|---|---|
| License | Open-source (Apache 2.0) | Apache 2.0 | Proprietary |
| Max participants | 1000+ | 50–100 | 50 (free) |
| Latency (50 participants) | < 200 ms | 300–600 ms | 200–400 ms |
| Self-hosted | Yes | Yes | No |
| Scaling cost | Open-source + server | Open-source + server | Proprietary |
LiveKit is 3 times faster in latency than Jitsi and has no hidden costs.
How to Achieve Stable Operation with 1000 Participants?
For 1000+ participants, use SFU clustering. LiveKit supports horizontal scaling via Redis and NATS. Configure TURN servers (e.g., Coturn) for NAT traversal. Important: choose servers in multiple regions for low latency. Also enable adaptive bitrate and use the AdaptiveStream option on the client.
LiveKit Features: Version Comparison
| Feature | Open Source | Cloud (Enterprise) |
|---|---|---|
| Recording (Egress) | Yes | Yes (built-in) |
| Streaming (RTMP/WHIP) | Yes | Yes |
| Chat and file sharing | Via WebSocket | Built-in |
| Virtual backgrounds | Requires processing | Built-in |
| Analytics | Prometheus metrics | Dashboard |
| Support | Community | 24/7 |
Process of Work
Integration Stages
- Analytics — assessment of current infrastructure, number of users, recording and UI requirements.
- Design — selection of architecture (single SFU or cluster), configuration of TURN servers, backup plan.
- Implementation — backend development (authentication, room management), integration of React components.
- Testing — load tests up to 500 participants, latency and audio quality checks.
- Deployment — server deployment, monitoring setup, load testing.
What is Included in the Integration
- Setup of LiveKit Server on your or our server (Docker).
- Development of a backend module for token generation and room management.
- Integration of React components from
@livekit/components-reactwith optional custom UI. - Recording setup via Egress API (S3, MinIO).
- Documentation and 2 weeks of support after delivery.
- 30-day guarantee on stable video call operation.
Timeline
- Basic integration (server + tokens + React UI) — from 5 to 10 business days.
- Extended integration (custom UI, recording, admin panel) — from 15 to 25 business days.
LiveKit also supports end-to-end encryption and JWT authentication. In our integration, we configure security by default.
How to Order Integration?
Contact us for a free assessment of your project. We will analyze the requirements and offer the optimal solution. Get a consultation — write to Telegram or email. Implementing LiveKit pays off due to reduced infrastructure costs from the first month. Order LiveKit integration for your project today.







