RAM
20–40 MB
CPU
5–20%
Latencia vídeo
100–300 ms
Binario
~15 MB
Contexto
General
Diagrama de Arquitectura
┌───────────────────────────────────────────────────────────┐
│ Raspberry Pi 3B (Debian / Docker) │
│ │
│ ┌────────────┐ v4l2/ALSA ┌──────────┐ HTTP ┌─────┐│
│ │ 🎥 Cam │─────────────▶│ go2rtc │───────▶│Oasis││
│ │ CSI/USB │ │ :1984 │ MJPEG │:3000││
│ │ 🎤 Mic USB │─────────────▶│ │ HLS │ ││
│ └────────────┘ │ (20 MB) │ JPEG │ HTML││
│ └──────────┘ └─────┘│
│ │ │ │
│ WebRTC │ │
│ WHEP │ │
│ │ │ │
└───────────────────────────────────┼──────────────────┼───┘
│ │
┌──────────┴──────────────────┴──┐
│ Navegador (cero JS) │
│ │
│ <img src="/video.mjpeg"> │
│ <video src="/video.m3u8"> │
│ <audio src="/audio.ogg"> │
│ │
│ Oasis sirve HTML con URLs │
└────────────────────────────────┘
1 · ¿Qué es go2rtc?
Binario Go estático (~15 MB) que captura directamente de V4L2 (cámara) y ALSA (micrófono) y re-sirve en múltiples protocolos: MJPEG, HLS, WebRTC (WHEP), RTSP, snapshots JPEG. Sin ffmpeg intermedio. Transcodifica PCMA/PCMU → FLAC automáticamente para MSE/HLS. Incluye Web UI en :1984 y API HTTP + WebSocket.
2 · ¿Por qué "relay integral"?
go2rtc cubre captura + transcodificación ligera + serving multi-protocolo todo en un solo proceso. Elimina ffmpeg y node-datachannel del pipeline de media. Node.js (Oasis) solo sirve el HTML apuntando a los endpoints de go2rtc — queda libre de toda carga de media.
3 · CSI y USB: ambas soportadas
go2rtc lee
cualquier cámara expuesta como V4L2 — funciona con CSI y USB sin cambiar la config base. Para CSI se puede optar por
exec:rpicam-vid (encode H.264 HW) para máxima eficiencia. Para USB con H.264 nativo:
v4l2:///dev/video0#format=h264 (passthrough).
La arquitectura más flexible en hardware. → Comparación completa en poster CSI/USB
⚠️ USB H.264 encoding: cámaras USB sin H.264 nativo requieren paso extra (UVC → buffer userspace → V4L2 M2M
/dev/video11 → H.264 HW). Overhead CPU ~10–15% por la copia y conversión de formatos. Ver
poster CSI/USB para detalles.
(Fuente: web-rtc-ext.md EXT-2)
4 · Simplicidad máxima
Config: ~10 líneas YAML. Un binario. Un fichero de config. Un systemctl start. Sin dependencias de runtime. Probado en miles de despliegues Home Assistant / Frigate. Complejidad mínima — ideal para Fase 1 (LAN).
5 · Límite: Tor y señalización
go2rtc no gestiona señalización SSB — eso sigue siendo trabajo de Node.js. Para Fase 3 (Internet vía Tor), WebRTC necesita TURN, y TURN no funciona bien sobre Tor (UDP bloqueado, TCP >500 ms). Para Tor, Arq. 3 (Mumble) es mejor. En LAN, Arq. 1 es imbatible en simplicidad.
Componentes
| Componente | Función | RAM | Protocolo |
| go2rtc |
Captura V4L2/ALSA → MJPEG, HLS, WHEP, RTSP, JPEG |
~20–40 MB |
HTTP :1984 |
| Oasis |
Proxy HTML → endpoints go2rtc. Sin carga media. |
~80 MB |
HTTP :3000 |
| node-datachannel |
Solo si P2P remoto (DataChannel texto/archivos) |
~20 MB |
WebRTC via SDP SSB |
Ficha Rápida
| Campo | Valor |
| Repo | github.com/AlexxIT/go2rtc |
| Lenguaje | Go (binario estático) |
| Licencia | MIT |
| Binario ARM | ~15 MB (pre-compilado, wget + chmod) |
| Entrada | V4L2, ALSA, RTSP, RTMP, ffmpeg exec, MJPEG, WHEP |
| Salida | MJPEG, HLS (.m3u8), MP4 progressive, WHEP, RTSP, JPEG |
| Transcodificación | PCMA/PCMU/PCM → FLAC auto (MSE/HLS); resampling WebRTC |
| Web UI | Sí (:1984) — API HTTP + WebSocket |
| ffmpeg necesario | No (captura directa V4L2/ALSA) |
| Cámara | CSI ✔ · USB ✔ · Ambas ✔ |
| Contexto | General — si no se necesita Tor para audio; simplicidad máxima |
Config: CSI vs USB
go2rtc.yaml — CSI
streams:
solar-cam:
- v4l2:///dev/video0
solar-mic:
- alsa:///default
api:
listen: "127.0.0.1:1984"
go2rtc.yaml — USB
streams:
solar-cam:
- v4l2:///dev/video0
solar-mic:
- alsa:///default
api:
listen: "127.0.0.1:1984"
| go2rtc + CSI | go2rtc + USB |
| Captura | V4L2 o exec rpicam-vid | V4L2 directo (MJPEG/YUYV) |
| Encode H.264 | HW vía rpicam-vid exec | Solo si webcam lo entrega nativo |
| RAM | ~20–30 MB | ~20–40 MB |
| CPU | ~5–10% | ~10–20% |
| Docker flags | --device /dev/video0 --device /dev/vchiq | --device /dev/video0 |
Endpoints go2rtc (:1984)
| Endpoint | Protocolo | HTML sin JS | Latencia |
| /api/frame.mjpeg?src=solar-cam | MJPEG | ✔ <img> | 100–300 ms |
| /api/stream.m3u8?src=solar-cam | HLS fMP4 | ✔ <video> | 2–6 s |
| /api/frame.jpeg?src=solar-cam | JPEG snapshot | ✔ <img> | instantáneo |
| /api/stream.mp4?src=solar-cam | MP4 progressive | ✔ <video> | ~1 s |
| /api/webrtc?src=solar-cam | WebRTC WHEP | ✘ (JS) | ~100 ms |
| /api/stream.m3u8?src=solar-mic | Audio HLS | ✔ <video> | 2–6 s |
| /api/ws?src=solar-mic | WebSocket audio | ✘ (JS) | ~200 ms |
Para audio sin JS: go2rtc transcodifica PCMA→FLAC para HLS. Accesible vía <video src="/api/stream.m3u8?src=solar-mic">. Alternativa: proxy ffmpeg OGG en Oasis.
Integración con Oasis
| Ruta Oasis | Proxy a | HTML |
| GET /video.mjpeg | go2rtc :1984/api/frame.mjpeg?src=solar-cam | <img src="/video.mjpeg"> |
| GET /video.m3u8 | go2rtc :1984/api/stream.m3u8?src=solar-cam | <video src="/video.m3u8"> |
| GET /snapshot | go2rtc :1984/api/frame.jpeg?src=solar-cam | <img src="/snapshot"> |
| GET /audio | ffmpeg RTSP→OGG o HLS go2rtc | <audio src="/audio"> |
Node.js no toca media. Solo proxy reverso HTTP a go2rtc. ~0% CPU extra para Oasis por el streaming.
Comparativa con otras arquitecturas
| Arq. 1 (go2rtc) | Arq. 2 (MediaMTX) | Arq. 3 (Mumble hybrid) | Arq. 6 (µStreamer) |
| Complejidad | Baja | Media | Media | Baja |
| RAM extra | ~20–40 MB | ~15–30 MB | ~65 MB total | ~10–20 MB |
| ffmpeg | No | Solo audio | Solo re-encode bridge | No |
| CSI + USB | ✔ ambas | ✔ CSI / ⚠ USB | ✔ ambas | ✔ ambas |
| Bidireccional | ✔ WHEP | ✔ WebRTC | ✔ Mumble | ✘ |
| Tor compatible | ⚠ TURN | ⚠ TURN | ✔ TCP nativo | ⚠ HTTP only |
| HLS | ✔ | ✔ | ✔ (vía go2rtc) | ✘ |
| MJPEG | ✔ | ✘ (solo snapshot) | ✔ (vía go2rtc) | ✔ |
| Escrit. µSD | No | No | No | No |
Implementación: Camino B
| Fase | Alcance | Ficheros / Componentes |
| 1. DataChannel |
Solo texto (P2P) |
webrtc_model.js, webrtc_view.js, backend.js |
| 2. Señalización SSB |
SDP vía mensajes SSB |
signaling/ssb.js, signaling/index.js |
| 3. Media streams |
go2rtc captura → Oasis sirve HTML con URLs |
go2rtc.yaml (~10 líneas) — no se necesita media_capture.js |
| 4. File transfer |
DataChannel binario |
Extensión de webrtc_model.js |
Impacto: las Fases 1, 2 y 4 son idénticas al Camino A. La Fase 3 reemplaza ~400 líneas de media_capture.js (ffmpeg pipelines) por un go2rtc.yaml de 10 líneas + un binario de 15 MB.
Posición en el Árbol de Decisión
¿CSI?
SÍ → ¿Max eficiencia HW?
NO → ★ Arq. 1 (go2rtc, CSI vía V4L2)
SÍ → Arq. 2 (MediaMTX rpicam)
¿USB?
SÍ → ¿H.264 HW integrado?
SÍ → ★ Arq. 1 (go2rtc, passthrough)
NO → ★ Arq. 1 (go2rtc, MJPEG)
¿Ambas / incierto?
SÍ → ★ Arq. 1 + hardware_detect.js
¿Tor para audio?
SÍ → Arq. 3 (Mumble)
¿Solo LAN + RAM mínima?
SÍ → Arq. 6 (µStreamer)
Arq. 1 gana en 4 de 6 ramas del árbol de decisión. Su límite: Tor (TURN no funciona bien sobre TCP onion).
Riesgos
| Riesgo | Impacto | Mitigación |
| Tor incompatible con WHEP/WebRTC |
Alto — sin audio remoto vía Tor |
Migrar a Arq. 3 (Mumble TCP tunnel) para Fase 3 |
| go2rtc no gestiona señalización SSB |
Medio — P2P remoto requiere Node.js aparte |
node-datachannel + signaling/ssb.js (invariante) |
| Audio sin JS en browser limitado |
Medio — HLS audio funciona, pero latencia 2–6 s |
Proxy ffmpeg RTSP→OGG en Oasis para <audio> nativo |
| USB sin H.264 HW → re-encode SW |
Bajo — ~10–20% CPU más que CSI |
Reducir resolución a 640×480; o Arq. 6 si solo MJPEG |
| Dependencia de binario Go externo |
Bajo — proyecto muy activo (Home Assistant) |
Pin version en config; binario estático sin deps |
go2rtc
V4L2
ALSA
MJPEG
HLS
WHEP
relay
Camino B
zero-ffmpeg
CSI+USB