IoTLabs

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

Series ESP-WebRTC: Signaling Server WHIP — Tự Deploy Trong 30 Phút

WebRTC cần signaling server để trao đổi SDP và ICE candidates giữa ESP32 và browser. Bài này triển khai WHIP — giao thức đơn giản nhất, dễ deploy nhất, và được esp-webrtc-solution hỗ trợ sẵn.

Signaling Là Gì, Tại Sao Cần Nó?

WebRTC tự thiết lập kết nối P2P — nhưng trước đó, hai bên cần biết thông tin của nhau (IP candidates, codec support). Signaling server làm nhiệm vụ này: là “người môi giới” trao đổi metadata, sau đó hai đầu kết nối thẳng.

esp-webrtc-solution hỗ trợ nhiều signaling protocol:

ProtocolMô TảĐộ Phức Tạp
WHIPHTTP-based, chuẩn mới (RFC 9725)Thấp
AppRTCGoogle’s signaling demoTrung bình
JanusFull WebRTC serverCao
OpenAI RealtimeWebSocket + OpenAI APITrung bình
Amazon KVSAWS Kinesis Video StreamsCao

WHIP là lựa chọn tốt nhất để bắt đầu.

WHIP Protocol Là Gì?

WHIP (WebRTC-HTTP Ingestion Protocol) — RFC 9725 (2024) — là giao thức đơn giản để ingest WebRTC stream vào server bằng HTTP:

Client → POST /whip  → Server  (offer SDP)
Server → 201 Created → Client  (answer SDP)

Đó là toàn bộ signaling. Không cần WebSocket, không cần session management phức tạp.

WHEP (WebRTC-HTTP Egress Protocol) là phần đối xứng — browser fetch stream về:

Browser → POST /whep → Server  (offer SDP)
Server  → 201 Created → Browser (answer SDP)
Browser ← RTP stream ←────────  Server

Với ESP32: ESP32 POST offer → nhận answer → kết nối WebRTC thẳng với browser qua WHEP.

Deploy MediaMTX (WHIP/WHEP Server)

MediaMTX (trước gọi là rtsp-simple-server) là media server nhẹ, hỗ trợ WHIP/WHEP/RTSP/HLS, Docker image chỉ 20MB.

Cách 1: Docker (Khuyến Nghị)

# Pull và chạy MediaMTX
docker run -d \
  --name mediamtx \
  -p 8554:8554 \   # RTSP
  -p 8889:8889 \   # WebRTC/WHIP/WHEP (HTTP)
  -p 8890:8890/udp \ # WebRTC UDP
  bluenviron/mediamtx:latest

Kiểm tra server chạy:

curl http://localhost:8889/
# → MediaMTX đang chạy

Cách 2: Binary Trực Tiếp

# Download MediaMTX
wget https://github.com/bluenviron/mediamtx/releases/latest/download/mediamtx_linux_amd64.tar.gz
tar -xzf mediamtx_linux_amd64.tar.gz

# Chạy
./mediamtx

📷 [Hình minh hoạ: Architecture diagram: ESP32 → WHIP POST → MediaMTX → WHEP → Browser]

Cấu Hình ESP32 Kết Nối WHIP

Trong menuconfig của demo esp-webrtc:

Component config → ESP WebRTC Demo
  → Signaling Protocol: WHIP
  → WHIP URL: http://192.168.1.x:8889/esp32-stream/whip
  → WHEP URL: http://192.168.1.x:8889/esp32-stream/whep

Hoặc trong code:

esp_webrtc_cfg_t cfg = {
    .signaling = {
        .type     = ESP_WEBRTC_SIGNALING_WHIP,
        .whip_url = "http://192.168.1.100:8889/mystream/whip",
    },
};

Thay 192.168.1.100 bằng IP máy chủ chạy MediaMTX.

Xem Stream Từ Browser

Sau khi ESP32 đã POST WHIP offer thành công, browser fetch stream qua WHEP:

  1. Mở http://IP_SERVER:8889/mystream trong browser
  2. MediaMTX tự serve trang web với WebRTC player
  3. Stream từ ESP32 hiển thị với latency ~100–200ms

Hoặc dùng HTML đơn giản:

<video id="video" autoplay muted></video>
<script>
  const pc = new RTCPeerConnection();
  pc.ontrack = e => document.getElementById('video').srcObject = e.streams[0];
  pc.addTransceiver('video', { direction: 'recvonly' });
  pc.addTransceiver('audio', { direction: 'recvonly' });
  const offer = await pc.createOffer();
  await pc.setLocalDescription(offer);

  const resp = await fetch('http://SERVER_IP:8889/esp32-stream/whep', {
    method: 'POST',
    headers: { 'Content-Type': 'application/sdp' },
    body: offer.sdp
  });
  const answerSdp = await resp.text();
  await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
</script>

MediaMTX Trên VPS (Truy Cập Từ Internet)

Để ESP32 và browser truy cập từ mạng khác nhau, deploy MediaMTX trên VPS:

# Trên VPS Ubuntu/Debian
docker run -d \
  --name mediamtx \
  -p 8889:8889 \
  -p 8890:8890/udp \
  -e MTX_WEBRTCADDITIONALHOSTS=VPS_PUBLIC_IP \
  bluenviron/mediamtx:latest

Thêm biến MTX_WEBRTCADDITIONALHOSTS để MediaMTX biết IP public của mình và announce đúng ICE candidates.

Các Signaling Server Khác

Janus WebRTC Server — phức tạp hơn nhưng nhiều tính năng hơn:

# Docker Janus
docker run -d \
  -p 8088:8088 \  # REST API
  -p 8188:8188 \  # WebSocket
  -p 20000-20100:20000-20100/udp \
  canyan/janus-gateway

esp-webrtc-solution có adapter cho Janus trong components/esp_webrtc/signaling/janus/.

AppRTC — server demo của Google, chỉ dùng cho testing.

Bài tiếp theo: NAT Traversal Thực Tế — STUN TURN Cho ESP32 Sau Router