IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series ESP-WebRTC: WebRTC Là Gì? ICE, STUN, TURN Giải Thích Bằng Hình

Trước khi viết một dòng code ESP-WebRTC nào, bạn cần hiểu WebRTC hoạt động như thế nào bên dưới. Bài này giải thích toàn bộ cơ chế — từ ICE candidate đến STUN/TURN — bằng ngôn ngữ thực tế, không phải RFC.

WebRTC Là Gì?

WebRTC (Web Real-Time Communication) là bộ giao thức cho phép hai thiết bị trao đổi audio, video và data trực tiếp với nhau — peer-to-peer, không qua server trung gian.

Điều này khác hoàn toàn với HTTP hay MQTT: thay vì client gửi lên server rồi server forward xuống, WebRTC thiết lập đường truyền thẳng giữa hai đầu. Latency có thể xuống dưới 100ms vì data không phải đi vòng qua cloud.

ESP-WebRTC của Espressif đưa bộ giao thức này lên vi điều khiển ESP32 — cho phép camera ESP32 stream video thẳng về browser của bạn mà không cần server video.

Vấn Đề: Hai Thiết Bị Không Thể Nói Chuyện Thẳng

Lý thuyết nghe hay, nhưng thực tế có một vấn đề lớn: NAT (Network Address Translation).

Điện thoại bạn, laptop bạn, ESP32 của bạn — tất cả đều ngồi sau router nhà, có địa chỉ IP private (192.168.x.x hoặc 10.x.x.x). Bên ngoài internet không thể kết nối trực tiếp vào IP private đó.

Hai thiết bị ở hai mạng khác nhau → không thể mở kết nối P2P trực tiếp. Đây là lý do WebRTC cần ICE, STUN, và TURN.

📷 [Hình minh hoạ: Sơ đồ NAT — ESP32 sau router A, browser sau router B, không thể kết nối trực tiếp]

ICE: Tìm Đường Kết Nối

ICE (Interactive Connectivity Establishment) là quá trình hai peer thử tất cả mọi cách có thể để kết nối với nhau.

ICE thu thập candidates — các địa chỉ IP:port có thể dùng để nhận kết nối:

Loại CandidateMô TảVí Dụ
HostIP private của thiết bị192.168.1.100:54321
Server ReflexiveIP public nhìn từ STUN server203.0.113.10:54321
RelayIP của TURN server (fallback)turn.example.com:3478

ICE sẽ thử từng cặp candidate (local ↔ remote) theo thứ tự ưu tiên: host → server reflexive → relay. Cặp nào kết nối được đầu tiên thì dùng.

STUN: Tìm IP Public

STUN (Session Traversal Utilities for NAT) là server đơn giản làm một việc: nói cho thiết bị biết IP public của nó là gì.

ESP32 → STUN Server: "Tôi là ai?"
STUN Server → ESP32: "IP public của bạn là 203.0.113.10, port 54321"

ESP32 dùng thông tin này tạo server reflexive candidate, rồi gửi cho peer kia biết để thử kết nối. Trong nhiều trường hợp (NAT full-cone hoặc restricted-cone), STUN đủ để thiết lập P2P.

Google có STUN server public: stun.l.google.com:19302 — esp-webrtc-solution dùng mặc định này.

TURN: Relay Khi P2P Thất Bại

TURN (Traversal Using Relays around NAT) là fallback khi P2P không thể thiết lập — thường gặp với symmetric NAT (router mỗi lần đổi port khác nhau, STUN không dùng được).

Với TURN, traffic đi qua TURN server:

ESP32 → TURN Server → Browser
Browser → TURN Server → ESP32

Latency tăng lên vì có relay, nhưng đảm bảo kết nối được 100%. Bài 08 hướng dẫn deploy coturn (TURN server open-source).

SDP: Mô Tả Khả Năng Của Mỗi Bên

Trước khi stream bắt đầu, hai peer phải thỏa thuận: codec nào dùng? Resolution bao nhiêu? Encryption key gì?

SDP (Session Description Protocol) là định dạng văn bản mô tả tất cả thông tin này. Ví dụ đoạn SDP cho audio:

m=audio 9 UDP/TLS/RTP/SAVPF 111
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1

Nghĩa là: dùng Opus codec, sample rate 48kHz, 2 channels.

Signaling: Trao Đổi SDP Và Candidates

WebRTC không định nghĩa cách hai peer trao đổi SDP và ICE candidates. Bạn phải tự implement bằng bất kỳ giao thức nào — WebSocket, HTTP, MQTT đều được. Đây gọi là signaling.

Quy trình offer/answer:

Peer A (ESP32)                    Signaling Server              Peer B (Browser)
    │                                    │                            │
    ├── createOffer() ──────────────────►│                            │
    │   (SDP + ICE candidates)           ├──────────────────────────►│
    │                                    │                            ├── setRemoteDescription()
    │                                    │◄──────────── createAnswer()┤
    │◄───────────────────────────────────┤   (SDP + ICE candidates)  │
    ├── setRemoteDescription()           │                            │
    │                                    │                            │
    └─────────────── P2P Connection ─────────────────────────────────┘

esp-webrtc-solution hỗ trợ nhiều signaling protocol: WHIP, AppRTC, OpenAI Realtime, Amazon KVS, Janus. Bài 07 sẽ đi sâu vào WHIP — protocol đơn giản nhất để tự deploy.

DTLS và SRTP: Bảo Mật

WebRTC bắt buộc mã hóa. Sau khi ICE kết nối thành công:

  • DTLS handshake: trao đổi key qua UDP
  • SRTP: mã hóa audio/video stream
  • SCTP over DTLS: mã hóa data channel

Tất cả diễn ra tự động — esp-webrtc-solution xử lý hết phần này, bạn không cần implement.

Tóm Tắt Flow Đầy Đủ

1. Signaling: ESP32 và Browser trao đổi SDP + ICE candidates
2. ICE: thử từng cặp candidate để tìm đường P2P
3. STUN: xác định IP public của mỗi bên
4. TURN: relay nếu P2P thất bại
5. DTLS: handshake mã hóa
6. SRTP/SCTP: stream audio/video/data đã mã hóa

📷 [Hình minh hoạ: Flow diagram đầy đủ WebRTC từ signaling đến streaming]

Tại Sao Phù Hợp Với ESP32?

esp-webrtc-solution của Espressif implement toàn bộ stack này trên ESP32: ICE agent, DTLS, SRTP, và các signaling adapter. Multi-threaded design đảm bảo encode, network, và decode chạy song song.

Bài tiếp theo: Cài SDK và Build Demo Đầu Tiên Trên ESP32-P4