Интеграция 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, корпоративный файрвол). Обязателен для продакшна. Рекомендуется 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 и интерфейсом звонка.







