244 lines
5.7 KiB
Markdown
244 lines
5.7 KiB
Markdown
# 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.
|
|
|
|
## 0) Mô hình triển khai
|
|
|
|
### A) 1 thiết bị (đơn giản nhất)
|
|
|
|
- MediaMTX + Dashboard backend + Dashboard frontend chạy cùng máy
|
|
|
|
### B) 2 thiết bị (cùng LAN / cùng lớp mạng)
|
|
|
|
- Máy A: chạy MediaMTX + lưu recordings
|
|
- Máy B: chạy Dashboard backend + frontend
|
|
- Máy B sẽ gọi:
|
|
- MediaMTX API của máy A (port 9997) để add/remove camera + bật/tắt recording
|
|
- WebRTC/WHEP của máy A (port 8889 + UDP 8189) để xem live
|
|
- Playback: máy B cần đọc được recordings của máy A (khuyến nghị mount NFS/SMB)
|
|
|
|
## 1) Yêu cầu
|
|
|
|
- Orange Pi chạy Debian/Ubuntu
|
|
- 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
|
|
|
|
Trong file `mediamtx.yml`:
|
|
|
|
```yaml
|
|
api: yes
|
|
apiAddress: :9997
|
|
|
|
webrtc: yes
|
|
webrtcAddress: :8889
|
|
webrtcAllowOrigin: '*'
|
|
|
|
record: yes
|
|
recordFormat: fmp4
|
|
recordPath: /recordings/%path/%Y-%m-%d_%H-%M-%S-%f
|
|
recordPartDuration: 5m
|
|
```
|
|
|
|
Nếu chạy mô hình 2 thiết bị, đảm bảo MediaMTX trả về đúng IP LAN để client kết nối ICE:
|
|
|
|
```yaml
|
|
webrtcAdditionalHosts:
|
|
- 192.168.88.10
|
|
```
|
|
|
|
### 2.1) Nếu MediaMTX API bị 401 Unauthorized
|
|
|
|
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.
|
|
|
|
Ví dụ trong `mediamtx.yml`:
|
|
|
|
```yaml
|
|
authMethod: internal
|
|
authInternalUsers:
|
|
- user: dashboard
|
|
pass: dashboard_password
|
|
ips: ['127.0.0.1', '::1', '192.168.88.0/24']
|
|
permissions:
|
|
- action: api
|
|
```
|
|
|
|
Sau đó set trực tiếp trong `api/data/config.json` của dashboard backend:
|
|
|
|
```
|
|
"mediamtx_api_user": "dashboard",
|
|
"mediamtx_api_pass": "dashboard_password"
|
|
```
|
|
|
|
Trong `paths`, bạn có thể để dashboard tự thêm path bằng API (Settings → Add Camera).
|
|
|
|
Tạo thư mục recordings:
|
|
|
|
```bash
|
|
sudo mkdir -p /recordings
|
|
sudo chown -R $USER:$USER /recordings
|
|
```
|
|
|
|
Mở firewall/cổng (tuỳ hệ thống):
|
|
|
|
- `8554/tcp` RTSP
|
|
- `8889/tcp` WebRTC HTTP
|
|
- `9997/tcp` MediaMTX Control API
|
|
- `8189/udp` ICE
|
|
|
|
## 2.1) Playback khi tách 2 thiết bị (mount recordings)
|
|
|
|
Vì MediaMTX ghi file recordings trên máy A, nên Dashboard (máy B) cần truy cập được folder này để:
|
|
|
|
- list file `/api/recordings`
|
|
- serve file `/videos/...`
|
|
|
|
Khuyến nghị dùng NFS (Linux-Linux):
|
|
|
|
Máy A:
|
|
|
|
```bash
|
|
sudo apt-get update
|
|
sudo apt-get install -y nfs-kernel-server
|
|
echo "/recordings 192.168.88.0/24(rw,sync,no_subtree_check)" | sudo tee -a /etc/exports
|
|
sudo exportfs -ra
|
|
```
|
|
|
|
Máy B:
|
|
|
|
```bash
|
|
sudo apt-get update
|
|
sudo apt-get install -y nfs-common
|
|
sudo mkdir -p /recordings
|
|
sudo mount -t nfs 192.168.88.10:/recordings /recordings
|
|
```
|
|
|
|
## 3) Backend FastAPI
|
|
|
|
### 3.1 Cài dependencies
|
|
|
|
```bash
|
|
cd IPCam_OrangePi_Dashboard
|
|
python3 -m venv api/.venv
|
|
source api/.venv/bin/activate
|
|
pip install -r api/requirements.txt
|
|
```
|
|
|
|
### 3.2 Cấu hình
|
|
|
|
Backend chỉ đọc cấu hình từ `api/data/config.json` (không đọc `.env`).
|
|
Chạy lần đầu sẽ tự tạo file này (lưu camera + schedule + các tham số backend).
|
|
|
|
Bạn có thể chỉnh:
|
|
|
|
- `mediamtx_api_url` (mặc định `http://127.0.0.1:9997`)
|
|
- `mediamtx_webrtc_url` (mặc định `http://127.0.0.1:8889`)
|
|
- `mediamtx_api_user` / `mediamtx_api_pass` (nếu bật auth API của MediaMTX)
|
|
- `recordings_dir` (mặc định `./mediamtx/recordings` trong project)
|
|
- `api_port` (mặc định `8008`)
|
|
|
|
Nếu chạy mô hình 2 thiết bị, set theo IP máy A (MediaMTX), ví dụ:
|
|
|
|
```json
|
|
{
|
|
"mediamtx_api_url": "http://192.168.88.10:9997",
|
|
"mediamtx_webrtc_url": "http://192.168.88.10:8889",
|
|
"mediamtx_api_user": null,
|
|
"mediamtx_api_pass": null,
|
|
"recordings_dir": "./mediamtx/recordings",
|
|
"api_port": 8008,
|
|
"cameras": [],
|
|
"schedule": { "enabled": true, "weekdays_from": "18:00", "weekdays_to": "08:00", "weekend_all_day": true }
|
|
}
|
|
```
|
|
|
|
### 3.3 Chạy backend
|
|
|
|
```bash
|
|
source api/.venv/bin/activate
|
|
python3 -m api.run
|
|
```
|
|
|
|
## 4) Frontend (build static)
|
|
|
|
### 4.1 Build
|
|
|
|
```bash
|
|
cd IPCam_OrangePi_Dashboard
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
Output nằm ở `dist/`.
|
|
|
|
### 4.2 Serve frontend
|
|
|
|
Có 2 cách phổ biến:
|
|
|
|
1) Nginx serve `dist/` và reverse proxy `/api` + `/videos` về backend `:8008`
|
|
2) Dùng Caddy tương tự
|
|
|
|
Ví dụ Nginx server block tối thiểu:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
|
|
root /opt/ipcam-dashboard/dist;
|
|
index index.html;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:8008;
|
|
}
|
|
|
|
location /videos/ {
|
|
proxy_pass http://127.0.0.1:8008;
|
|
}
|
|
}
|
|
```
|
|
|
|
Nếu chạy mô hình 2 thiết bị, phần Nginx ở máy B không cần proxy tới MediaMTX. Frontend sẽ gọi trực tiếp `mediamtx_webrtc_url` (máy A).
|
|
|
|
## 5) Systemd service (khuyến nghị)
|
|
|
|
### 5.1 Backend service
|
|
|
|
Tạo file `/etc/systemd/system/ipcam-dashboard.service`:
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=IPCam Dashboard Backend
|
|
After=network.target
|
|
|
|
[Service]
|
|
WorkingDirectory=/opt/ipcam-dashboard
|
|
ExecStart=/opt/ipcam-dashboard/api/.venv/bin/python /opt/ipcam-dashboard/api/run.py
|
|
Restart=always
|
|
RestartSec=2
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Enable:
|
|
|
|
```bash
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now ipcam-dashboard
|
|
sudo systemctl status ipcam-dashboard
|
|
```
|
|
|
|
## 6) Kiểm tra nhanh
|
|
|
|
- Backend: `curl http://localhost:8008/api/health`
|
|
- MediaMTX API: `curl http://localhost:9997/v3/paths/list`
|
|
- Frontend: mở `http://<orange-pi-ip>/`
|
|
|