ARQ. 4

ffmpeg → HLS estático

La más simple posible — ffmpeg escribe segmentos .ts, Oasis los sirve como ficheros estáticos
RAM
~30 MB
CPU
10–25%
Latencia
4–12 s
Complejidad
Mínima
Contexto
Baseline

Diagrama de Arquitectura

┌──────────────────────────────────────────────────────┐
│              Raspberry Pi 3B (Debian / Docker)       │
│                                                      │
│  ┌────────────┐         ┌────────┐       ┌─────────┐│
│  │ 🎥 Cam     │─v4l2──▶│ ffmpeg │──.ts─▶│ /var/   ││
│  │   CSI/USB  │         │        │  .m3u8│ www/    ││
│  │ 🎤 Mic USB │─ALSA──▶│ (~30MB)│──────▶│ stream/ ││
│  └────────────┘         └────────┘       └────┬────┘│
│                                               │     │
│                                          ┌────┴────┐│
│                                          │  Oasis  ││
│                                          │  :3000  ││
│                                          │  static ││
│                                          └────┬────┘│
└───────────────────────────────────────────────┼─────┘
                                                │
                                     ┌──────────┴──────────┐
                                     │  Navegador (cero JS)│
                                     │                     │
                                     │  <video             │
                                     │   src="/stream/     │
                                     │        live.m3u8"   │
                                     │   autoplay muted    │
                                     │   playsinline       │
                                     │   controls>         │
                                     │  </video>           │
                                     └─────────────────────┘

El concepto

Sin servidor media, sin node-datachannel, sin paquetes npm para media. Solo ffmpeg escribiendo segmentos HLS a disco y Oasis sirviéndolos como ficheros estáticos. Es la arquitectura de mínima complejidad: un solo comando ffmpeg + un directorio estático. Funciona en Chrome/Safari sin JS.

El Comando

ffmpeg -f v4l2 -i /dev/video0 \ -f alsa -i default \ -c:v libx264 -preset ultrafast -tune zerolatency \ -c:a aac -b:a 64k \ -f hls -hls_time 2 -hls_list_size 5 \ -hls_flags delete_segments \ /var/www/stream/live.m3u8
Un solo comando. Captura vídeo (V4L2) y audio (ALSA), codifica H.264 + AAC, genera segmentos HLS de 2 s con ventana deslizante de 5 segmentos (~10 s). Borra segmentos antiguos automáticamente.

HTML del Consumidor

<video src="/stream/live.m3u8" autoplay muted playsinline controls> </video>
Oasis sirve /var/www/stream/ como directorio estático. El browser consume el .m3u8 nativamente (Safari siempre; Chrome 142+ con soporte MSE mejorado). Sin JS, sin WebSocket, sin signaling.

Parámetros ffmpeg explicados

ParámetroValorPor qué
-f v4l2 -i /dev/video0Captura V4L2Funciona con CSI (vía bcm2835-v4l2) y USB
-f alsa -i defaultCaptura ALSAMicrófono USB, device por defecto
-c:v libx264Encode H.264 swultrafast = mínimo CPU; alt: h264_v4l2m2m (HW)
-preset ultrafastVelocidad máx.Calidad baja pero ~10% CPU vs ~40% con medium
-tune zerolatencySin bufferReduce latencia encode ~200 ms
-c:a aac -b:a 64kAudio AACCompatible con HLS; 64k suficiente para voz
-hls_time 2Segmentos de 2 sBalance latencia/overhead. Mín. práctico ~1 s
-hls_list_size 5Ventana 5 seg.~10 s de buffer. Evita acumulación infinita
-hls_flags delete_segmentsBorrar viejosEvita llenar la microSD

CSI vs USB: variante del comando

CSIUSB (MJPEG)USB (H.264 HW)
Encoderpicam-vid→pipe o libx264libx264 / h264_v4l2m2m-c:v copy (passthrough)
CPU~5% (HW) / ~15% (SW)~15–25%~3%
NotaAlt: rpicam-vid --codec h264 -o - | ffmpeg -f h264 -i - …Decode MJPEG + encode H.264Mejor caso USB
# Variante CSI con HW encode (menor CPU): rpicam-vid -t 0 --codec h264 --inline -w 1280 -h 720 -o - | \ ffmpeg -f h264 -i - -f alsa -i default \ -c:v copy -c:a aac -b:a 64k \ -f hls -hls_time 2 -hls_list_size 5 \ -hls_flags delete_segments \ /var/www/stream/live.m3u8 # Variante USB con H.264 HW encode del RPi: ffmpeg -f v4l2 -input_format mjpeg -video_size 1280x720 \ -i /dev/video0 -f alsa -i default \ -c:v h264_v4l2m2m -b:v 1M -c:a aac -b:a 64k \ -f hls -hls_time 2 -hls_list_size 5 \ -hls_flags delete_segments \ /var/www/stream/live.m3u8

Lo que obtienes

✔ Tienes✘ No tienes
Vídeo + audio en browser sin JSLatencia baja (4–12 s mínimo)
Complejidad mínima absolutaAudio/vídeo bidireccional
Funciona sobre Tor (HTTP puro)MJPEG (solo HLS)
~20 líneas de código totalSnapshots JPEG nativos
Safari nativo, Chrome 142+WebRTC / P2P real
Sin dependencias nuevas (ffmpeg ya instalado)Multi-protocolo (solo HLS)

Comparativa directa

Arq. 4 (ffmpeg→HLS)Arq. 1 (go2rtc)Arq. 6 (µStreamer)
ComplejidadMínimaBajaBaja
Latencia vídeo4–12 s100–300 ms100–300 ms
Latencia audio4–12 s200 ms–2 s~200 ms (Mumble)
Bidireccional✔ WHEP✔ (Mumble)
ffmpegSí (permanente)NoNo
Escrit. µSD⚠ ConstanteNoNo
Tor✔ (HTTP puro)⚠ TURN⚠ HTTP solo
FormatosSolo HLSMJPEG+HLS+WHEP+RTSPSolo MJPEG
RAM~30 MB~20–40 MB~5–15 MB
Binario extraNo (ffmpeg existe)Sí (~15 MB Go)Sí (~1 MB C)

Riesgos Críticos

RiesgoImpactoMitigación
Escritura constante a microSD ALTO — segmentos .ts cada 2 s → desgaste flash, especialmente en RPi solar sin UPS Montar /var/www/stream en tmpfs (RAM): mount -t tmpfs -o size=20m tmpfs /var/www/stream
Latencia inherente HLS (4–12 s) Alto — inaceptable para vigilancia o interacción en tiempo real Reducir hls_time a 1 s (ayuda poco). Para <1 s necesitas MJPEG → Arq. 1/6
ffmpeg CPU constante Medio — encode SW ~15–25% CPU permanente mientras haya stream h264_v4l2m2m para HW encode (CSI: rpicam-vid pipe, USB: v4l2m2m)
Sin bidireccionalidad Medio — no hay canal de vuelta para audio ni datos Añadir Mumble para audio retorno → se convierte en Arq. 3
Firefox no soporta HLS nativo Bajo — Firefox requiere JS (hls.js) para HLS→MSE Aceptar limitación o añadir MJPEG fallback → ya no es Arq. 4

tmpfs: mitigar escritura a SD

# /etc/fstab — montar stream en RAM tmpfs /var/www/stream tmpfs defaults,noatime,size=20m 0 0 # O manualmente: mount -t tmpfs -o size=20m tmpfs /var/www/stream
Con 5 segmentos × 2 s a ~500 KB/seg = ~5 MB rotando. 20 MB de tmpfs es sobrado. Coste: 20 MB de RAM extra (~50 MB total para Arq. 4). Pero elimina el riesgo de desgaste flash.

systemd (si se necesita)

# /etc/systemd/system/ffmpeg-hls.service [Unit] Description=ffmpeg HLS streaming After=network-online.target RequiresMountsFor=/var/www/stream [Service] Type=simple User=ffmpeg Group=video,audio ExecStartPre=/bin/mkdir -p /var/www/stream ExecStart=/usr/bin/ffmpeg \ -f v4l2 -i /dev/video0 \ -f alsa -i default \ -c:v libx264 -preset ultrafast -tune zerolatency \ -c:a aac -b:a 64k \ -f hls -hls_time 2 -hls_list_size 5 \ -hls_flags delete_segments \ /var/www/stream/live.m3u8 Restart=on-failure RestartSec=5 MemoryMax=80M CPUQuota=40% [Install] WantedBy=multi-user.target

¿Cuándo elegir Arq. 4?

Casi nunca. La Arq. 4 existe como baseline teórico — demuestra que se puede hacer streaming con cero infraestructura nueva. Pero en la práctica: Su único caso válido: un prototipo rápido para demostrar que el pipeline funciona antes de elegir la arquitectura real.
ffmpeg HLS .m3u8 .ts estático tmpfs ultrafast zero-infra baseline baseline