No description
Find a file
Daniel Labella d7bea928c5 fixes
2026-09-25 14:51:24 +02:00
backend fixes 2026-09-25 14:51:24 +02:00
frontend add save to file 2026-09-25 14:47:27 +02:00
.gitignore initial commit 2026-09-24 19:12:55 +02:00
LICENSE Initial commit 2026-09-24 18:54:44 +02:00
README.md initial commit 2026-09-24 19:12:55 +02:00

Streambox

Estación de streaming sobre Raspberry Pi para emitir partidos de vóley a Twitch y YouTube simultáneamente, con control y previsualización desde el móvil.

Características

  • Multistreaming a Twitch y YouTube con una sola instancia de FFmpeg (muxer tee).
  • HLS local en tmpfs para previsualización sin desgaste de SD.
  • Control remoto desde cualquier navegador (móvil o PC).
  • Dos modos de emisión:
    • Preview: FFmpeg arranca solo con HLS local, sin emitir a plataformas.
    • OnAir: FFmpeg arranca con HLS + RTMP a Twitch y YouTube.
  • Placeholder del .m3u8 para evitar 404 durante el arranque.
  • Detección automática del formato de cámara (H.264 nativo vs MJPG/YUYV con recodificación).
  • Backend optimizado: cachés de CPU y estado, limpieza de FFmpeg huérfanos.
  • Frontend optimizado: polling adaptativo, pausa al ocultar pestaña.

Arquitectura

┌──────────────┐      ┌──────────────────────┐      ┌──────────┐
│ Cámara USB   │─────▶│  FFmpeg (muxer tee)  │─────▶│  Twitch  │
│ (H.264/MJPG) │      │                      │      └──────────┘
└──────────────┘      │                      │      ┌──────────┐
                      │                      │─────▶│ YouTube  │
                      │                      │      └──────────┘
                      │                      │      ┌──────────┐
                      │                      │─────▶│ HLS tmpfs│
                      └──────────────────────┘      └──────────┘
                                ▲                         │
                                │                         ▼
                      ┌──────────────────────┐    ┌──────────────┐
                      │  Flask API (5000)    │◀───│ Navegador    │
                      │  + control FFmpeg    │    │ (móvil/PC)   │
                      └──────────────────────┘    └──────────────┘

Requisitos

  • Raspberry Pi 3/4/5 con Raspberry Pi OS o DietPi (64-bit recomendado).
  • FFmpeg, Python 3, Flask.
  • Cámara USB (idealmente con H.264 nativo, como la Logitech C925e).
  • Conexión a internet para emitir a Twitch/YouTube.

Instalación

1. Dependencias

apt update
apt install -y ffmpeg python3 python3-flask alsa-utils v4l-utils

2. Estructura de directorios

mkdir -p /opt/streambox/backend
mkdir -p /opt/streambox/frontend
mkdir -p /mnt/hls

3. tmpfs para HLS

Añade a /etc/fstab:

tmpfs /mnt/hls tmpfs size=64M,mode=0755,uid=root,gid=root,noatime 0 0

Y monta:

systemctl daemon-reload
mount -a

4. Copiar los ficheros

  • backend/app.py → /opt/streambox/backend/app.py
  • backend/config.example.json → /opt/streambox/backend/config.json
  • frontend/index.html → /opt/streambox/frontend/index.html

5. Editar config.json

Copia config.example.json a config.json y rellena:

  • video.device: normalmente /dev/video0. Idealmente usa el path estable /dev/v4l/by-id/....
  • video.input_format: h264 (cámara H.264 nativo) o mjpeg (la mayoría de webcams USB).
  • video.size: 1280x720 recomendado.
  • video.bitrate: 2500k para 720p, 4000k para 1080p.
  • audio.device: plughw:0,0 o el que corresponda (ver arecord -l).
  • outputs.twitch.url y outputs.youtube.url: tus claves reales.

6. Arrancar

cd /opt/streambox/backend
python3 app.py

Y abre en el navegador:

http://<ip-de-la-pi>:5000

Uso

Botones

  • 👁 Preview: arranca FFmpeg en modo preview (solo HLS, sin emitir).
  • 🔴 Emitir: arranca FFmpeg en modo onair (HLS + RTMP a Twitch/YouTube).
  • ⏹ Parar: detiene todo.

Flujo recomendado

  1. Pulsar 👁 Preview para verificar encuadre, foco, audio.
  2. Ajustar la cámara mientras se ve la preview.
  3. Pulsar 🔴 Emitir cuando todo esté listo.
  4. Al terminar, pulsar ⏹ Parar.

Configuración de cámara

Detectar formatos soportados

v4l2-ctl --list-formats-ext -d /dev/video0

Detectar dispositivos de audio

arecord -l

El formato para FFmpeg es plughw:X,Y donde X es el card y Y el device.

Si la cámara entrega H.264 nativo

Configura "input_format": "h264" en config.json. El backend automáticamente usa -c:v copy sin recodificar (CPU ~5-15%).

Si la cámara entrega MJPG o YUYV

Configura "input_format": "mjpeg" o "yuyv422". El backend recodifica con libx264 -preset ultrafast (CPU ~60-80% en 720p30).

Servicio systemd (opcional)

Crea /etc/systemd/system/streambox.service:

[Unit]
Description=Streambox backend
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/streambox/backend
ExecStart=/usr/bin/python3 app.py
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target

Activar:

systemctl daemon-reload
systemctl enable streambox
systemctl start streambox

Notas

  • Chrome/Edge de escritorio no soportan HLS nativo. La preview funciona solo en Safari (iOS/macOS) y navegadores móviles (Chrome Android, Firefox Android). Para PC de escritorio habría que añadir hls.js.
  • ?bandwidthtest=true en la URL de Twitch sirve para probar sin publicar. Quítalo para emitir de verdad.
  • El tmpfs evita desgaste de la SD. Un reinicio lo vacía, lo cual es deseable.

Licencia

MIT