← Quay lại Blog
Công nghệ & AI 19/09/2026 · 8 phút đọc

WebRTC: Công Nghệ Giao Tiếp Real-time Trên Web

Minh họa kết nối peer-to-peer WebRTC giữa các thiết bị

WebRTC (Web Real-Time Communication) cho phép truyền tải âm thanh, video và dữ liệu trực tiếp giữa các trình duyệt mà không cần plugin hay server trung gian. Độ trễ dưới 500ms, kết nối peer-to-peer mã hóa end-to-end, chạy ngay trên Chrome/Firefox/Safari. Đây là công nghệ nền tảng đằng sau Google Meet, Zoom web client, Discord voice chat và hàng ngàn ứng dụng giao tiếp real-time khác.

WebRTC là gì và tại sao quan trọng?

WebRTC là tập hợp các API và giao thức cho phép truyền tải media và dữ liệu real-time giữa các thiết bị qua web. Google phát triển từ 2011. Năm 2021 chính thức trở thành chuẩn W3C.

Ba khả năng cốt lõi:

  1. getUserMedia - truy cập camera và microphone
  2. RTCPeerConnection - truyền âm thanh/video giữa các peer
  3. RTCDataChannel - truyền dữ liệu tùy ý (text, file, game state)

Kiến trúc peer-to-peer:

WebRTC thiết lập kết nối trực tiếp giữa các trình duyệt sau bước “signaling” ban đầu qua server — trao đổi địa chỉ IP và khả năng codec. Xong.

Media stream sau đó đi thẳng peer-to-peer, không qua server. Giảm độ trễ. Giảm chi phí bandwidth.

Khi nào peer-to-peer thất bại:

Khoảng 15-20% kết nối không thiết lập được P2P do NAT symmetric hoặc firewall nghiêm ngặt. Lúc này cần TURN server làm relay - tốn bandwidth và chi phí.

Cách WebRTC hoạt động: từ signaling đến streaming

1. Signaling - trao đổi thông tin kết nối

WebRTC không định nghĩa cơ chế signaling - bạn tự chọn: WebSocket, HTTP long-polling, hoặc thậm chí copy/paste SDP qua chat.

Flow điển hình:

// Peer A tạo offer
const pc = new RTCPeerConnection(config);
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// Gửi offer qua signaling server tới Peer B

// Peer B nhận offer, tạo answer
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
// Gửi answer về Peer A

// Peer A nhận answer
await pc.setRemoteDescription(answer);

SDP (Session Description Protocol) mô tả codec được hỗ trợ, resolution, địa chỉ network candidate. Kích thước SDP khoảng 2-5KB JSON text.

2. ICE - tìm đường đi tốt nhất

ICE (Interactive Connectivity Establishment) thử nhiều candidate:

  • Host candidate: IP local (LAN)
  • Server reflexive: IP public qua STUN server
  • Relay candidate: qua TURN server khi P2P fail

Trình duyệt tự động thử từng cặp candidate theo thứ tự ưu tiên, chọn cái nhanh nhất (thường là host nếu cùng LAN, hoặc reflexive nếu khác mạng).

3. DTLS - mã hóa

Mọi media stream WebRTC đều mã hóa bằng DTLS-SRTP (TLS cho media).

Không có tùy chọn “unencrypted”. Bảo mật là bắt buộc.

4. Media streaming

Khi kết nối thiết lập, RTCPeerConnection tự động:

  • Encode video (VP8/VP9/H.264)
  • Adapt bitrate theo bandwidth (REMB feedback)
  • Forward error correction và retransmission khi mất gói
  • Đồng bộ âm thanh/video (RTP timestamps)

Bandwidth adaptive: nếu mạng yếu, WebRTC tự giảm resolution từ 720p → 480p → 360p để giữ fluency.

Triển khai WebRTC: code thực tế

Setup cơ bản - video call 1-1

// 1. Lấy stream từ camera/mic
const localStream = await navigator.mediaDevices.getUserMedia({
  video: { width: 1280, height: 720 },
  audio: { echoCancellation: true, noiseSuppression: true }
});
document.getElementById('localVideo').srcObject = localStream;

// 2. Tạo PeerConnection
const config = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' }, // STUN miễn phí
    { 
      urls: 'turn:turn.example.com:3478',
      username: 'user',
      credential: 'pass'
    }
  ]
};
const pc = new RTCPeerConnection(config);

// 3. Thêm local tracks vào connection
localStream.getTracks().forEach(track => {
  pc.addTrack(track, localStream);
});

// 4. Nhận remote stream
pc.ontrack = (event) => {
  document.getElementById('remoteVideo').srcObject = event.streams[0];
};

// 5. ICE candidate handling
pc.onicecandidate = (event) => {
  if (event.candidate) {
    // Gửi candidate qua signaling server
    signalingChannel.send({ type: 'ice', candidate: event.candidate });
  }
};

// 6. Signaling (ví dụ WebSocket)
signalingChannel.onmessage = async (msg) => {
  const data = JSON.parse(msg.data);
  if (data.type === 'offer') {
    await pc.setRemoteDescription(data.offer);
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    signalingChannel.send({ type: 'answer', answer });
  } else if (data.type === 'answer') {
    await pc.setRemoteDescription(data.answer);
  } else if (data.type === 'ice') {
    await pc.addIceCandidate(data.candidate);
  }
};

200 dòng code cho video call đầy đủ, bao gồm error handling và UI controls.

Screen sharing - một dòng khác biệt

// Thay getUserMedia bằng getDisplayMedia
const screenStream = await navigator.mediaDevices.getDisplayMedia({
  video: { cursor: 'always' },
  audio: false // hoặc true để capture system audio
});

// Thay track trong PeerConnection đang chạy
const [screenTrack] = screenStream.getVideoTracks();
const sender = pc.getSenders().find(s => s.track?.kind === 'video');
sender.replaceTrack(screenTrack); // Swap camera → screen mà không reconnect

Không cần thiết lập lại PeerConnection - chỉ swap track.

DataChannel - truyền dữ liệu tùy ý

// Peer A tạo channel
const dataChannel = pc.createDataChannel('chat', {
  ordered: false, // không đảm bảo thứ tự (nhanh hơn)
  maxRetransmits: 3 // retry tối đa 3 lần
});

dataChannel.onopen = () => {
  dataChannel.send('Hello from DataChannel!');
  dataChannel.send(new Uint8Array([1, 2, 3])); // binary data
};

dataChannel.onmessage = (event) => {
  console.log('Received:', event.data);
};

// Peer B nhận channel
pc.ondatachannel = (event) => {
  const channel = event.channel;
  channel.onmessage = (e) => console.log(e.data);
};

Ứng dụng DataChannel:

  • Game multiplayer (gửi player position 60 lần/giây)
  • File transfer P2P (không qua server)
  • Collaborative editing (sync cursor, selection)
  • Signaling cho nhiều peer (mesh network)

Xử lý lỗi phổ biến

// 1. Permission denied
try {
  const stream = await navigator.mediaDevices.getUserMedia({ video: true });
} catch (err) {
  if (err.name === 'NotAllowedError') {
    alert('Bạn cần cấp quyền camera');
  } else if (err.name === 'NotFoundError') {
    alert('Không tìm thấy camera');
  }
}

// 2. Connection failed
pc.oniceconnectionstatechange = () => {
  if (pc.iceConnectionState === 'failed') {
    // Thử ICE restart
    pc.restartIce();
  } else if (pc.iceConnectionState === 'disconnected') {
    // Chờ 5s trước khi reconnect
    setTimeout(() => {
      if (pc.iceConnectionState === 'disconnected') {
        reconnect();
      }
    }, 5000);
  }
};

// 3. Bandwidth adaptation
pc.getSenders().forEach(sender => {
  const params = sender.getParameters();
  params.encodings[0].maxBitrate = 500000; // giới hạn 500 kbps
  sender.setParameters(params);
});

Kiến trúc multi-user: SFU vs Mesh vs MCU

1. Mesh (P2P đầy đủ):

  • Mỗi peer kết nối với mọi peer khác
  • Upload bandwidth = (N-1) × bitrate
  • Chỉ chịu được tối đa 4-6 người

2. SFU (Selective Forwarding Unit):

  • Server nhận stream từ mọi peer, forward đến các peer khác
  • Không encode/decode - chỉ route
  • Upload 1 stream, nhận N-1 streams
  • Giải pháp phổ biến nhất (Jitsi, Janus, mediasoup)

3. MCU (Multipoint Control Unit):

  • Server mix mọi stream thành 1 stream hợp nhất
  • Tốn CPU server, nhưng client chỉ nhận 1 stream
  • Dùng cho conference lớn (>50 người)

Lựa chọn:

  • ≤ 4 người: Mesh (đơn giản nhất)
  • 5-50 người: SFU
  • 50 người: MCU hoặc hybrid

Chi phí và hạ tầng

STUN server: miễn phí
Google cung cấp stun:stun.l.google.com:19302 công khai.

TURN server: $0.01-0.05/GB
Chỉ dùng khi P2P fail (15-20% kết nối). Self-hosted coturn hoặc managed service (Twilio, Xirsys).

SFU server:

Ước tính:

  • 100 phòng 4 người, mỗi phòng 30 phút/ngày
  • Bandwidth: ~80% P2P (miễn phí), 20% TURN = 24 GB/ngày TURN
  • Chi phí TURN: $0.48-1.2/ngày ($15-36/tháng)
  • SFU self-hosted: server $40-80/tháng (8GB RAM, 4 vCPU)

Khi nào không nên dùng WebRTC

1. Broadcast một chiều đến hàng nghìn người
WebRTC tốn bandwidth cho mỗi viewer. Dùng HLS/DASH (CDN-friendly, buffer 5-10s OK).

2. Recording session trên server bắt buộc
P2P khó record. Cần force relay qua SFU hoặc dùng giải pháp khác (RTMP).

3. Môi trường network bị block UDP
WebRTC ưu tiên UDP, fallback TCP qua TURN nhưng chất lượng kém. Một số enterprise firewall chặn cứng.

4. Cần hỗ trợ IE11 hoặc Safari cũ
WebRTC mới được Safari hỗ trợ đầy đủ từ iOS 11/macOS High Sierra (2017). IE11 không bao giờ hỗ trợ.

Debug và monitoring

Chrome DevTools:
chrome://webrtc-internals - xem real-time stats: bitrate, packet loss, codec, ICE candidates.

Key metrics:

  • Packet loss: < 2% tốt, > 5% ảnh hưởng chất lượng
  • RTT (Round Trip Time): < 100ms tốt
  • Jitter: < 30ms

Monitoring production:

pc.getStats().then(stats => {
  stats.forEach(report => {
    if (report.type === 'inbound-rtp' && report.kind === 'video') {
      console.log('Packets lost:', report.packetsLost);
      console.log('Jitter:', report.jitter);
      console.log('Bitrate:', report.bytesReceived * 8 / report.timestamp);
    }
  });
});

Gửi metrics này về analytics server để track quality của service.

Xu hướng mới: AV1, simulcast, e2e encryption

AV1 codec:
Nén tốt hơn VP9 30%, nhưng encode chậm. Chrome đã hỗ trợ từ 2023, đang phổ biến dần.

Simulcast:
Gửi cùng lúc 3 quality (720p, 480p, 240p), SFU chọn quality phù hợp cho từng receiver. Tiết kiệm bandwidth downstream.

Insertable streams (E2EE):
API mới cho phép encrypt media trước khi gửi (end-to-end encryption ngay cả khi qua SFU). Zoom, Google Meet đang áp dụng.

Kết luận

WebRTC đã chuyển video call từ app native phức tạp thành 200 dòng JavaScript chạy trên mọi trình duyệt.

Độ trễ thấp. Bảo mật built-in. Chi phí hợp lý khi thiết kế đúng kiến trúc.

Ba điều cần nhớ:

  • P2P cho 90% performance — nhưng cần TURN làm fallback cho 10% còn lại
  • Mesh chỉ chịu 4 người, SFU mở rộng được
  • DataChannel không chỉ chat — game, file transfer, mọi thứ real-time đều dùng được

Công nghệ này là xương sống của ứng dụng collaboration hiện đại. Hiểu WebRTC là hiểu cách internet real-time hoạt động.

Đọc thêm:

Câu hỏi thường gặp

WebRTC khác gì so với các giải pháp streaming truyền thống?

WebRTC cho phép kết nối peer-to-peer trực tiếp giữa các trình duyệt mà không cần server trung gian để truyền tải media, giảm độ trễ xuống dưới 500ms so với vài giây của streaming qua server. Tuy nhiên, vẫn cần STUN/TURN server để thiết lập kết nối ban đầu qua NAT và firewall.

Những ứng dụng nào nên dùng WebRTC?

WebRTC lý tưởng cho video call, live streaming tương tác, game multiplayer real-time, chia sẻ màn hình, và truyền file P2P. Không phù hợp cho broadcast một chiều đến hàng nghìn người (nên dùng HLS/DASH) hoặc khi cần recording trên server.

WebRTC có hoạt động trên mobile không?

Có, WebRTC được hỗ trợ native trên Chrome/Safari iOS và Android từ 2015. Tuy nhiên cần xử lý cẩn thận lifecycle (ứng dụng chuyển background), battery drain, và fallback khi mạng yếu.

Chi phí bandwidth và server cho WebRTC như thế nào?

Bandwidth từ thiết bị người dùng (upload video HD tốn 2-3 Mbps). STUN server miễn phí (Google cung cấp), TURN server tính theo lượng traffic relay khi P2P thất bại (khoảng 15-20% connection), khoảng $0.01-0.05/GB.

#webrtc#real-time-communication#peer-to-peer#video-call#streaming