┌──────────────────────────────────────────────────────────────────┐
│ RASPBERRY PI 3B · SOLAR NET HUB │
│ BCM2837 · Cortex-A53 · VideoCore IV │
│ │
│ ┌──────────┐ MMAL/ ┌─────────────────────────┐ │
│ │ 🎥 CAM │─libcam──▷│ RPi-WebRTC :8889 │ │
│ │ CSI ONLY │ zero-copy│ ┌───────────────────────┐│ │
│ └──────────┘ │ │H.264 HW encode (VC IV)││ │
│ │ │Opus audio (ALSA) ││ │
│ ┌──────────┐ ALSA │ │ICE + DTLS-SRTP ││ │
│ │ 🎤 MIC │────────▷│ │DataChannel (SCTP) ││ │
│ └──────────┘ │ │Señalización HTTP+WS ││ │
│ │ └───────────────────────┘│ │
│ └──────────┬──────────────┘ │
│ │ WebRTC (localhost) │
│ ┌────────────────────────────────┴──────────────────────────┐ │
│ │ OASIS :3000 (Node.js · SSB · cero JS en browser) │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ WebRTC Consumer (node-datachannel) │ │ │
│ │ │ Conecta como peer a RPi-WebRTC (localhost) │ │ │
│ │ │ Recibe H.264 RTP → ffmpeg decode → MJPEG │ │ │
│ │ │ Recibe Opus RTP → ffmpeg decode → OGG/WAV │ │ │
│ │ └────────────┬──────────────────┬─────────────────────┘ │ │
│ │ │ │ │ │
│ │ GET /video → MJPEG stream GET /audio → OGG stream │ │
│ │ │ │
│ │ webrtc_view → <img src="/video"> + <audio src="/audio"> │ │
│ │ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ node-datachannel (P2P DataChannels) │ │ │
│ │ │ texto · archivos · señalización SSB │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌────────────┐ ┌─────────────┐ ┌─────────────┐
│ 📺 BROWSER │ │ 📡 PEER │ │ 🔊 BROWSER │
│ LAN (no JS)│ │ REMOTO │ │ REMOTO │
│ <img>MJPEG │ │ WebRTC P2P │ │ WebRTC P2P │
│ <audio>OGG │ │ nativo !! │ │ video+audio │
│ vía proxy │ │ ICE+DTLS │ │ ~100ms lat. │
└────────────┘ └─────────────┘ └─────────────┘
RTCPeerConnection, setRemoteDescription). Esto viola la restricción de Oasis (cero JS en cliente). El proxy Node.js consume WebRTC en localhost y re-sirve como MJPEG/OGG puro (HTML <img> / <audio>).| Propiedad | Estado |
|---|---|
| Cero JS en browser SNH | ✔ (vía proxy) |
| Cámara CSI | ✔ (zero-copy HW) |
| Cámara USB | ✘ No soportada |
| Audio | Opus (ALSA→libwebrtc) |
| Audio bidireccional | ⚠️ Solo vía DataChannel |
| Funciona sobre Tor | ⚠️ Necesita TURN |
| MJPEG streaming | ✔ (vía proxy) |
| HLS para remoto | ✘ No nativo |
| WebRTC P2P (media) | ✔ Nativo !! |
| DataChannels P2P (data) | ✔ |
| RAM nuevos procesos | ~80–100 MB |
| CPU vídeo (CSI) | ~15–20% |
| Campo | Valor |
|---|---|
| Lenguaje | C++ (basado en libwebrtc de Google, parcheado para RPi) |
| Repo | github.com/kclyu/rpi-webrtc-streamer |
| Licencia | BSD (derivado de libwebrtc / Chromium) |
| Arquitectura | WebRTC nativo completo: señalización + ICE + DTLS-SRTP + H.264 HW |
| Captura | MMAL (legacy) / libcamera (moderno). Solo cámaras CSI |
| Encode | H.264 HW del VideoCore IV/VI, zero-copy. Sin ffmpeg |
| Transporte | SRTP sobre DTLS, ICE completo (host / srflx / relay) |
| Señalización | HTTP + WebSocket embebidos. Compatible AppRTC signaling |
| Audio | ALSA capture → Opus encode (libwebrtc AudioEncoder) |
| DataChannel | ✔ SCTP sobre DTLS (igual que browsers) |
| RAM típica | ~30–50 MB (libwebrtc pesada, pero encode es HW) |
| CPU RPi 3B | ~10–15% (encode HW) + ~5% (ICE/DTLS/SRTP) = ~15–20% total |
| Binario | ~25–40 MB (libwebrtc compilada estáticamente). Cross-compile x86→ARM |
| Estado | ⚠️ Mantenimiento irregular. Último commit significativo: 2023. Fork community activo |
| USB | ❌ No soportadas. Requiere MMAL/libcamera (solo CSI) |
| Criterio | RPi-WebRTC | go2rtc | MediaMTX | µStreamer |
|---|---|---|---|---|
| Protocolo salida | WebRTC nativo (SRTP) | MJPEG, HLS, WebRTC, RTSP | RTSP, HLS, WebRTC, MJPEG | MJPEG, JPEG |
| Cam CSI | ✔ MMAL/libcamera, zero-copy | ✔ vía V4L2 (con copia) | ✔ rpicam nativo (zero-copy) | ✔ V4L2 M2M HW |
| Cam USB | ✘ No | ✔ V4L2 directo | ✔ V4L2 directo | ✔ V4L2 directo |
| Encode H.264 HW | ✔ Nativo, sin ffmpeg | ⚠️ Solo si fuente ya es H.264 | ✔ rpicam nativo (CSI) | ✘ Solo MJPEG |
| Browser sin JS | ✘ Requiere JS (WebRTC API) | ✔ MJPEG/HLS | ✔ MJPEG/HLS | ✔ MJPEG puro |
| Tor | ✘ WebRTC+ICE incompatible | ⚠️ MJPEG/HLS sí | ⚠️ MJPEG/HLS sí | ✔ HTTP puro |
| Señalización | ✔ HTTP+WS embebidos | ✔ API HTTP | ✔ Hooks HTTP | ✘ No tiene |
| RAM | ~30–50 MB | ~20–40 MB | ~15–30 MB | ~5–15 MB |
| Compilación | Alta (libwebrtc, ~4 GB build) | Baja (binario Go) | Baja (binario Go) | Baja (C, apt/make) |
| Madurez | ⚠️ Irregular desde 2023 | ✔ Activo (7k ★) | ✔ Activo (13k ★) | ✔ Activo (pikvm) |
┌──────────────────────────────────────────────────────────────────┐ │ Raspberry Pi 3B (Solar Net Hub) │ │ │ │ ┌──────────┐ MMAL ┌───────────────┐ WebRTC ┌─────────┐ │ │ │ 🎥 CSI │────────▷│ RPi-WebRTC │──(WHEP)──▷│ go2rtc │ │ │ └──────────┘ │ H.264 HW │ │ :1984 │ │ │ │ zero-copy │ │ │ │ │ ┌──────────┐ ALSA │ + Opus audio │ │ MJPEG │ │ │ │ 🎤 Mic │────────▷│ :8889 │ │ HLS │ │ │ └──────────┘ └───────────────┘ │ JPEG │ │ │ └────┬────┘ │ │ │ │ │ ┌─────────────────────────────────────────────────────┤ │ │ │ Node.js (Oasis :3000) │ │ │ │ Sirve HTML con <img>/<video> apuntando a go2rtc │ │ │ └─────────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────────────┘
| Fase | Alcance | Ficheros / componentes |
|---|---|---|
| 0. Detección HW | Verificar CSI presente. Abortar si solo USB | hardware_detect.js |
| 1. DataChannel | Idéntico al Camino A (P2P datos) | webrtc_model.js, webrtc_view.js, backend.js |
| 2. Señalización SSB | Idéntico al Camino A | signaling/ssb.js, signaling/index.js |
| 3. Captura + encode | RPi-WebRTC: CSI + H.264 HW + Opus. Server en :8889 | rpi-webrtc-streamer (binario C++, ARM64) |
| 3b. Proxy WebRTC→HTTP | Node.js peer local → decode → MJPEG/OGG | media_proxy.js (~200 lín, usa node-datachannel) |
| 4. File transfer | Idéntico al Camino A | Extensión de webrtc_model.js |
webrtc_view.js ─── renderiza HTML con <img>/<video>/<audio> sin JS
│
backend.js ────── rutas GET/POST /webrtc/*
│
webrtc_model.js ── estado + node-datachannel (DataChannel para datos)
│
media_proxy.js ─── consume WebRTC de RPi-WebRTC (localhost:8889)
│ └─ decode H.264→MJPEG (ffmpeg)
│ └─ decode Opus→OGG (ffmpeg)
│ └─ sirve GET /video, GET /audio
│
RPi-WebRTC ─────── binario C++: CSI → H.264 HW → WebRTC server (:8889)
│
signaling/ ────── abstracción: manual | ssb | ssb-lan
| Riesgo | Probabilidad | Impacto | Mitigación |
|---|---|---|---|
| RPi-WebRTC deja de compilar en kernels nuevos | Media-Alta | Bloqueante | Mantener fork o fallback a Arq. 3 (go2rtc) |
| libwebrtc ~4 GB build time | Segura | DX | Cross-compile x86→ARM. Pre-build binario. CI/CD |
| Cámara USB en el futuro | Media | Bloqueante | hardware_detect.js → cambio automático a Arq. 3 |
| RAM ~80–100 MB en device de 1 GB | Segura | Alto | Monitorizar con cgroups. Fallback a Arq. 6 (~10–20 MB) |
| Tor incompatible con WebRTC/ICE | Segura | Medio | Para Tor: proxy MJPEG/HLS sin WebRTC, o usar Arq. 3 (Mumble) |