This commit is contained in:
2026-03-11 00:06:51 +01:00
commit 2215fd96f9
167 changed files with 2627 additions and 0 deletions

546
RTSP_STREAMING_SETUP.md Normal file
View File

@@ -0,0 +1,546 @@
# RTSP to HLS Streaming in SvelteKit
This guide walks you through setting up real-time RTSP stream conversion to HLS format in your SvelteKit application.
## What's Included
- **Backend**: FFmpeg-based RTSP to HLS converter running on Node.js
- **Frontend**: SvelteKit component with HLS.js video player
- **API**: RESTful endpoints to control streams
## Prerequisites
### System Requirements
- **Node.js**: 18 or higher
- **FFmpeg**: Must be installed and in your PATH
- **Package Manager**: npm or bun
### Install FFmpeg
#### macOS
```bash
brew install ffmpeg
```
#### Ubuntu/Debian
```bash
sudo apt-get update
sudo apt-get install ffmpeg
```
#### Windows (Chocolatey)
```bash
choco install ffmpeg
```
#### Windows (Scoop)
```bash
scoop install ffmpeg
```
#### Verify Installation
```bash
ffmpeg -version
```
## Installation
### 1. Install Dependencies
```bash
npm install
# or with bun
bun install
```
This installs `hls.js` for browser-based HLS playback.
### 2. Project Structure
The setup creates the following files:
```
src/
├── lib/
│ ├── server/
│ │ └── streaming.ts # FFmpeg stream manager
│ └── components/
│ └── RTSPVideoPlayer.svelte # Video player component
├── routes/
│ ├── +page.svelte # Home page
│ └── api/
│ └── stream/
│ └── +server.ts # Stream API endpoints
└── ...
static/
└── hls/ # HLS playlists & segments (auto-created)
```
### 3. Run Development Server
```bash
npm run dev
```
Open `http://localhost:5173` in your browser.
## Usage
### Web Interface
1. **Stream ID**: Enter a unique identifier (e.g., "camera-1")
2. **RTSP URL**: Enter your camera's RTSP stream URL
3. **Start Stream**: Click to begin conversion and playback
4. **Stop Stream**: Click to terminate the stream
### Common RTSP URLs
**Hikvision Cameras**
```
rtsp://admin:password@192.168.1.100:554/stream
rtsp://admin:password@192.168.1.100:554/Streaming/Channels/101
```
**Dahua Cameras**
```
rtsp://admin:password@192.168.1.100:554/live
```
**Generic IP Cameras**
```
rtsp://user:password@camera-ip:554/stream
rtsp://camera-ip:554/stream1
```
## API Reference
### Start Stream
**Request:**
```bash
curl -X POST http://localhost:5173/api/stream \
-H "Content-Type: application/json" \
-d '{
"action": "start",
"streamId": "camera-1",
"rtspUrl": "rtsp://192.168.1.100:554/stream"
}'
```
**Response:**
```json
{
"playlistUrl": "/hls/camera-1.m3u8"
}
```
### Stop Stream
**Request:**
```bash
curl -X POST http://localhost:5173/api/stream \
-H "Content-Type: application/json" \
-d '{
"action": "stop",
"streamId": "camera-1"
}'
```
**Response:**
```json
{
"success": true
}
```
### Get Stream Status
**Request:**
```bash
curl -X POST http://localhost:5173/api/stream \
-H "Content-Type: application/json" \
-d '{
"action": "status",
"streamId": "camera-1"
}'
```
**Response:**
```json
{
"streamId": "camera-1",
"rtspUrl": "rtsp://192.168.1.100:554/stream",
"startedAt": "2024-01-15T10:30:45.123Z",
"isRunning": true,
"playlistUrl": "/hls/camera-1.m3u8"
}
```
### List All Streams
**Request:**
```bash
curl -X POST http://localhost:5173/api/stream \
-H "Content-Type: application/json" \
-d '{"action": "list"}'
```
**Response:**
```json
{
"streams": [
{
"streamId": "camera-1",
"rtspUrl": "rtsp://192.168.1.100:554/stream",
"startedAt": "2024-01-15T10:30:45.123Z",
"isRunning": true,
"playlistUrl": "/hls/camera-1.m3u8"
}
]
}
```
## Configuration
### FFmpeg Parameters
Edit `src/lib/server/streaming.ts` to adjust encoding parameters:
```typescript
// Current defaults
'-hls_time', '10', // Segment duration (seconds)
'-hls_list_size', '3', // Number of segments to keep
'-preset', 'fast', // Encoding speed
'-b:a', '128k', // Audio bitrate
```
### Low Latency Setup
For real-time applications, modify the FFmpeg arguments:
```typescript
'-hls_time', '2', // 2-second segments
'-hls_list_size', '5', // Keep more segments
'-preset', 'ultrafast', // Fastest encoding
'-flags', '+low_delay', // Low-delay mode
```
### High Quality Setup
```typescript
'-crf', '23', // Quality (0-51, lower=better)
'-b:v', '2500k', // Video bitrate
'-c:a', 'aac',
'-b:a', '192k', // Higher audio quality
```
### GPU Acceleration (NVIDIA)
```typescript
'-c:v', 'h264_nvenc', // NVIDIA encoder
'-preset', 'fast', // fast, medium, slow
```
## Troubleshooting
### "ffmpeg: command not found"
FFmpeg is not installed or not in your system PATH.
**Solution:** Reinstall FFmpeg and ensure it's in your PATH, then restart your terminal.
```bash
# Verify FFmpeg is accessible
which ffmpeg
ffmpeg -version
```
### Stream won't connect
Check the following:
1. **RTSP URL is correct**: Test with VLC player first
2. **Network connectivity**: Ping the camera IP
3. **Firewall rules**: Ensure port 554 (default RTSP) is open
4. **Camera credentials**: Verify username/password in URL
5. **FFmpeg logs**: Check browser console and terminal output
### "Playlist not found" Error
This usually means FFmpeg hasn't created the HLS segments yet.
**Solution:** Increase the wait time in the component:
```typescript
// In RTSPVideoPlayer.svelte, startStream function
await new Promise((resolve) => setTimeout(resolve, 3000)); // Increase from 1000 to 3000
```
### Video won't play in Safari
HLS.js may have issues with some configurations.
**Solution:** Check that the HLS.js library is loaded:
```typescript
// Verify HLS.js is available
if (typeof window !== 'undefined' && !(window as any).HLS) {
console.error('HLS.js not loaded');
}
```
### High CPU Usage
The FFmpeg process is using too many resources.
**Solution:** Use a faster preset or reduce resolution:
```typescript
// Use ultrafast preset
'-preset', 'ultrafast',
// Or reduce resolution
'-vf', 'scale=1280:720',
```
### High Latency / Buffering
Segments are taking too long to generate or playback is laggy.
**Solutions:**
1. Reduce segment duration to 2-5 seconds
2. Enable low-latency mode
3. Check network bandwidth
4. Reduce video resolution
5. Close other CPU-intensive applications
## Browser Support
| Browser | HLS Support | Notes |
|---------|-------------|-------|
| Chrome | ✓ HLS.js | Full support via HLS.js library |
| Firefox | ✓ HLS.js | Full support via HLS.js library |
| Safari | ✓ Native | Native HLS support |
| Edge | ✓ HLS.js | Chromium-based, full support |
| Mobile Chrome | ✓ HLS.js | Full support |
| Mobile Safari | ✓ Native | Native HLS support |
| Opera | ✓ HLS.js | Full support |
## Security Best Practices
### 1. Environment Variables for Credentials
Never hardcode camera credentials in your code.
```typescript
// Load from environment
const rtspUrl = `rtsp://${process.env.CAMERA_USER}:${process.env.CAMERA_PASS}@${process.env.CAMERA_IP}:554/stream`;
```
Create a `.env.local` file:
```
CAMERA_USER=admin
CAMERA_PASS=password
CAMERA_IP=192.168.1.100
```
### 2. Restrict API Access
Implement authentication on the `/api/stream` endpoint:
```typescript
// src/routes/api/stream/+server.ts
export async function POST({ request, locals }) {
// Check authentication
if (!locals.user) {
return json({ error: 'Unauthorized' }, { status: 401 });
}
// Continue with stream logic
}
```
### 3. Network Security
- Use HTTPS in production
- Restrict camera access to internal network only
- Use VPN for remote access
- Implement IP whitelisting
### 4. Process Management
FFmpeg runs with server privileges. Ensure:
- Minimal file system access
- Process limits to prevent DoS
- Regular monitoring and logging
## Performance Optimization
### 1. Adaptive Bitrate
Implement multiple quality levels:
```typescript
// Start multiple streams at different resolutions
const streams = [
{ id: 'high', resolution: '1920:1080', bitrate: '5000k' },
{ id: 'medium', resolution: '1280:720', bitrate: '2500k' },
{ id: 'low', resolution: '640:360', bitrate: '1000k' }
];
```
### 2. Connection Pooling
For multiple concurrent streams, optimize memory usage:
```typescript
// Limit concurrent streams
const MAX_STREAMS = 5;
if (activeStreams.size >= MAX_STREAMS) {
return { error: 'Too many concurrent streams' };
}
```
### 3. Caching
Cache HLS segments on a CDN for better performance.
### 4. Hardware Acceleration
Use GPU encoding when available:
- NVIDIA: `h264_nvenc`
- Intel: `h264_qsv`
- AMD: `h264_amf`
## Production Deployment
### Docker
Create `Dockerfile`:
```dockerfile
FROM node:18-slim
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", "build/index.js"]
```
Build and run:
```bash
docker build -t rtsp-hls-app .
docker run -p 3000:3000 \
-e CAMERA_USER=admin \
-e CAMERA_PASS=password \
-e CAMERA_IP=192.168.1.100 \
rtsp-hls-app
```
### Docker Compose
```yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
CAMERA_USER: admin
CAMERA_PASS: password
CAMERA_IP: 192.168.1.100
volumes:
- ./static/hls:/app/static/hls
restart: unless-stopped
```
### Nginx Reverse Proxy
```nginx
server {
listen 443 ssl http2;
server_name stream.example.com;
ssl_certificate /etc/ssl/certs/cert.pem;
ssl_certificate_key /etc/ssl/private/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /hls/ {
alias /app/static/hls/;
expires 1h;
add_header Cache-Control "public, max-age=3600";
}
}
```
## Advanced Topics
### Custom Video Filters
Add effects or transformations:
```typescript
'-vf', 'scale=1280:720,fps=30,format=yuv420p'
```
### Audio Processing
```typescript
'-af', 'aresample=44100' // Resample to 44.1kHz
```
### Statistics and Monitoring
Log stream statistics:
```typescript
ffmpegProcess.stdout.on('data', (data) => {
console.log(`Stream stats: ${data}`);
});
```
### Multiple Bitrate HLS (Adaptive)
Generate multiple quality versions:
```typescript
// Create master playlist pointing to multiple variants
const masterPlaylist = `#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5000000
high.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000
medium.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000
low.m3u8`;
```
## Support & Resources
- [FFmpeg Documentation](https://ffmpeg.org/documentation.html)
- [HLS.js Documentation](https://github.com/video-dev/hls.js/wiki)
- [SvelteKit Documentation](https://kit.svelte.dev)
- [ONVIF Protocol](https://www.onvif.org/) - For camera device discovery
## License
MIT