WebRTC (Web Real-Time Communication) example
WebRTC (Web Real-Time Communication) enables peer-to-peer audio, video, and data sharing between browsers without the need for an intermediary server. However, before a WebRTC connection can be established, signaling is necessary. Signaling involves the exchange of information required to set up the connection, such as session descriptions and network information (ICE candidates). This process typically uses a signaling server, which can be implemented using WebSockets or any other communication protocol.
Here’s a high-level overview of the signaling process with a basic example using Socket.IO as the signaling server:
WebRTC Signaling Steps
- Establish a Signaling Channel: Use WebSockets to allow peers to exchange signaling messages.
- Exchange Offer and Answer: One peer creates an offer, and the other peer responds with an answer.
- Exchange ICE Candidates: Both peers exchange network information to establish a direct connection.
Example: Simple WebRTC Video Chat
Server-side (Node.js with Socket.IO)
-
Install Dependencies:
npm install express socket.io
-
Server Code (
server.js
):const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const app = express(); const server = http.createServer(app); const io = socketIo(server); app.use(express.static('public')); io.on('connection', (socket) => { console.log('a user connected'); socket.on('offer', (data) => { socket.broadcast.emit('offer', data); }); socket.on('answer', (data) => { socket.broadcast.emit('answer', data); }); socket.on('candidate', (data) => { socket.broadcast.emit('candidate', data); }); socket.on('disconnect', () => { console.log('user disconnected'); }); }); server.listen(3000, () => { console.log('server is running on port 3000'); });
Client-side (HTML + JavaScript)
-
HTML (
public/index.html
):<!DOCTYPE html> <html> <head> <title>WebRTC Video Chat</title> </head> <body> <video id="localVideo" autoplay playsinline></video> <video id="remoteVideo" autoplay playsinline></video> <script src="/socket.io/socket.io.js"></script> <script src="client.js"></script> </body> </html>
-
Client JavaScript (
public/client.js
):const socket = io(); const localVideo = document.getElementById('localVideo'); const remoteVideo = document.getElementById('remoteVideo'); let localStream; let pc; const configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; async function start() { localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); localVideo.srcObject = localStream; pc = new RTCPeerConnection(configuration); localStream.getTracks().forEach(track => pc.addTrack(track, localStream)); pc.onicecandidate = ({ candidate }) => { if (candidate) { socket.emit('candidate', candidate); } }; pc.ontrack = ({ streams: [stream] }) => { remoteVideo.srcObject = stream; }; socket.on('offer', async (offer) => { if (!pc) start(); await pc.setRemoteDescription(new RTCSessionDescription(offer)); const answer = await pc.createAnswer(); await pc.setLocalDescription(answer); socket.emit('answer', answer); }); socket.on('answer', async (answer) => { await pc.setRemoteDescription(new RTCSessionDescription(answer)); }); socket.on('candidate', async (candidate) => { try { await pc.addIceCandidate(new RTCIceCandidate(candidate)); } catch (e) { console.error('Error adding received ice candidate', e); } }); } start(); async function createOffer() { const offer = await pc.createOffer(); await pc.setLocalDescription(offer); socket.emit('offer', offer); } // Create offer when user clicks the "Call" button document.getElementById('callButton').addEventListener('click', createOffer);
Published on: Jun 26, 2024, 05:50 AM