dịch chuyển documents

This commit is contained in:
2026-04-30 21:41:16 +07:00
parent c10912a756
commit ae583a72de
4 changed files with 0 additions and 0 deletions
+194
View File
@@ -0,0 +1,194 @@
# IPCam Orange Pi Dashboard - FastAPI Backend Skeleton
## 1. Project Structure
```
ipcam-dashboard/
├── main.py
├── mediamtx.py
├── scheduler.py
├── models.py
├── config.py
└── requirements.txt
```
---
## 2. requirements.txt
```
fastapi
uvicorn
httpx
pydantic
```
---
## 3. config.py
```python
MEDIAMTX_API = "http://127.0.0.1:9997"
CAMERAS = ["cam1", "cam2", "cam3", "cam4"]
```
---
## 4. mediamtx.py (MediaMTX API wrapper)
```python
import httpx
from config import MEDIAMTX_API, CAMERAS
async def set_recording(enabled: bool):
payload = {
"paths": {
cam: {"record": enabled}
for cam in CAMERAS
}
}
async with httpx.AsyncClient() as client:
r = await client.post(
f"{MEDIAMTX_API}/v3/config/paths/patch",
json=payload,
timeout=5
)
return r.json()
async def get_paths():
async with httpx.AsyncClient() as client:
r = await client.get(f"{MEDIAMTX_API}/v3/paths/list")
return r.json()
```
---
## 5. scheduler.py
```python
from datetime import datetime
from mediamtx import set_recording
_last_state = None
def is_record_time(now: datetime) -> bool:
day = now.weekday() # 0=Mon
hour = now.hour
# Weekend: always record
if day in (5, 6):
return True
# Weekdays: 18:00 → 08:00
return hour >= 18 or hour < 8
async def scheduler_loop():
global _last_state
while True:
now = datetime.now()
should_record = is_record_time(now)
if _last_state != should_record:
print(f"[Scheduler] Set recording = {should_record}")
await set_recording(should_record)
_last_state = should_record
import asyncio
await asyncio.sleep(60)
```
---
## 6. models.py
```python
from pydantic import BaseModel
class RecordingToggle(BaseModel):
enabled: bool
```
---
## 7. main.py
```python
from fastapi import FastAPI
import asyncio
from mediamtx import set_recording, get_paths
from scheduler import scheduler_loop
from models import RecordingToggle
app = FastAPI()
@app.on_event("startup")
async def startup():
asyncio.create_task(scheduler_loop())
@app.get("/")
async def root():
return {"status": "ok"}
@app.get("/paths")
async def list_paths():
return await get_paths()
@app.post("/recording")
async def toggle_recording(data: RecordingToggle):
return await set_recording(data.enabled)
```
---
## 8. Run Server
```
uvicorn main:app --host 0.0.0.0 --port 8008
```
---
## 9. API Endpoints
### Get stream status
```
GET /paths
```
### Enable recording
```
POST /recording
{
"enabled": true
}
```
### Disable recording
```
POST /recording
{
"enabled": false
}
```
---
## 10. Next Steps
- Add recordings API (list files)
- Serve video files (StaticFiles)
- Add camera config management (DB or JSON)
- Build frontend dashboard (WebRTC grid)
+192
View File
@@ -0,0 +1,192 @@
# IPCam Orange Pi Dashboard - Frontend UI Specification
## 1. Overview
This document describes the frontend UI/UX design for IPCam Orange Pi Dashboard.
The dashboard includes:
- Live camera monitoring (WebRTC)
- Playback system (recorded files)
- System configuration (camera + schedule)
---
## 2. Layout Structure
```
┌───────────────────────────────┐
│ Header / Navigation │
├───────────────┬───────────────┤
│ Live View │ Playback │
│ (WebRTC Grid) │ (Files list) │
├───────────────┴───────────────┤
│ Settings (modal / tab) │
└───────────────────────────────┘
```
---
## 3. Live View (WebRTC Grid)
### Features
- 4 camera grid (2x2)
- Real-time streaming via WebRTC
- Low latency
- Auto reconnect
### Layout
```
┌────────────┬────────────┐
│ cam1 │ cam2 │
│ [video] │ [video] │
├────────────┼────────────┤
│ cam3 │ cam4 │
│ [video] │ [video] │
└────────────┴────────────┘
```
### Camera Tile Components
- Video player (WebRTC)
- Camera name
- Status indicator (online/offline)
- Buttons:
- Fullscreen
- Reload
### Behavior
- Lazy load streams
- Auto reconnect on failure
- Click to fullscreen
---
## 4. Playback (Recordings)
### Layout
```
┌───────────────┬──────────────────────┐
│ Camera + Date │ File List + Player │
└───────────────┴──────────────────────┘
```
### Left Panel
- Camera selector (dropdown)
- Date picker
### Right Panel
#### File List
```
13:00:00 ▶️ ⬇️
13:05:00 ▶️ ⬇️
13:10:00 ▶️ ⬇️
```
#### Video Player
- HTML5 video player
- Load selected file
### API Integration
- GET /recordings?camera=cam1&date=YYYY-MM-DD
- /videos/<camera>/<file>
### Behavior
- Click ▶️ → play
- Click ⬇️ → download
- Auto load newest file
---
## 5. Settings
## 5.1 Camera Management
### UI
```
Camera List:
[cam1] rtsp://...
[cam2] rtsp://...
[ + Add Camera ]
```
### Add Camera Form
```
Name: camX
RTSP URL: rtsp://...
[ Save ]
```
---
## 5.2 Recording Schedule
### UI
```
Recording Schedule
[ ] Enable scheduler
Weekdays:
From: 18:00
To: 08:00
Weekend:
[x] Record all day
```
### Logic
- Controlled by backend scheduler
- Uses MediaMTX API
---
## 6. Navigation
```
[ Live ] [ Playback ] [ Settings ]
```
---
## 7. Tech Stack
- HTML / CSS / JS (or React)
- WebRTC player
- REST API integration
---
## 8. Constraints
- Requires H264 cameras (browser support)
- Requires open ports:
- 8889 (WebRTC HTTP)
- 8189/UDP (ICE)
---
## 9. Future Enhancements
- Timeline playback
- Multi-camera playback
- Mobile UI
- Authentication
---
## 10. Summary
Frontend responsibilities:
- Render WebRTC streams
- Display recordings
- Control system configuration
This UI completes the full system:
Camera → MediaMTX → Backend → Frontend
+198
View File
@@ -0,0 +1,198 @@
# IPCam Orange Pi Dashboard (Updated)
## 1. Overview
IPCam Orange Pi Dashboard is a lightweight web-based surveillance system built on top of MediaMTX.
The system is designed for:
- Orange Pi (low-resource hardware)
- Multiple IP cameras (410 cams)
- No AI processing (unlike Frigate)
- Full control via MediaMTX Control API
---
## 2. Architecture
### Components
- IP Cameras (RTSP - H264 recommended)
- MediaMTX (stream proxy + recorder + API)
- Dashboard Backend (scheduler + API)
- Dashboard Frontend (live view + playback UI)
### Data Flow
Camera → MediaMTX → WebRTC → Dashboard
Camera → MediaMTX → Recording (fMP4) → Storage → Playback UI
---
## 3. Core Features
### 3.1 Live View
- Grid layout (1 / 4 / 9 cameras)
- WebRTC streaming (low latency)
- Auto reconnect
- Lazy loading streams
### 3.2 Playback
- List recordings by:
- Camera
- Date
- Play fMP4 files via HTML5 video
- File-based playback (no timeline initially)
### 3.3 Camera Management
- Add/remove camera (update MediaMTX config)
- Reload MediaMTX if needed
### 3.4 Recording Schedule (IMPORTANT)
- Configure recording time per system:
- Weekdays: 18:00 → 08:00
- Weekend: 24h
- Implemented in Dashboard (NOT MediaMTX)
---
## 4. MediaMTX Integration
### 4.1 Endpoints
- RTSP: rtsp://<server>:8554/<path>
- WebRTC: http://<server>:8889
- API: http://<server>:9997
---
### 4.2 Control API Usage
#### Enable API
```
api: true
apiAddress: :9997
```
---
### 4.3 Toggle Recording via API
#### Enable recording
```
POST /v3/config/paths/patch
{
"paths": {
"cam1": { "record": true }
}
}
```
#### Disable recording
```
POST /v3/config/paths/patch
{
"paths": {
"cam1": { "record": false }
}
}
```
---
### 4.4 Bulk Update
```
{
"paths": {
"cam1": { "record": true },
"cam2": { "record": true },
"cam3": { "record": true },
"cam4": { "record": true }
}
}
```
---
## 5. Scheduler Design
### Logic
- Dashboard backend controls recording
- Runs every 60 seconds
### Example Logic
```
if weekend:
record = true
else:
record = (hour >= 18 or hour < 8)
```
### Implementation
- setInterval / cron job in backend
- Calls MediaMTX API
---
## 6. Storage
### Format
- fMP4 segments
### Path
```
/recordings/<camera>/<timestamp>.fmp4
```
### Notes
- Files created per segment (e.g., 5 minutes)
- Recording starts immediately when enabled
---
## 7. Technology Stack
### Backend
- Node.js (Express) or Python (FastAPI)
- Responsibilities:
- Scheduler
- MediaMTX API integration
- Recording index API
### Frontend
- HTML + JS (or React)
- WebRTC player
- Video playback UI
---
## 8. Performance Requirements
- 45 simultaneous streams
- Minimal CPU usage (no transcoding)
- Stable on Orange Pi
---
## 9. Constraints
- Browser requires H264 (NOT H265)
- WebRTC requires UDP port (8189) open
- Firewall must allow:
- 8554 (RTSP)
- 8889 (WebRTC HTTP)
- 8189/UDP (ICE)
---
## 10. Future Enhancements
- Timeline playback (merge segments)
- Multi-user authentication
- Mobile UI
- Event-based recording (optional)
---
## 11. Summary
- MediaMTX handles streaming + recording
- Dashboard handles logic + scheduling
- Recording is controlled via API (not config reload)
This architecture is optimized for simplicity, performance, and scalability on Orange Pi.
+195
View File
@@ -0,0 +1,195 @@
# IPCam Orange Pi Dashboard - Recording API & Video Serving
## 1. Overview
This module extends the backend to support:
- Listing recorded video files
- Serving video files to frontend (playback)
- Filtering by camera and date
This is REQUIRED for playback feature in dashboard.
---
## 2. Storage Structure (MediaMTX)
Assumed recording path:
```
/recordings/<camera>/<timestamp>.fmp4
```
Example:
```
/recordings/cam1/2026-04-26_13-14-00-123456.fmp4
```
---
## 3. Backend Responsibilities
Backend must:
1. Scan recording directory
2. Parse metadata (camera, timestamp)
3. Provide API for frontend
4. Serve video files via HTTP
---
## 4. Add to requirements.txt
```
python-multipart
```
---
## 5. recordings.py (new module)
```python
import os
from datetime import datetime
BASE_PATH = "/recordings"
def parse_filename(filename: str):
try:
name = filename.replace(".fmp4", "")
dt = datetime.strptime(name, "%Y-%m-%d_%H-%M-%S-%f")
return dt
except:
return None
def list_recordings(camera: str, date: str = None):
cam_path = os.path.join(BASE_PATH, camera)
if not os.path.exists(cam_path):
return []
results = []
for file in os.listdir(cam_path):
if not file.endswith(".fmp4"):
continue
dt = parse_filename(file)
if not dt:
continue
if date:
if dt.strftime("%Y-%m-%d") != date:
continue
results.append({
"camera": camera,
"filename": file,
"timestamp": dt.isoformat(),
"url": f"/videos/{camera}/{file}"
})
# sort newest first
results.sort(key=lambda x: x["timestamp"], reverse=True)
return results
```
---
## 6. Update main.py
```python
from fastapi.staticfiles import StaticFiles
from recordings import list_recordings
# mount video folder
app.mount("/videos", StaticFiles(directory="/recordings"), name="videos")
@app.get("/recordings")
async def get_recordings(camera: str, date: str = None):
return list_recordings(camera, date)
```
---
## 7. API Usage
### List recordings
```
GET /recordings?camera=cam1
```
### Filter by date
```
GET /recordings?camera=cam1&date=2026-04-26
```
---
## 8. Response Example
```json
[
{
"camera": "cam1",
"filename": "2026-04-26_13-14-00-123456.fmp4",
"timestamp": "2026-04-26T13:14:00",
"url": "/videos/cam1/2026-04-26_13-14-00-123456.fmp4"
}
]
```
---
## 9. Playback in Frontend
Use standard HTML:
```html
<video controls width="600">
<source src="http://<server>:8008/videos/cam1/file.fmp4">
</video>
```
---
## 10. Important Notes
### fMP4 compatibility
- Modern browsers support fMP4
- If issues → fallback to HLS later
### File size
- Large files → consider pagination later
### Security (future)
- Add auth before exposing /videos
---
## 11. Next Improvements
- Pagination (limit, offset)
- Thumbnail generation
- Timeline UI
- Merge segments
---
## 12. Summary
This module completes playback pipeline:
MediaMTX → Disk → Backend API → Frontend Player
Without this layer:
- You cannot build usable playback UI
This is a critical component of your system.