Інтеграція VoIP-звонків через WebRTC на сайт
WebRTC (Web Real-Time Communication) — браузерний стандарт для peer-to-peer медіапотоків. Дозволяє організувати аудіо та відео звонки прямо у браузері без плагінів. Сценарії: звонок відвідувача в підтримку, відеоконсультація, голосовий чат у грі.
Компоненти WebRTC-звонка
Signaling server — не входить у стандарт WebRTC, реалізується самостійно. Обмінюється SDP (Session Description Protocol) та ICE candidates між клієнтами. Зазвичай через WebSocket.
STUN server — допомагає клієнтам визначити зовнішній IP і порт (NAT traversal). Можна використовувати безплатний Google STUN: stun:stun.l.google.com:19302.
TURN server — relay-сервер для випадків, коли прямое P2P-з'єднання неможливе (симетричний NAT, корпоративний файрвол). Обов'язковий для production. Рекомендується coturn.
Базовий звонок між двома браузерами
// Конфігурація ICE серверів
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{
urls: 'turn:turn.yourserver.ru:3478',
username: 'user',
credential: 'pass'
}
]
};
// Створення з'єднання
const pc = new RTCPeerConnection(configuration);
// Захоплення мікрофону
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
stream.getTracks().forEach(track => pc.addTrack(track, stream));
// Обробка вхідного медіапотоку
pc.ontrack = (event) => {
const remoteAudio = document.getElementById('remote-audio');
remoteAudio.srcObject = event.streams[0];
};
// Створення offer (інціатор звонка)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// Відправка offer через signaling (WebSocket)
signalingSocket.send(JSON.stringify({
type: 'offer',
sdp: offer,
to: targetUserId
}));
// Обробка ICE candidates
pc.onicecandidate = (event) => {
if (event.candidate) {
signalingSocket.send(JSON.stringify({
type: 'ice_candidate',
candidate: event.candidate,
to: targetUserId
}));
}
};
Signaling Server на Node.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const clients = new Map(); // userId → WebSocket
wss.on('connection', (ws, req) => {
const userId = extractUserId(req);
clients.set(userId, ws);
ws.on('message', (data) => {
const message = JSON.parse(data);
const { type, to } = message;
if (['offer', 'answer', 'ice_candidate'].includes(type)) {
const target = clients.get(to);
if (target && target.readyState === WebSocket.OPEN) {
target.send(JSON.stringify({ ...message, from: userId }));
}
}
});
ws.on('close', () => clients.delete(userId));
});
Функції звонка у React
function CallButton({ targetUserId }) {
const [callState, setCallState] = useState('idle'); // idle | calling | connected
const pcRef = useRef(null);
const startCall = async () => {
setCallState('calling');
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
pcRef.current = new RTCPeerConnection(configuration);
stream.getTracks().forEach(t => pcRef.current.addTrack(t, stream));
// ... (створення offer, відправка через signaling)
};
const endCall = () => {
pcRef.current?.close();
setCallState('idle');
};
return (
<button onClick={callState === 'idle' ? startCall : endCall}>
{callState === 'idle' ? '📞 Позвонити' : '❌ Завершити'}
</button>
);
}
Якість зв'язку
- OPUS codec — стандартний аудіокодек WebRTC, хороший для голосу
- Adaptive bitrate — WebRTC автоматично регулює якість під канал
-
Echo cancellation — вбудована у браузер (
echoCancellation: trueу constraints) - Noise suppression — аналогічно вбудована
Моніторинг якості
// WebRTC Stats API
const stats = await pc.getStats();
stats.forEach(report => {
if (report.type === 'inbound-rtp' && report.kind === 'audio') {
console.log('Jitter:', report.jitter);
console.log('Packet loss:', report.packetsLost / report.packetsReceived);
console.log('RTT:', report.roundTripTime);
}
});
TURN-сервер (coturn)
# /etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
fingerprint
lt-cred-mech
user=user:password
realm=yourserver.ru
Без TURN близько 15–20% звонків не встановляться через мережні обмеження. З TURN — практично 100%.
Термін розробки: 3–5 тижнів для повної реалізації з signaling-сервером, TURN та інтерфейсом звонка.







