cập nhật lại README và INSTALL

This commit is contained in:
2026-05-20 10:53:58 +07:00
parent 0491789777
commit a8dd5d0d9c
2 changed files with 261 additions and 101 deletions
+178 -75
View File
@@ -1,21 +1,73 @@
# IPCam Orange Pi Dashboard INSTALL # IPCam Orange Pi Dashboard - INSTALL
Tài liệu này hướng dẫn triển khai trên Orange Pi (Linux). Mục tiêu: MediaMTX chạy như media server, FastAPI chạy như dashboard backend, React build ra static. Tài liệu này hướng dẫn triển khai toàn bộ hệ thống trên duy nhất một thiết bị `Orange Pi 5`.
## 0) Mô hình triển khai Mục tiêu:
- MediaMTX + Dashboard backend + Dashboard frontend chạy cùng máy. - `MediaMTX` chạy trên chính Orange Pi 5
- `FastAPI backend` chạy trên chính Orange Pi 5
- `Frontend React` build static và serve ngay trên chính Orange Pi 5
- File recordings lưu trên ổ cứng gắn trực tiếp vào Orange Pi 5
## 1) Yêu cầu ## 0) Cấu hình phần cứng khuyến nghị
- Orange Pi chạy Debian/Ubuntu Bắt buộc theo kịch bản này:
- MediaMTX đã cài và chạy được
- Python 3.9+ (khuyến nghị 3.10+)
- Node.js 20+ (để build frontend)
## 2) MediaMTX cấu hình tối thiểu - Thiết bị: `Orange Pi 5`
- RAM: `8GB` hoặc `16GB`
- Ổ lưu trữ: `>= 256GB`
Trong file `mediamtx.yml`: Khuyến nghị mạnh:
- Dùng `NVMe SSD` thay vì thẻ nhớ
- Nếu ghi nhiều camera hoặc lưu lâu ngày, nên dùng `512GB` hoặc `1TB`
- Không nên để recordings trên thẻ microSD
## 1) Mô hình triển khai
Tất cả dịch vụ chạy trên cùng một máy Orange Pi 5:
```text
Orange Pi 5
|- MediaMTX
|- FastAPI backend
|- Frontend React static
`- Thu muc recordings tren SSD/NVMe
```
Không cần thêm server riêng cho MediaMTX hay dashboard.
## 2) Yêu cầu hệ điều hành và phần mềm
- Orange Pi 5 chạy Debian/Ubuntu
- Python `3.9+` khuyến nghị `3.10+`
- Node.js `20+`
- Docker + Docker Compose plugin
- Nginx hoặc Apache nếu muốn serve frontend static production
## 3) Chuẩn bị ổ lưu trữ
Ví dụ SSD được mount tại `/mnt/ssd`.
Tạo thư mục dự án và thư mục recordings:
```bash
sudo mkdir -p /mnt/ssd/IPCam_OrangePi_Dashboard
sudo mkdir -p /mnt/ssd/IPCam_OrangePi_Dashboard/mediamtx/recordings
sudo chown -R $USER:$USER /mnt/ssd/IPCam_OrangePi_Dashboard
```
Clone source:
```bash
cd /mnt/ssd
git clone <YOUR_REPOSITORY_URL> IPCam_OrangePi_Dashboard
cd /mnt/ssd/IPCam_OrangePi_Dashboard
```
## 4) MediaMTX cấu hình tối thiểu
Trong `mediamtx/mediamtx.yml` cần có tối thiểu:
```yaml ```yaml
api: yes api: yes
@@ -27,116 +79,147 @@ webrtcAllowOrigin: '*'
record: yes record: yes
recordFormat: fmp4 recordFormat: fmp4
recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f recordPath: /mnt/ssd/IPCam_OrangePi_Dashboard/mediamtx/recordings/%path/%Y-%m-%d_%H-%M-%S-%f
recordPartDuration: 5m recordPartDuration: 5m
``` ```
### 2.1) Nếu MediaMTX API bị 401 Unauthorized Ghi chú:
401 nghĩa là request thiếu thông tin xác thực hợp lệ. Khi bật auth trong MediaMTX, bạn cần tạo user có quyền `api` và cấu hình backend dashboard gửi Basic Auth. - `recordPath` nên trỏ thẳng vào SSD/NVMe
- Dashboard sẽ tự đồng bộ camera vào `mediamtx.yml`
- Dashboard cần truy cập được MediaMTX API ở `127.0.0.1:9997`
Ví dụ trong `mediamtx.yml`: ### 4.1) Nếu MediaMTX API dùng auth
Nếu MediaMTX bật auth và dashboard bị `401 Unauthorized`, thêm user có quyền `api`:
```yaml ```yaml
authMethod: internal authMethod: internal
authInternalUsers: authInternalUsers:
- user: dashboard - user: dashboard
pass: dashboard_password pass: dashboard_password
ips: ['127.0.0.1', '::1', '192.168.88.0/24'] ips: ['127.0.0.1', '::1', '192.168.1.0/24']
permissions: permissions:
- action: api - action: api
``` ```
Sau đó set trực tiếp trong `api/data/config.json` của dashboard backend: Sau đó khai báo trong `api/data/config.json`:
``` ```json
"mediamtx_api_user": "dashboard", {
"mediamtx_api_pass": "dashboard_password" "mediamtx_api_user": "dashboard",
"mediamtx_api_pass": "dashboard_password"
}
``` ```
Trong `paths`, bạn có thể để dashboard tự thêm path bằng Settings (nhập RTSP URL). Backend sẽ cập nhật trực tiếp file `mediamtx.yml`. ## 5) Chạy MediaMTX trên Orange Pi 5
Tạo thư mục recordings: Nếu project đã có `mediamtx/docker-compose.yml`, chạy:
```bash ```bash
sudo mkdir -p /recordings cd /mnt/ssd/IPCam_OrangePi_Dashboard
sudo chown -R $USER:$USER /recordings docker compose -f mediamtx/docker-compose.yml up -d
``` ```
Mở firewall/cổng (tuỳ hệ thống): Kiểm tra:
- `8554/tcp` RTSP
- `8889/tcp` WebRTC HTTP
- `9997/tcp` MediaMTX Control API
- `8189/udp` ICE
## 3) Backend FastAPI
### 3.1 Cài dependencies
```bash ```bash
cd IPCam_OrangePi_Dashboard docker compose -f mediamtx/docker-compose.yml ps
curl http://127.0.0.1:9997/v3/paths/list
```
## 6) Cài backend FastAPI
### 6.1) Cài dependencies
```bash
cd /mnt/ssd/IPCam_OrangePi_Dashboard
python3 -m venv api/.venv python3 -m venv api/.venv
source api/.venv/bin/activate source api/.venv/bin/activate
pip install -r api/requirements.txt pip install -r api/requirements.txt
``` ```
### 3.2 Cấu hình ### 6.2) Cấu hình backend
Backend chỉ đọc cấu hình từ `api/data/config.json` (không đọc `.env`). Backend chỉ đọc cấu hình từ `api/data/config.json`.
Chạy lần đầu sẽ tự tạo file này (lưu camera + schedule + các tham số backend).
Danh sách camera trong `config.json` sẽ được backend đồng bộ từ `mediamtx.yml`.
Các thông số kết nối MediaMTX (`mediamtx_api_url`, `mediamtx_webrtc_url`, credentials, `recordings_dir`) do user điền trong dashboard Settings hoặc chỉnh trực tiếp `config.json`.
Bạn có thể chỉnh: File này chứa:
- `mediamtx_api_url` (mặc định `http://127.0.0.1:9997`) - thông số MediaMTX
- `mediamtx_webrtc_url` (mặc định `http://127.0.0.1:8889`) - thư mục recordings
- `mediamtx_api_user` / `mediamtx_api_pass` (nếu bật auth API của MediaMTX) - danh sách camera
- `recordings_dir` (mặc định `./mediamtx/recordings` trong project) - lịch ghi hình
- `api_port` (mặc định `8008`) - cổng backend
Các thao tác trong Settings: Chạy lần đầu, backend có thể tự tạo file nếu chưa có.
- Add Camera: chỉ nhập RTSP URL, backend tự tạo tên `camN` trong `mediamtx.yml` Các giá trị nên dùng trên Orange Pi 5:
- Delete Camera: xóa path tương ứng trong `mediamtx.yml`
- MediaMTX record: bật/tắt `pathDefaults.record` trong `mediamtx.yml`
- Restart MediaMTX Docker: gọi `docker compose -f mediamtx/docker-compose.yml restart mediamtx`
### 3.3 Chạy backend - `mediamtx_api_url`: `http://127.0.0.1:9997`
- `mediamtx_webrtc_url`: `http://127.0.0.1:8889`
- `recordings_dir`: `/mnt/ssd/IPCam_OrangePi_Dashboard/mediamtx/recordings`
- `api_port`: `8008`
Ví dụ `api/data/config.json`:
```json
{
"mediamtx_api_url": "http://127.0.0.1:9997",
"mediamtx_webrtc_url": "http://127.0.0.1:8889",
"mediamtx_api_user": null,
"mediamtx_api_pass": null,
"recordings_dir": "/mnt/ssd/IPCam_OrangePi_Dashboard/mediamtx/recordings",
"api_port": 8008,
"cameras": [],
"schedule": {
"enabled": true,
"weekdays_from": "18:00",
"weekdays_to": "08:00",
"weekend_all_day": true
}
}
```
### 6.3) Chạy backend
```bash ```bash
cd /mnt/ssd/IPCam_OrangePi_Dashboard
source api/.venv/bin/activate source api/.venv/bin/activate
python3 -m api.run python3 -m api.run
``` ```
## 4) Frontend (build static) Kiểm tra:
### 4.1 Build
```bash ```bash
cd IPCam_OrangePi_Dashboard curl http://127.0.0.1:8008/api/health
```
## 7) Build frontend
```bash
cd /mnt/ssd/IPCam_OrangePi_Dashboard
npm install npm install
npm run build npm run build
``` ```
Output nằm ở `dist/`. Output nằm ở `dist/`.
### 4.2 Serve frontend ## 8) Serve frontend production
2 cách phổ biến: thể dùng `Nginx` hoặc `Apache`. Mục tiêu là:
1) Nginx serve `dist/` và reverse proxy `/api` + `/videos` về backend `:8008` - serve thư mục `dist/`
2) Dùng Caddy tương tự - reverse proxy `/api` về backend `127.0.0.1:8008`
- reverse proxy `/videos` về backend `127.0.0.1:8008`
Ví dụ Nginx server block tối thiểu: ### 8.1) Ví dụ Nginx
```nginx ```nginx
server { server {
listen 80; listen 80;
server_name _; server_name _;
root /opt/ipcam-dashboard/dist; root /mnt/ssd/IPCam_OrangePi_Dashboard/dist;
index index.html; index index.html;
location / { location / {
@@ -153,14 +236,14 @@ server {
} }
``` ```
Ví dụ Apache VirtualHost tối thiểu: ### 8.2) Ví dụ Apache
```apache ```apache
<VirtualHost *:80> <VirtualHost *:80>
ServerName _ ServerName _
DocumentRoot /opt/ipcam-dashboard/dist DocumentRoot /mnt/ssd/IPCam_OrangePi_Dashboard/dist
<Directory /opt/ipcam-dashboard/dist> <Directory /mnt/ssd/IPCam_OrangePi_Dashboard/dist>
Options Indexes FollowSymLinks Options Indexes FollowSymLinks
AllowOverride All AllowOverride All
Require all granted Require all granted
@@ -180,16 +263,14 @@ Ví dụ Apache VirtualHost tối thiểu:
</VirtualHost> </VirtualHost>
``` ```
Apache cần bật module trước khi reload: Nếu dùng Apache:
```bash ```bash
sudo a2enmod rewrite proxy proxy_http sudo a2enmod rewrite proxy proxy_http
sudo systemctl reload apache2 sudo systemctl reload apache2
``` ```
## 5) Systemd service (khuyến nghị) ## 9) Systemd service cho backend
### 5.1 Backend service
Tạo file `/etc/systemd/system/ipcam-dashboard.service`: Tạo file `/etc/systemd/system/ipcam-dashboard.service`:
@@ -199,8 +280,8 @@ Description=IPCam Dashboard Backend
After=network.target After=network.target
[Service] [Service]
WorkingDirectory=/opt/ipcam-dashboard WorkingDirectory=/mnt/ssd/IPCam_OrangePi_Dashboard
ExecStart=/opt/ipcam-dashboard/api/.venv/bin/python /opt/ipcam-dashboard/api/run.py ExecStart=/mnt/ssd/IPCam_OrangePi_Dashboard/api/.venv/bin/python /mnt/ssd/IPCam_OrangePi_Dashboard/api/run.py
Restart=always Restart=always
RestartSec=2 RestartSec=2
@@ -216,9 +297,31 @@ sudo systemctl enable --now ipcam-dashboard
sudo systemctl status ipcam-dashboard sudo systemctl status ipcam-dashboard
``` ```
## 6) Kiểm tra nhanh ## 10) Firewall/cổng cần mở
- Backend: `curl http://localhost:8008/api/health` Tùy hệ thống mạng, cần cho phép:
- MediaMTX API: `curl http://localhost:9997/v3/paths/list`
- Frontend: mở `http://<orange-pi-ip>/` - `8554/tcp` cho RTSP
- `8889/tcp` cho WebRTC HTTP
- `9997/tcp` cho MediaMTX API
- `8189/udp` cho ICE/WebRTC
- `80/tcp` hoặc `443/tcp` nếu serve dashboard qua web server
## 11) Kiểm tra nhanh sau triển khai
- Backend: `curl http://127.0.0.1:8008/api/health`
- MediaMTX API: `curl http://127.0.0.1:9997/v3/paths/list`
- Frontend: mở `http://<ip-orange-pi>/`
- Trong Settings:
- thêm camera bằng RTSP URL
- lưu cấu hình
- kiểm tra camera xuất hiện trong Live View
- kiểm tra file recordings được tạo trên SSD/NVMe
## 12) Ghi chú vận hành
- Nên để toàn bộ project và recordings trên cùng SSD/NVMe
- Nếu ghi nhiều camera liên tục, cần theo dõi dung lượng trống định kỳ
- Orange Pi 5 RAM `16GB` phù hợp hơn khi số camera lớn hơn hoặc cần playback đồng thời
- Khi cần ổn định cao, nên dùng nguồn tốt và tản nhiệt phù hợp cho Orange Pi 5
+83 -26
View File
@@ -1,36 +1,83 @@
# IPCam Orange Pi Dashboard # IPCam Orange Pi Dashboard
Dashboard giám sát camera IP gọn nhẹ chạy trên Orange Pi, dựa trên MediaMTX: Dashboard giám sát camera IP chạy gọn trên duy nhất một thiết bị `Orange Pi 5`, dùng `MediaMTX` làm media server, `FastAPI` làm backend và `React` làm frontend.
- Live View (WebRTC WHEP) dạng grid, auto reconnect, lazy load ## Mô hình triển khai khuyến nghị
- Playback fMP4 theo camera + ngày (file list + HTML5 video)
- Settings: quản lý camera trực tiếp trong `mediamtx.yml` + lịch ghi hình Toàn bộ hệ thống chạy trên cùng một máy:
- Thiết bị: `Orange Pi 5`
- RAM: `8GB` hoặc `16GB`
- Lưu trữ: `SSD/NVMe >= 256GB`
- Hệ điều hành: Debian/Ubuntu cho Orange Pi
- Thành phần chạy cùng máy:
- `MediaMTX`
- `FastAPI backend`
- `Frontend React build static`
- Thư mục recordings
Mô hình này phù hợp khi cần một hộp camera nội bộ gọn nhẹ, dễ bảo trì và không phụ thuộc thêm server khác.
## Tính năng chính
- Live View qua `WebRTC/WHEP`, dạng grid, tự reconnect, lazy load
- Playback file ghi hình `fMP4` theo camera và ngày
- Settings để:
- thêm/xóa camera trực tiếp vào `mediamtx.yml`
- bật/tắt ghi hình
- chỉnh lịch ghi hình
- cấu hình API/WebRTC URL của MediaMTX
- restart container MediaMTX
## Cấu trúc thư mục ## Cấu trúc thư mục
- `src/`: frontend React - `src/`: frontend React
- `api/`: backend FastAPI - `api/`: backend FastAPI
- `.trae/documents/`: tài liệu yêu cầu/kiến trúc - `mediamtx/`: Dockerfile, `docker-compose.yml`, `mediamtx.yml`
- `.trae/documents/`: tài liệu yêu cầu và kiến trúc
## Luồng hệ thống
```text
IP Camera -> MediaMTX -> FastAPI Backend -> Frontend Dashboard
|
-> recordings tren SSD/NVMe
```
## Yêu cầu phần cứng
- `Orange Pi 5` RAM `8GB` hoặc `16GB`
- Ổ lưu trữ `>= 256GB`
- Khuyến nghị dùng `NVMe SSD` thay vì thẻ nhớ để ghi hình ổn định hơn
- Nếu ghi nhiều camera hoặc giữ file lâu ngày, nên dùng `512GB` hoặc `1TB`
## Yêu cầu phần mềm
- Python `3.9+` (khuyến nghị `3.10+`)
- Node.js `20+`
- Docker và Docker Compose plugin cho MediaMTX
- Nginx hoặc Apache nếu muốn serve frontend static qua web server
## Backend API ## Backend API
- `GET /api/health` - `GET /api/health`
- `GET /api/config` - `GET /api/config`
- `POST /api/config/basic` (cập nhật thông số `config.json`) - `POST /api/config/basic`
- `GET /api/paths` (proxy trạng thái từ MediaMTX) - `GET /api/paths`
- `POST /api/recording` (bật/tắt ghi hình ngay) - `POST /api/recording`
- `POST /api/scheduler/enabled` / `POST /api/scheduler/schedule` - `POST /api/scheduler/enabled`
- `POST /api/scheduler/schedule`
- `GET /api/mediamtx/config` - `GET /api/mediamtx/config`
- `POST /api/mediamtx/cameras` (body: `{ "rtsp_url": "..." }`) - `POST /api/mediamtx/cameras`
- `DELETE /api/mediamtx/cameras/{name}` - `DELETE /api/mediamtx/cameras/{name}`
- `POST /api/mediamtx/recording` (ghi `pathDefaults.record` vào `mediamtx.yml`) - `POST /api/mediamtx/recording`
- `POST /api/mediamtx/restart` (restart container `mediamtx`) - `POST /api/mediamtx/restart`
- `GET /api/recordings?camera=cam1&date=YYYY-MM-DD` - `GET /api/recordings?camera=cam1&date=YYYY-MM-DD`
- `GET /videos/<camera>/<file>.fmp4` - `GET /videos/<camera>/<file>.fmp4`
## Chạy dev (máy dev) ## Chạy development
### 1) Chạy backend ### Backend
```bash ```bash
python3 -m venv api/.venv python3 -m venv api/.venv
@@ -39,30 +86,32 @@ pip install -r api/requirements.txt
python3 -m api.run python3 -m api.run
``` ```
### 2) Chạy frontend ### Frontend
```bash ```bash
npm install npm install
npm run dev npm run dev
``` ```
Frontend dev server đã được cấu hình proxy `/api``/videos` sang `http://localhost:8008`. Frontend dev server đã proxy sẵn `/api``/videos` sang `http://localhost:8008`.
## Cấu hình ## Cấu hình
Backend chỉ dùng file `api/data/config.json` (không đọc `.env`). Backend chỉ đọc `api/data/config.json`.
Frontend dùng `.env` ch với `VITE_DEV_BACKEND_URL``VITE_API_BASE_URL`. Frontend chỉ dùng `.env` cho môi trường dev với `VITE_DEV_BACKEND_URL``VITE_API_BASE_URL`.
Các key quan trọng trong `config.json`:
- `mediamtx_api_url`: ví dụ `http://127.0.0.1:9997` - `mediamtx_api_url`: ví dụ `http://127.0.0.1:9997`
- `mediamtx_webrtc_url`: ví dụ `http://127.0.0.1:8889` - `mediamtx_webrtc_url`: ví dụ `http://127.0.0.1:8889`
- `mediamtx_api_user`: username API (nếu bật auth trong MediaMTX) - `mediamtx_api_user`: username API nếu bật auth
- `mediamtx_api_pass`: password API (nếu bật auth trong MediaMTX) - `mediamtx_api_pass`: password API nếu bật auth
- `recordings_dir`: ví dụ `./mediamtx/recordings` (cùng máy) hoặc đường dẫn mount NFS/SMB - `recordings_dir`: đường dẫn recordings trên SSD/NVMe
- `api_port`: cổng chạy backend (mặc định `8008`) - `api_port`: cổng backend, mặc định `8008`
- `cameras`: danh sách camera được đồng bộ từ `mediamtx.yml` (`name` + `rtsp_url`) - `cameras`: danh sách camera đồng bộ từ `mediamtx.yml`
- `schedule`: lịch ghi hình - `schedule`: lịch ghi hình
Ví dụ `config.json`: Ví dụ:
```json ```json
{ {
@@ -82,6 +131,14 @@ Ví dụ `config.json`:
} }
``` ```
## Triển khai ## Triển khai production
Xem hướng dẫn chi tiết trong `INSTALL.md`. Kịch bản production chuẩn cho project này:
- `Orange Pi 5` là máy duy nhất chạy cả dashboard và MediaMTX
- MediaMTX chạy local trên chính Orange Pi
- Backend FastAPI chạy local trên chính Orange Pi
- Frontend build ra `dist/` và được serve local
- Recordings lưu vào SSD/NVMe gắn trực tiếp với Orange Pi
Hướng dẫn cài đặt chi tiết xem trong `INSTALL.md`.