Una aplicación web moderna para reproducir múltiples streams RTSP simultáneamente en tu navegador.
- ✅ Conversión RTSP integrada - Backend Node.js con FFmpeg para convertir RTSP a HLS en runtime
- ✅ Descubrimiento automático de cámaras - Detecta cámaras ONVIF, Tapo y Yi Cams en tu red local
- ✅ Reproduce múltiples cámaras simultáneamente
- ✅ Soporte para HLS, MJPEG y WebRTC
- ✅ Almacenamiento automático en localStorage
- ✅ Diseño responsive con grid personalizable (1, 2 o 3 columnas)
- ✅ Interfaz moderna y oscura con Tailwind CSS
- ✅ Agregar/eliminar cámaras fácilmente
- ✅ TypeScript para mayor seguridad de tipos
- ✅ API REST para gestión de streams y descubrimiento
- Node.js 18+ (para el backend)
- FFmpeg (para conversión RTSP a HLS)
Linux (Ubuntu/Debian):
sudo apt update
sudo apt install ffmpegmacOS:
brew install ffmpegWindows: Descarga desde ffmpeg.org y agrega al PATH.
# Instalar todas las dependencias (frontend + backend)
npm run setup
# O manualmente:
npm install # Frontend
npm run server:install # BackendNecesitas ejecutar dos terminales simultáneamente:
Terminal 1 - Backend (servidor de conversión RTSP):
npm run serverTerminal 2 - Frontend (interfaz web):
npm run devAhora abre tu navegador en http://localhost:5173
- Iniciar la aplicación: Ejecuta
npm run devynpm run server - Descubrir cámaras: Haz clic en el botón "Descubrir Cámaras" en el header
- Iniciar búsqueda: Haz clic en "Iniciar Descubrimiento"
- Seleccionar cámara: Elige una de las cámaras encontradas
- Autenticar: Ingresa usuario y contraseña de la cámara
- Conectar: La cámara se agregará automáticamente
Ver CAMERA_DISCOVERY.md para más detalles sobre el descubrimiento automático.
- Iniciar la aplicación: Ejecuta
npm run devynpm run server - Agregar cámara: Haz clic en el botón
+flotante - Configurar cámara:
- Nombre: Un nombre descriptivo para tu cámara
- URL: La URL del stream (ver sección de configuración RTSP)
- Tipo: Selecciona el tipo de stream (HLS, RTSP, MJPEG, WebRTC)
- Gestionar vista: Usa los botones de grid en la parte superior para cambiar el layout
Los navegadores web NO pueden reproducir streams RTSP directamente. Esta aplicación incluye un backend integrado que convierte automáticamente tus streams RTSP a HLS usando FFmpeg.
La forma más fácil de usar streams RTSP es con el backend integrado:
-
Inicia el backend (si no lo has hecho):
npm run server
-
Agrega tu cámara RTSP en la interfaz web:
- URL:
rtsp://usuario:password@192.168.1.100:554/stream - La conversión a HLS se hará automáticamente
- El checkbox "Convertir automáticamente usando el backend" debe estar marcado
- URL:
-
¡Listo! El backend convertirá el stream en tiempo real
Tu Cámara RTSP → Backend (FFmpeg) → Conversión HLS → Navegador
El backend:
- Recibe la URL RTSP de tu cámara
- Usa FFmpeg para convertir a HLS en tiempo real
- Sirve los archivos HLS (.m3u8 y .ts)
- El frontend los reproduce automáticamente
El backend expone una API REST en http://localhost:3001:
Iniciar stream:
curl -X POST http://localhost:3001/api/streams \
-H "Content-Type: application/json" \
-d '{"id":"cam1","rtspUrl":"rtsp://..."}'Listar streams activos:
curl http://localhost:3001/api/streamsDetener stream:
curl -X DELETE http://localhost:3001/api/streams/cam1Health check:
curl http://localhost:3001/api/healthConvierte tu stream RTSP a HLS usando FFmpeg:
ffmpeg -rtsp_transport tcp -i rtsp://usuario:password@192.168.1.100:554/stream \
-c:v copy -c:a copy -f hls -hls_time 2 -hls_list_size 3 \
-hls_flags delete_segments stream.m3u8Luego sirve los archivos con un servidor HTTP simple:
# Con Python
python -m http.server 8080
# Con Node.js
npx serve .Usa la URL: http://localhost:8080/stream.m3u8
MediaMTX es un servidor de streaming que convierte RTSP a HLS/WebRTC automáticamente.
# Descargar y ejecutar MediaMTX
wget https://github.com/bluenviron/mediamtx/releases/latest/download/mediamtx_linux_amd64.tar.gz
tar -xzf mediamtx_linux_amd64.tar.gz
./mediamtxConfiguración básica en mediamtx.yml:
paths:
cam1:
source: rtsp://usuario:password@192.168.1.100:554/streamURL para usar: http://localhost:8889/cam1/index.m3u8
go2rtc soporta múltiples protocolos y es muy eficiente.
# Instalar go2rtc
docker run -p 1984:1984 -p 8554:8554 alexxit/go2rtcConfigurar en go2rtc.yaml:
streams:
camera1: rtsp://usuario:password@192.168.1.100:554/streamURL para WebRTC: http://localhost:1984/
Algunas cámaras IP soportan MJPEG directamente:
http://192.168.1.100/video.cgi
http://192.168.1.100/videostream.cgi
| Formato | Extensión | Descripción | Latencia |
|---|---|---|---|
| HLS | .m3u8 | HTTP Live Streaming (más compatible) | Media (5-10s) |
| MJPEG | .mjpeg, .cgi | Motion JPEG sobre HTTP | Baja (< 1s) |
| WebRTC | N/A | Streaming en tiempo real | Muy baja (< 500ms) |
| RTSP | rtsp:// | Requiere conversión a HLS/WebRTC | N/A |
// HLS desde servidor local
http://localhost:8080/camera1/stream.m3u8
// MJPEG desde cámara IP
http://192.168.1.100/videostream.cgi
// HLS desde MediaMTX
http://localhost:8889/cam1/index.m3u8
// Big Buck Bunny (demo HLS)
https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8rtsp-web-player/
├── src/ # Frontend (React + TypeScript)
│ ├── components/
│ │ ├── VideoPlayer.tsx # Componente de reproductor individual
│ │ ├── AddCameraForm.tsx # Formulario para agregar cámaras
│ │ └── CameraDiscovery.tsx # Componente de descubrimiento
│ ├── hooks/
│ │ └── useLocalStorage.ts # Hook para persistencia
│ ├── types.ts # Tipos TypeScript
│ ├── App.tsx # Componente principal
│ └── main.tsx # Punto de entrada
├── server/ # Backend (Node.js + Express)
│ ├── index.js # Servidor Express + API REST
│ ├── streamManager.js # Gestor de conversión RTSP → HLS
│ ├── cameraDiscovery.js # Módulo de descubrimiento de cámaras
│ ├── streams/ # Archivos HLS generados (auto-creado)
│ └── package.json # Dependencias del backend
├── CAMERA_DISCOVERY.md # Documentación de descubrimiento
├── package.json # Dependencias del frontend
├── tsconfig.json
└── tailwind.config.js
# Instalación
npm run setup # Instala dependencias del frontend y backend
# Desarrollo
npm run dev # Inicia servidor de desarrollo (frontend)
npm run server # Inicia backend de conversión RTSP
npm run server:install # Instala solo dependencias del backend
# Producción
npm run build # Construye para producción
npm run preview # Preview de build de producción
# Linting
npm run lint # Ejecuta ESLint- React 18 - Librería UI
- TypeScript - Lenguaje tipado
- Vite - Build tool y dev server
- Tailwind CSS - Framework CSS utility-first
- HLS.js - Reproductor HLS para navegadores
- Lucide React - Iconos modernos
- Node.js - Runtime JavaScript
- Express - Framework web minimalista
- FFmpeg - Conversión de video RTSP → HLS
- fluent-ffmpeg - Wrapper de FFmpeg para Node.js
- node-onvif - Descubrimiento y control de cámaras ONVIF
- tp-link-tapo-connect - API para dispositivos Tapo
- CORS - Manejo de CORS para API REST
- Asegúrate de usar un navegador moderno (Chrome, Firefox, Edge)
- Safari tiene soporte nativo para HLS
-
Verifica que el backend esté corriendo:
npm run server
Deberías ver:
✅ Servidor corriendo en: http://localhost:3001 -
Verifica FFmpeg:
ffmpeg -version
Si no está instalado, instálalo según tu sistema operativo.
-
Verifica la URL RTSP:
- Asegúrate de que la cámara sea accesible en tu red
- Prueba la URL con VLC o similar primero
- Formato:
rtsp://usuario:password@IP:puerto/stream
-
Revisa los logs:
- Consola del navegador (F12)
- Terminal donde corre el backend
-
Verifica CORS:
- El backend ya incluye CORS habilitado
- Si usas otro servidor, configura CORS adecuadamente
- Usa WebRTC para menor latencia
- Reduce el
hls_timeen FFmpeg (ej:-hls_time 1) - Considera usar go2rtc con WebRTC
Si estás sirviendo HLS desde otro dominio, necesitas configurar CORS:
// Ejemplo con Express
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});- Las URLs con credenciales se almacenan en localStorage del navegador
- No expongas esta aplicación públicamente sin autenticación
- Usa HTTPS en producción
- Considera usar variables de entorno para credenciales
- Backend integrado para conversión RTSP → HLS
- API REST para gestión de streams
- Descubrimiento automático de cámaras ONVIF
- Soporte para cámaras Tapo (TP-Link)
- Descubrimiento completo de Yi Cams (Xiaomi)
- Detener streams automáticamente cuando se elimina la cámara
- Interfaz de administración de streams activos
- Soporte para WebRTC nativo (baja latencia)
- Grabación de streams
- Detección de movimiento
- Vista de pantalla completa
- Snapshots/Capturas
- Mejoras en soporte de audio
- Layouts predefinidos (2x2, 3x3, etc)
- Exportar/importar configuración
- Dashboard con estadísticas de streams
- Notificaciones en tiempo real
Las contribuciones son bienvenidas! Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
MIT License - ve el archivo LICENSE para más detalles.
¿Tienes preguntas o problemas?
- Abre un issue en GitHub
- Revisa la sección de Solución de Problemas
Hecho con ❤️ usando React + TypeScript + Tailwind CSS