A high-performance surveillance system featuring real-time binary JPEG streaming from ESP32-CAM devices with live frontend video display, centralized recording, and complete web dashboard control.
π΄ Live Video Streaming - Real-time JPEG frames via WebSocket binary streaming
πΉ H.264 Recording - FFmpeg transcoding with automatic file management
ποΈ Web Dashboard - React frontend with device control and live video display
π Secure HTTPS - SSL encryption for all communications
β‘ Real-time Status - Device heartbeats, connection monitoring, and status updates
π― ESP32-CAM Support - Optimized for ESP32-CAM binary streaming protocol
- Node.js 18+
- npm
- OpenSSL (for SSL certificates)
# 1. Install all dependencies
npm run install:all
# 2. Generate SSL certificates (development)
npm run setup:certs
# 3. Build the complete application
npm run build
# 4. Start the server
npm startThe application will be available at: https://localhost:3443
MagicPi-NVR/
βββ client/ # React TypeScript frontend
β βββ src/
β β βββ components/ # React components
β β βββ services/ # API services
β β βββ types/ # TypeScript interfaces
β βββ dist/ # Built frontend (after npm run build)
βββ pi-cam-server/ # Node.js TypeScript backend
β βββ src/
β β βββ api/ # REST API controllers
β β βββ services/ # Business logic services
β β βββ middleware/ # Express middleware
β β βββ types/ # TypeScript interfaces
β βββ dist/ # Built backend + deployed frontend
β β βββ client/ # Frontend files (copied during build)
β β βββ *.js # Compiled backend files
β βββ security/ # SSL certificates
βββ package.json # Root workspace configuration
npm run dev:frontend # Start Vite dev server (http://localhost:5173)npm run dev:backend # Start nodemon with auto-reload# Terminal 1: Frontend dev server
npm run dev:frontend
# Terminal 2: Backend dev server
npm run dev:backendThe build process creates a single deployable package:
- Frontend Build: React app compiled to static files
- Backend Build: TypeScript compiled to JavaScript
- Integration: Frontend copied to backend's
dist/client/ - Result: Single
pi-cam-server/dist/folder ready for deployment
# Build everything for production
npm run build
# Or step by step:
cd client && npm run build # Build frontend
cd pi-cam-server && npm run build # Build backend
cd pi-cam-server && npm run copy:frontend # Copy frontend to backendFor development:
npm run setup:certs # Generates self-signed certificatesFor production: Replace files in pi-cam-server/security/:
key.pem- Private keycert.pem- Certificate
Edit pi-cam-server/src/config.ts:
- Server ports and host
- Recording settings
- Video processing options
- Security settings
-
Build the application:
npm run build
-
Copy the
pi-cam-server/dist/folder to your server -
Install production dependencies:
cd pi-cam-server npm install --production -
Add proper SSL certificates to
security/ -
Start the server:
npm start
Docker support will be added in future versions for easier deployment.
- Real-time JPEG Streaming: ESP32-CAM devices send raw binary JPEG frames via WebSocket
- Automatic Format Detection: Server detects JPEG magic numbers (0xFF, 0xD8) vs JSON commands
- Live Video Recording: Binary frames processed through FFmpeg pipeline to MP4 files
- High Performance: Eliminates JSON parsing overhead for video data transmission
- Stream Processing: PassThrough streams with MJPEG input format for efficient processing
- π± Responsive surveillance dashboard
- π₯ Real-time video streaming interface
- π Recording browser with hierarchical navigation
- βοΈ Device configuration interface
- π WebSocket real-time updates
- π Device status monitoring
- π‘οΈ Device registration and authentication
- π¬ FFmpeg Binary Stream Processing: Direct MJPEG input from binary WebSocket data
- π HTTPS and WebSocket secure connections
- π‘ mDNS service discovery
- π§Ή Automatic cleanup services
- π Dual WebSocket support (frontend + devices)
- π¦ Binary Data Handling: Efficient processing of raw JPEG frames
- π₯ H.264 MP4 Recording: Real-time encoding with configurable quality settings
- πΉ Binary JPEG Transmission: Sends raw camera frames via
wsClient.sendBinary() - π Automatic server discovery and registration
- π€ Power-efficient operation modes
- π§ Remote configuration capabilities
- π± Hardware motion sensor support
The system implements a high-performance binary streaming architecture for real-time video transmission:
graph LR
A[ESP32-CAM] -->|Binary JPEG| B[WebSocket]
B -->|Magic Number Detection| C[Server Handler]
C -->|JPEG Data| D[PassThrough Stream]
D -->|MJPEG Input| E[FFmpeg Process]
E -->|H.264 Encode| F[MP4 File]
// Sends raw JPEG buffer data
wsClient.sendBinary((const char*)frameBuffer->buf, frameBuffer->len);// Detect JPEG magic numbers (0xFF, 0xD8)
if (data[0] === 0xFF && data[1] === 0xD8) {
// Process as binary JPEG frame for recording
await this.videoProcessor.writeFrame(deviceId, data);
// Forward frame to subscribed frontend clients for live viewing
this.forwardVideoFrameToFrontend(deviceId, data);
}// Subscribe to live video stream
const subscribeMessage = {
type: 'subscribe',
deviceId: deviceId
};
this.ws.send(JSON.stringify(subscribeMessage));
// Handle incoming video frames
ws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// Display live JPEG frame in video player
this.handleVideoFrame(new Uint8Array(event.data));
}
};// Direct MJPEG input from WebSocket stream
ffmpeg()
.inputFormat('mjpeg')
.input('pipe:0')
.videoCodec('libx264')
.outputOptions(['-preset ultrafast', '-tune zerolatency'])
.fps(10)
.save(outputPath)- Zero JSON Overhead: Raw binary transmission eliminates parsing delays
- Real-time Live Streaming: JPEG frames forwarded directly to frontend via WebSocket
- Direct Stream Processing: JPEG frames pipe directly to FFmpeg without intermediate storage
- Dual Output: Simultaneous live viewing and H.264 recording from single stream
- Memory Efficient: PassThrough streams prevent buffer accumulation
- Frame Capture: ESP32-CAM captures JPEG at configured quality
- Binary Transmission: Raw frame data sent via WebSocket to server
- Magic Number Detection: Server identifies JPEG vs command data
- Dual Processing:
- Live Stream: Frame forwarded to subscribed frontend clients
- Recording: Frame written to FFmpeg PassThrough stream
- Frontend Display: Browser receives binary JPEG and displays in real-time
- H.264 Recording: Simultaneous conversion to MP4 with configurable settings
- File Management: Automatic directory creation and file rotation
- Ensure all dependencies installed:
npm run install:all - Clear build cache:
npm run clean && npm run build
- Regenerate certificates:
npm run setup:certs - Check
pi-cam-server/security/folder exists
- Verify build completed: Check
pi-cam-server/dist/client/exists - Check server logs for frontend path detection
- Default HTTPS port: 3443
- Modify in
pi-cam-server/src/config.tsif needed
The backend binary streaming architecture is complete and operational. The next development phase focuses on frontend integration:
-
Live Stream Viewer Component
- Create React component to display real-time JPEG frames
- WebSocket connection to receive binary frame data
- Canvas-based rendering for smooth playback
-
Recording Status Integration
- Real-time recording indicators on device dashboard
- Live file size and duration tracking
- Recording start/stop controls
-
Binary Stream Monitoring
- Frame rate statistics and quality metrics
- Network throughput visualization
- Device performance monitoring
// Frontend WebSocket handler for binary frames
const handleBinaryFrame = (data: ArrayBuffer) => {
const blob = new Blob([data], { type: 'image/jpeg' });
const imageUrl = URL.createObjectURL(blob);
updateCanvasWithFrame(imageUrl);
};- β Backend Binary Streaming: Complete
- β ESP32-CAM Binary Transmission: Complete
- β FFmpeg Pipeline: Complete
- β MP4 Recording: Complete
- π§ Frontend Live Display: Next Phase
- π§ Stream Controls: Next Phase
- π§ Recording Management UI: Next Phase
- Advanced video player with scrubbing
- Multi-camera grid view
- Motion detection visualization
- Mobile-responsive controls
MIT License - see LICENSE file for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
Ready for deployment! π - Wireless Camera Security System
A complete, secure wireless camera system consisting of a Raspberry Pi 5 host server and multiple ESP32-CAM clients. This system provides automated video recording, motion detection, and secure wireless communication for comprehensive surveillance coverage.
βββββββββββββββββββ WiFi/TLS βββββββββββββββββββ
β ESP32-CAM βββββββββββββββββΊβ Raspberry Pi 5 β
β (Client) β WebSocket β (Host Server) β
β β β β
β β’ Motion Detectionβ β β’ Video Recordingβ
β β’ Camera Streamingβ β β’ Device Managementβ
β β’ Deep Sleep β β β’ Web API β
β β’ TLS Security β β β’ mDNS Service β
βββββββββββββββββββ βββββββββββββββββββ
β β
β Multiple Clients β
βββββββββββββββββββββββββββββββββββββ
- Secure Communication: HTTPS/WSS with TLS encryption
- Device Management: Automatic discovery and registration
- Video Recording: H.264 encoding with FFmpeg
- RESTful API: Complete device control and monitoring
- Automated Cleanup: Configurable retention policies
- mDNS Discovery: Zero-configuration networking
- Multi-client Support: Handle up to 50 ESP32-CAM devices
- Motion-Triggered Recording: PIR sensor integration
- Always-On Mode: Continuous monitoring without motion sensor
- Continuous Mode: Non-stop streaming for critical areas
- Auto-Detection: Automatically detects hardware and configures mode
- Power Efficient: Deep sleep with wake-on-motion or timer
- Auto-Discovery: Finds server via mDNS
- Secure Registration: API key authentication
- Real-time Streaming: JPEG over WebSocket
- Remote Configuration: Server-controlled camera settings
- OTA Ready: Over-the-air update capable
MagicPi-NVR/
βββ pi-cam-server/ # Raspberry Pi 5 Host Server
β βββ src/
β β βββ services/ # Core business logic
β β β βββ DeviceManager.ts
β β β βββ VideoProcessor.ts
β β β βββ CleanupService.ts
β β βββ middleware/ # Authentication & security
β β β βββ auth.ts
β β βββ config.ts # Configuration settings
β β βββ server.ts # Main application
β βββ security/ # SSL certificates
β βββ recordings/ # Video storage
β βββ package.json
β βββ tsconfig.json
β βββ README.md
β
βββ esp32-cam-client/ # ESP32-CAM Client Code
β βββ esp32_cam_client.ino # Arduino sketch
β βββ README.md
β
βββ LICENSE
βββ README.md # This file
- Raspberry Pi 5 (4GB+ RAM recommended)
- MicroSD card (32GB+ Class 10)
- Ethernet connection or WiFi
- Power supply (USB-C, 5V/5A)
- ESP32-CAM AI-Thinker modules
- PIR motion sensors (HC-SR501)
- Stable 3.3V power supplies
- MicroSD cards (optional)
# Clone the repository
git clone https://github.com/MagicInUse/MagicPi-NVR.git
cd MagicPi-NVR/pi-cam-server
# Install dependencies
npm install
# Generate SSL certificates
openssl genrsa -out security/key.pem 2048
openssl req -new -x509 -key security/key.pem -out security/cert.pem -days 365 \
-subj "/C=US/ST=State/L=City/O=Pi Camera Server/CN=$(hostname -I | awk '{print $1}')"
# Install FFmpeg
sudo apt update && sudo apt install ffmpeg
# Start the server
npm run build && npm start- Install Arduino IDE with ESP32 support
- Install required libraries:
- ArduinoWebsockets
- ArduinoJson
- Configure the code:
- Update WiFi credentials
- Paste server certificate
- Upload to ESP32-CAM
- Connect motion sensor to GPIO 13
-
Check server logs:
# Server should show: # "Device registered: XX:XX:XX:XX:XX:XX" # "WebSocket connection established"
-
Trigger motion detection on ESP32-CAM
-
Check recordings in
/recordings/directory
POST /register
Content-Type: application/json
{
"deviceId": "AA:BB:CC:DD:EE:FF"
}GET /device/status
X-API-Key: your-api-keyPUT /device/config
X-API-Key: your-api-key
{
"config": {
"resolution": "VGA",
"framerate": 15
}
}GET /recordings?date=2023-12-01
X-API-Key: your-api-key- TLS 1.2+ Encryption: All communications encrypted
- API Key Authentication: Unique keys per device
- Certificate Validation: ESP32 clients validate server
- Secure Headers: HSTS, CSP, and other security headers
- Rate Limiting: Protection against abuse
/recordings/
βββ AA-BB-CC-DD-EE-FF/ # Device MAC address
β βββ 2023-12-01/ # Date (YYYY-MM-DD)
β β βββ 08.mp4 # Hour-based files
β β βββ 09.mp4
β β βββ ...
β βββ 2023-12-02/
βββ ...
- Format: MP4 (H.264)
- Input: MJPEG from ESP32-CAM
- Quality: Configurable (CRF 23 default)
- Resolution: Up to UXGA (1600Γ1200)
- Frame Rate: Configurable (10 FPS default)
- Active (Streaming): ~200-300mA
- Deep Sleep: ~10-50Β΅A
- Battery Life: 7-10 hours active, 4-20 months sleep
- Motion-triggered activation
- Configurable streaming duration
- Deep sleep between triggers
- Optimized camera settings
export const config = {
server: {
httpsPort: 3443,
recordingRetentionDays: 7,
cleanupSchedule: '0 2 * * *' // Daily at 2 AM
},
video: {
inputFormat: 'mjpeg',
outputCodec: 'libx264',
defaultResolution: 'SVGA'
}
};const unsigned long STREAMING_DURATION = 30000; // 30 seconds
const unsigned long FRAME_INTERVAL = 100; // 10 FPS
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";GET /stats
X-API-Key: your-api-keyReturns:
- Device counts by status
- Recording statistics
- System resources
- Cleanup information
GET /health- Server logs: Console output
- Client logs: Serial monitor (115200 baud)
- Recording errors: Automatic logging
-
ESP32-CAM won't connect
- Check WiFi credentials
- Verify power supply stability
- Ensure 2.4GHz network
-
Server discovery fails
- Check mDNS service
- Verify network connectivity
- Check firewall settings
-
Recording issues
- Verify FFmpeg installation
- Check disk space
- Review camera settings
-
Certificate errors
- Regenerate certificates
- Check date/time sync
- Verify certificate format
Enable verbose logging:
# Server
NODE_ENV=development npm run dev
# Client
Serial.setDebugOutput(true); // In Arduino codecd pi-cam-server
git pull origin main
npm install
npm run build
sudo systemctl restart pi-camera-server- Use Arduino IDE for firmware updates
- Consider implementing OTA updates
- Update libraries regularly
- Monitor disk usage
- Check certificate expiration
- Review cleanup logs
- Update dependencies
- Fork the repository
- Create feature branch
- Make changes with tests
- Submit pull request
- Server: Add services in
src/services/ - Client: Modify Arduino sketch
- Update documentation
# Server tests
npm test
# Client tests
# Use Arduino IDE serial monitorMIT License - see LICENSE file for details.
- Check existing issues on GitHub
- Provide detailed error logs
- Include hardware specifications
- Test with minimal configuration
- GitHub Discussions for questions
- Wiki for additional documentation
- Examples in
/examplesdirectory
- ESP32 Camera library by Espressif
- FFmpeg for video processing
- Arduino WebSocket library
- Node.js and TypeScript communities
Made with β€οΈ by MagicInUse A repository for ESP32 Cameras and a Raspberry Pi home network video recording client/server interaction.