StreamVision is a Node.js-based real-time DVR camera streaming platform that allows users to stream multiple RTSP camera feeds directly in the browser. It's now fully containerized with Docker, making deployment easier than ever. It supports dynamic DVR configurations, lazy loading of streams, and a responsive public viewer page.
- π Secure Access: Multi-layered security with JWT authentication, Bcrypt password hashing, and CSRF protection.
- π³ Containerized Deployment: Fully Dockerized setup for effortless deployment including automatic FFmpeg handling and Nginx reverse proxy.
- π¨ High-Performance Streaming: Sub-second latency RTSP to HLS conversion using a scalable Cluster-based process model.
- π₯οΈ Centralized Dashboard: Manage multiple DVRs and up to 16 RTSP camera channels per DVR from a single interface.
- π Real-time Analytics: Track stream usage, active sessions, and system performance with built-in analytics.
- π Automated Reporting: Generate professional PDF reports for system activity and camera health using
pdfkit. - π Public Streaming: Dedicated public viewing URLs for simplified stream sharing with optimized Hls.js playback.
- π§ Resource Efficiency: Lazy loading of video players and automatic stream cleanup after inactivity.
- π¨ Modern UI: Responsive design built with EJS, Tailwind CSS v4, and Flowbite components.
- Backend: Node.js, Express.js (v5.x), Cluster API
- Frontend: EJS (Embedded JavaScript), Tailwind CSS v4, Flowbite, Hls.js
- Media Engine: FFmpeg (RTSP β HLS conversion)
- Database: MySQL 8.0+ (using
mysql2/promise) - Security: CSRF-CSRF (Double-Submit Cookie), JWT, Bcrypt
- Monitoring: Prometheus, Loki (via
monitoringClient.js) - Deployment: Docker, Docker Compose, Nginx
The StreamVision architecture is designed for high-performance RTSP to HLS conversion with minimal latency, utilizing Node.js's scalability features.
- Workflow Model: The application uses a Master-Worker process model (Node.js
clustermodule).- Master Process: Manages the lifecycle of workers and provides IPC (Inter-Process Communication) handlers to start/stop streams.
- Worker Processes: Run the Express.js application, handling HTTP requests and serving the UI/API.
- Ingestion: The system receives raw RTSP streams from DVRs or IP Cameras via TCP (configured in
ffmpegflags for reliability). - Processing: When a stream is requested, the Master process spawns a dedicated FFmpeg process. This process is managed by
worker_threadsandchild_process.spawn. - Segmentation: FFmpeg converts the RTSP input into HLS (.m3u8) playlists and MPEG-TS (.ts) segments.
- Segments are 1-second long for near real-time latency.
- Stale segments are automatically cleaned up to save disk space.
- Delivery: HLS segments are served via Express static middleware (or Nginx in production) and played back using Hls.js on the frontend.
StreamVision/
βββ app.js # Express server & middleware configuration
βββ cluster.js # Master process (Cluster management & IPC)
βββ Dockerfile # Docker image definition
βββ docker-compose.yaml # Multi-container orchestration (App & Nginx)
βββ .env.example # Environment variables template
βββ config/
β βββ db.js # MySQL connection (mysql2/promise)
βββ controllers/ # Business logic for each feature
β βββ analyticsController.js # Usage tracking & stats
β βββ camerasController.js # Camera CRUD & config
β βββ dvrController.js # DVR management
β βββ publicStreamController.js # Public viewing logic
β βββ settingsController.js # App settings management
βββ routes/ # Express route definitions
β βββ api/ # Backend API endpoints
β βββ cameraRoutes.js # Camera management UI routes
β βββ userRouters.js # Auth & Profile routes
β βββ publicRoutes.js # Public viewing & streaming routes
βββ services/ # Core background services
β βββ auth.js # JWT & Bcrypt logic
β βββ rtspHealth.service.js # Stream health monitoring
β βββ rtspMetadata.service.js # Metadata extraction from RTSP
βββ utils/ # Shared utility functions
β βββ streamStore.js # Master stream management (spawn FFmpeg)
β βββ activityLogger.js # Audit logs for system actions
β βββ reportGenerator.js # PDF report creation (pdfkit)
β βββ logger.js # Winston-based logging
βββ views/ # EJS Templates
β βββ partials/ # Reusable UI components (Navbar, Sidebar)
β βββ dashboard.ejs # Main admin overview
β βββ camera.ejs # Individual camera viewing
βββ public/ # Static assets
β βββ css/ # Compiled Tailwind CSS
β βββ streams/ # Active HLS segments (temporary)
βββ database/
βββ structure.sql # Initial database schema- Docker
- Docker Compose
git clone https://github.com/CodeByAmrit/StreamVision.git
cd StreamVisionThis project supports the encrypted .env.vault workflow from dotenv.org. You can still use .env.example locally, but for production the recommended flow is to pull the runtime .env file from the vault.
If you want a plain .env sample file, copy the example:
cp .env.example .envAlternatively, pull the development values directly from vault:
npx dotenv-vault pull development .env -yKeep .env.vault in the repository (it is included in the Docker build context by default). On your VPS or Dokploy UI, simply set the DOTENV_KEY environment variable:
DOTENV_KEY="dotenv://:key_xyz@dotenv.org/vault/.env.vault?environment=production"When your Node.js application starts (either in Docker or directly), dotenv will automatically detect DOTENV_KEY, decrypt .env.vault, and inject the production secrets into process.env. No manual environment setup or .env files are required on the host/VPS.
(Optional) If you ever need to manually pull the production .env file on the VPS:
npx dotenv-vault pull production .env -y| Variable | Description | Example |
|---|---|---|
NODE_ENV |
Environment mode | production |
PORT |
Web server port | 3000 |
DB_HOST |
MySQL hostname | localhost |
DB_PORT |
MySQL port | 3306 |
DB_USER |
MySQL username | root |
DB_PASSWORD |
MySQL password | ****** |
DB_DATABASE |
MySQL database name | streamvision |
DB_CA |
MySQL SSL CA (base64 string) | <base64 certificate> |
jwt_token |
Secret for auth tokens | secure_token_here |
saltRounds |
Bcrypt work factor | 12 |
STREAM_AUTO_STOP_MINUTES |
Auto-stop duration in minutes | 120 |
PROMETHEUS_URL |
Prometheus endpoint | http://prometheus:9090 |
PROMETHEUS_USER |
Prometheus basic auth user | user |
PROMETHEUS_PASS |
Prometheus basic auth password | pass |
LOKI_URL |
Loki endpoint | http://loki:3100 |
LOKI_USER |
Loki basic auth user | user |
LOKI_PASS |
Loki basic auth password | pass |
The platform provides several internal and public API endpoints for stream management.
GET /api/public/camera/:id/hls: Returns the active HLS URL for a specific camera.GET /public/dvr/:id: Direct link to the public viewing dashboard for a DVR.
POST /api/start-stream: Starts an RTSP to HLS conversion session.- Body:
{ "rtspUrl": "rtsp://..." }
- Body:
POST /api/stop-stream: Manually terminates a stream session.- Body:
{ "rtspUrl": "rtsp://..." }
- Body:
StreamVision includes an integrated monitoring client for enterprise-grade observability.
- Metrics: Built-in Prometheus metrics exporter.
- Log Aggregation: Ready-to-use Grafana Loki integration for centralized log search.
- Audit Logs: Every camera/DVR state change is recorded with user attribution in
utils/activityLogger.js.
Located in utils/reportGenerator.js, this utility allows for generating detailed PDF reports containing:
- Camera uptime and health status.
- System activity and security events.
- Customizable location-based summary statistics.
Ensure your MySQL server is running and accessible from the Docker container. Import the database structure using the provided SQL file:
# Example using MySQL CLI
mysql -u your_user -p your_database < database/structure.sqlUse Docker Compose to build the image and start the container in the background.
docker-compose up --build -dThe application will now be running on the port you specified in your .env file (e.g., http://localhost:3000).
Use this flow when your Docker image is built in GitHub Actions and your VPS or Dokploy deployment only needs runtime configuration.
-
Ensure
.env.vaultis in Git: Verify that.env.vaultis committed to version control. -
Verify
.dockerignore: Ensure.env.vaultis included in the build context (which is done automatically via the negation!.env.vaultat the bottom of.dockerignore). -
Set Up Dokploy UI Environment Variables: In the Dokploy application settings UI, you only need to define two variables:
NODE_ENV=productionDOTENV_KEY="your_production_dotenv_key_here"
(You do not need to manually input DB credentials, JWT tokens, etc., in the Dokploy UI. They are decrypted automatically from the vault).
-
Deploy: Deploy the Docker image (created and pushed via your GitHub Actions workflow) onto Dokploy.
-
Verification: Once deployed, the application will automatically read the
DOTENV_KEY, decrypt.env.vaultinternally, and inject all variables intoprocess.envat startup. Check Dokploy/container logs to confirm the app starts successfully.
- View logs:
docker-compose logs -f - Stop the container:
docker-compose down
- Node.js (v14+ recommended)
- MySQL database
- FFmpeg installed on your system PATH
npm installCreate a .env file as described in the Docker setup, ensuring DB_HOST is set to localhost or your database IP.
npm run build:cssDevelopment Mode (with auto-reload):
npm run devProduction Mode:
# Start with Node
npm start
# Or start with PM2 for process management
npm run start:pm2| Command | Description |
|---|---|
npm start |
Starts the production server using node. |
npm run dev |
Starts the development server with nodemon. |
npm run build:css |
Builds and minifies CSS using Tailwind. |
npm run start:pm2 |
Starts the app using the PM2 process manager. |
npm run setup:linux |
Installs required dependencies for Debian/Ubuntu. |
- Express.js
- MySQL2
- FFmpeg-fluent
- Tailwind CSS
- Hls.js
- JWT for authentication
- Bcrypt for password hashing
- Nodemon
- Express Status Monitor
- Ensure FFmpeg is installed and in your system
PATH. - Verify the RTSP URL is accessible from your server (try
ffplay rtsp://your_url). - Check Docker logs:
docker-compose logs -f streamvision_app. - Verify database camera configuration (RTSP URL, port, credentials).
- Segments are 1-second long by default for low latency. If buffering occurs, adjust
-hls_timeinutils/streamStore.js. - Adjust
UV_THREADPOOL_SIZEincluster.jsif file I/O becomes a bottleneck.
ISC Β© Amrit
- FFmpeg team for powerful media processing
- Hls.js for excellent player implementation
- Tailwind CSS & Flowbite for modern styling
