新增支持人脸识别的压测脚本;优化部署脚本和文档
This commit is contained in:
parent
aea8ec0622
commit
b5b36457e4
340
configs/stress_5ch_face_recog.json
Normal file
340
configs/stress_5ch_face_recog.json
Normal file
@ -0,0 +1,340 @@
|
||||
{
|
||||
"global": {
|
||||
"metrics_port": 9000,
|
||||
"web_root": "web"
|
||||
},
|
||||
"queue": {
|
||||
"size": 4,
|
||||
"strategy": "drop_oldest"
|
||||
},
|
||||
"templates": {
|
||||
"face_recog_pipeline": {
|
||||
"nodes": [
|
||||
{
|
||||
"id": "in",
|
||||
"type": "input_rtsp",
|
||||
"role": "source",
|
||||
"enable": true,
|
||||
"url": "${url}",
|
||||
"fps": "${fps}",
|
||||
"width": "${src_w}",
|
||||
"height": "${src_h}",
|
||||
"use_mpp": true,
|
||||
"use_ffmpeg": false,
|
||||
"force_tcp": true,
|
||||
"reconnect_sec": 5,
|
||||
"reconnect_backoff_max_sec": 30
|
||||
},
|
||||
{
|
||||
"id": "pre",
|
||||
"type": "preprocess",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"dst_w": 640,
|
||||
"dst_h": 640,
|
||||
"dst_format": "rgb",
|
||||
"dst_packed": true,
|
||||
"keep_ratio": false,
|
||||
"rga_gate": "${name}",
|
||||
"use_rga": true
|
||||
},
|
||||
{
|
||||
"id": "ai",
|
||||
"type": "ai_yolo",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"infer_fps": 10,
|
||||
"model_path": "./models/best-640.rknn",
|
||||
"model_version": "v8",
|
||||
"num_classes": 3,
|
||||
"conf": 0.35,
|
||||
"nms": 0.45,
|
||||
"class_filter": []
|
||||
},
|
||||
{
|
||||
"id": "face_det",
|
||||
"type": "ai_face_det",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"model_path": "./models/RetinaFace_mobile320.rknn",
|
||||
"conf": 0.7,
|
||||
"nms": 0.4,
|
||||
"max_faces": 10,
|
||||
"output_landmarks": true,
|
||||
"input_format": "rgb"
|
||||
},
|
||||
{
|
||||
"id": "face_recog",
|
||||
"type": "ai_face_recog",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"model_path": "./models/mobilefacenet_arcface.rknn",
|
||||
"align": true,
|
||||
"emit_embedding": false,
|
||||
"max_faces": 10,
|
||||
"input_format": "rgb",
|
||||
"input_dtype": "uint8",
|
||||
"threshold": {
|
||||
"accept": 0.45,
|
||||
"margin": 0.05
|
||||
},
|
||||
"gallery": {
|
||||
"backend": "sqlite",
|
||||
"path": "${face_gallery_path}",
|
||||
"load_on_start": true,
|
||||
"expected_dim": 512,
|
||||
"dtype": "auto"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "trk",
|
||||
"type": "tracker",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"mode": "bytetrack_lite",
|
||||
"per_class": true,
|
||||
"state_key": "${name}",
|
||||
"track_classes": [0, 1, 2],
|
||||
"ignore_classes": [],
|
||||
"allowed_models": ["yolov5", "yolov8"],
|
||||
"high_th": 0.5,
|
||||
"low_th": 0.1,
|
||||
"iou_th": 0.3,
|
||||
"max_age_ms": 1500,
|
||||
"min_hits": 2,
|
||||
"max_tracks": 128,
|
||||
"debug": {
|
||||
"stats": false,
|
||||
"stats_interval": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "osd",
|
||||
"type": "osd",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"draw_bbox": true,
|
||||
"draw_text": true,
|
||||
"line_width": 2,
|
||||
"font_scale": 1,
|
||||
"labels": [],
|
||||
"use_rga_bbox": false,
|
||||
"draw_face_det": true,
|
||||
"draw_face_bbox": true
|
||||
},
|
||||
{
|
||||
"id": "post",
|
||||
"type": "preprocess",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"queue": {
|
||||
"size": 2,
|
||||
"policy": "drop_oldest"
|
||||
},
|
||||
"dst_w": "${src_w}",
|
||||
"dst_h": "${src_h}",
|
||||
"dst_format": "nv12",
|
||||
"keep_ratio": false,
|
||||
"rga_gate": "${name}",
|
||||
"use_rga": true
|
||||
},
|
||||
{
|
||||
"id": "alarm",
|
||||
"type": "alarm",
|
||||
"role": "sink",
|
||||
"enable": true,
|
||||
"eval_fps": 10,
|
||||
"labels": [],
|
||||
"rules": [
|
||||
{
|
||||
"name": "object_in_view",
|
||||
"class_ids": [0, 1, 2],
|
||||
"roi": {"x": 0.0, "y": 0.0, "w": 1.0, "h": 1.0},
|
||||
"min_score": 0.4,
|
||||
"min_box_area_ratio": 0.02,
|
||||
"require_track_id": true,
|
||||
"min_duration_ms": 1500,
|
||||
"min_hits": 3,
|
||||
"hit_window_ms": 1500,
|
||||
"cooldown_ms": 5000,
|
||||
"per_track_cooldown_ms": 5000
|
||||
}
|
||||
],
|
||||
"actions": {
|
||||
"log": {"enable": true, "level": "info"},
|
||||
"snapshot": {
|
||||
"enable": true,
|
||||
"min_interval_ms": 15000,
|
||||
"format": "jpg",
|
||||
"quality": 85,
|
||||
"upload": {
|
||||
"type": "minio",
|
||||
"endpoint": "${minio_endpoint}",
|
||||
"bucket": "${minio_bucket}",
|
||||
"region": "us-east-1",
|
||||
"access_key": "${minio_ak}",
|
||||
"secret_key": "${minio_sk}"
|
||||
}
|
||||
},
|
||||
"clip": {
|
||||
"enable": true,
|
||||
"min_interval_ms": 15000,
|
||||
"pre_sec": 5,
|
||||
"post_sec": 10,
|
||||
"format": "mp4",
|
||||
"fps": "${fps}",
|
||||
"upload": {
|
||||
"type": "minio",
|
||||
"endpoint": "${minio_endpoint}",
|
||||
"bucket": "${minio_bucket}",
|
||||
"region": "us-east-1",
|
||||
"access_key": "${minio_ak}",
|
||||
"secret_key": "${minio_sk}"
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"enable": false,
|
||||
"url": "http://127.0.0.1:8080/api/alarm",
|
||||
"timeout_ms": 3000,
|
||||
"include_media_url": true,
|
||||
"method": "POST"
|
||||
},
|
||||
"external_api": {
|
||||
"enable": true,
|
||||
"getTokenUrl": "http://10.0.0.49:8080/api/getToken",
|
||||
"putMessageUrl": "http://10.0.0.49:8080/api/putMessage",
|
||||
"tenantCode": "32",
|
||||
"channelNo": "${name}",
|
||||
"timeout_ms": 3000,
|
||||
"include_media_url": true,
|
||||
"token_header": "X-Access-Token",
|
||||
"token_json_path": "responseBody.token",
|
||||
"token_cache_sec": 1200
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "pub",
|
||||
"type": "publish",
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"queue": {"size": 2, "policy": "drop_oldest"},
|
||||
"codec": "h264",
|
||||
"fps": "${fps}",
|
||||
"gop": "${gop}",
|
||||
"bitrate_kbps": "${bitrate_kbps}",
|
||||
"use_mpp": true,
|
||||
"use_ffmpeg_mux": true,
|
||||
"outputs": [
|
||||
{"proto": "rtsp_server", "port": 8555, "path": "/live/${name}"},
|
||||
{"proto": "hls", "path": "./web/hls/${name}/index.m3u8", "segment_sec": 2}
|
||||
],
|
||||
"debug": {"stats": true, "stats_interval": 100}
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
["in", "pre"],
|
||||
["pre", "ai"],
|
||||
["ai", "trk"],
|
||||
["trk", "face_det"],
|
||||
["face_det", "face_recog"],
|
||||
["face_recog", "osd"],
|
||||
["osd", "post"],
|
||||
["post", "pub"],
|
||||
["pub", "alarm"]
|
||||
]
|
||||
}
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
"name": "cam1",
|
||||
"template": "face_recog_pipeline",
|
||||
"params": {
|
||||
"name": "cam1",
|
||||
"url": "rtsp://10.0.0.49:8554/cam",
|
||||
"src_w": 1280,
|
||||
"src_h": 720,
|
||||
"fps": 30,
|
||||
"gop": 60,
|
||||
"bitrate_kbps": 2000,
|
||||
"face_gallery_path": "./models/face_gallery_cam1.db",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_ak": "minioadmin",
|
||||
"minio_sk": "minioadmin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cam2",
|
||||
"template": "face_recog_pipeline",
|
||||
"params": {
|
||||
"name": "cam2",
|
||||
"url": "rtsp://10.0.0.49:8554/cam",
|
||||
"src_w": 1280,
|
||||
"src_h": 720,
|
||||
"fps": 30,
|
||||
"gop": 60,
|
||||
"bitrate_kbps": 2000,
|
||||
"face_gallery_path": "./models/face_gallery_cam2.db",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_ak": "minioadmin",
|
||||
"minio_sk": "minioadmin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cam3",
|
||||
"template": "face_recog_pipeline",
|
||||
"params": {
|
||||
"name": "cam3",
|
||||
"url": "rtsp://10.0.0.49:8554/cam",
|
||||
"src_w": 1280,
|
||||
"src_h": 720,
|
||||
"fps": 30,
|
||||
"gop": 60,
|
||||
"bitrate_kbps": 2000,
|
||||
"face_gallery_path": "./models/face_gallery_cam3.db",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_ak": "minioadmin",
|
||||
"minio_sk": "minioadmin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cam4",
|
||||
"template": "face_recog_pipeline",
|
||||
"params": {
|
||||
"name": "cam4",
|
||||
"url": "rtsp://10.0.0.49:8554/cam",
|
||||
"src_w": 1280,
|
||||
"src_h": 720,
|
||||
"fps": 30,
|
||||
"gop": 60,
|
||||
"bitrate_kbps": 2000,
|
||||
"face_gallery_path": "./models/face_gallery_cam4.db",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_ak": "minioadmin",
|
||||
"minio_sk": "minioadmin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cam5",
|
||||
"template": "face_recog_pipeline",
|
||||
"params": {
|
||||
"name": "cam5",
|
||||
"url": "rtsp://10.0.0.49:8554/cam",
|
||||
"src_w": 1280,
|
||||
"src_h": 720,
|
||||
"fps": 30,
|
||||
"gop": 60,
|
||||
"bitrate_kbps": 2000,
|
||||
"face_gallery_path": "./models/face_gallery_cam5.db",
|
||||
"minio_endpoint": "http://10.0.0.49:9000",
|
||||
"minio_bucket": "myminio",
|
||||
"minio_ak": "minioadmin",
|
||||
"minio_sk": "minioadmin"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -3,20 +3,40 @@
|
||||
## 架构说明
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ Media Server │ │ RK3588 Agent │
|
||||
│ (systemd) │◄────│ (systemd) │
|
||||
│ 高可用独立服务 │ │ 监控/控制 │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
RTSP 输出流 Web 管理界面
|
||||
HLS 输出流 http://IP:9100
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ RK3588 Device │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌─────────────────────┐ │
|
||||
│ │ Media Server │ │ RK3588 Agent │ │
|
||||
│ │ (systemd) │◄────│ (systemd) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ - RTSP输出 │ │ - Web管理界面 │ │
|
||||
│ │ - HLS输出 │ │ - 服务监控 │ │
|
||||
│ │ - NPU推理 │ │ - 远程配置 │ │
|
||||
│ └─────────┬───────────┘ └─────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌───────────────────────────────────────────────────┐ │
|
||||
│ │ 运行时数据目录 │ │
|
||||
│ │ /var/lib/rk3588-media-server/ │ │
|
||||
│ │ ├── hls/ - HLS分片输出 │ │
|
||||
│ │ ├── logs/ - 应用日志 │ │
|
||||
│ │ ├── alarms/ - 告警截图 │ │
|
||||
│ │ └── clips/ - 告警视频片段 │ │
|
||||
│ └───────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ /opt/rk3588-media-server/ # 程序文件 │
|
||||
│ /opt/rk3588-agent/ # Agent程序 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 设计特点
|
||||
|
||||
- **Media Server**: 独立的 systemd 服务,高可用(崩溃自动重启)
|
||||
- **Agent**: 独立的 systemd 服务,通过 `systemctl` 监控和控制 Media Server
|
||||
- **两者可独立重启**: 重启 Agent 不会影响 Media Server
|
||||
- **运行时数据分离**: 程序文件在 `/opt/`,数据在 `/var/lib/`
|
||||
- **自动清理**: HLS 分片、日志、告警数据自动轮转清理
|
||||
|
||||
---
|
||||
|
||||
@ -34,47 +54,188 @@ mkdir -p build && cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
make -j$(nproc)
|
||||
|
||||
# 编译 Agent
|
||||
# 编译 Agent(可选)
|
||||
cd ../agent
|
||||
go build -o rk3588-agent_linux_arm64 ./cmd/rk3588-agent
|
||||
```
|
||||
|
||||
### 2. 安装
|
||||
### 2. 部署
|
||||
|
||||
```bash
|
||||
cd ~/apps/OrangePi3588Media
|
||||
sudo ./scripts/manage.sh install
|
||||
sudo ./scripts/deploy.sh install
|
||||
```
|
||||
|
||||
安装过程会提示选择**配置文件**:
|
||||
- `test_cam1_face_det_rtsp_server.json` - 人脸检测(推荐)
|
||||
- `sample_cam1_native_rtsp_face.json` - 完整功能
|
||||
- `test_cam1_face_det_recog_rtsp_server.json` - 人脸识别
|
||||
- `sample_cam1.json` - 完整功能(需手动修复)
|
||||
部署过程会:
|
||||
1. 安装 Media Server 和 Agent 到 `/opt/`
|
||||
2. 创建运行时数据目录 `/var/lib/rk3588-media-server/`
|
||||
3. 配置日志轮转和自动清理
|
||||
4. 启动 systemd 服务
|
||||
|
||||
### 3. 查看状态
|
||||
|
||||
```bash
|
||||
sudo ./scripts/manage.sh status
|
||||
sudo ./scripts/deploy.sh status
|
||||
```
|
||||
|
||||
显示内容:
|
||||
- 系统运行时间
|
||||
- NPU 负载
|
||||
- Media Server 状态(PID、CPU/内存、端口)
|
||||
- Agent 状态
|
||||
- 最近日志
|
||||
|
||||
### 4. 卸载
|
||||
|
||||
```bash
|
||||
sudo ./scripts/manage.sh uninstall
|
||||
sudo ./scripts/deploy.sh uninstall
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 完整命令参考
|
||||
|
||||
### 部署脚本命令
|
||||
|
||||
| 命令 | 说明 |
|
||||
|------|------|
|
||||
| `sudo ./deploy.sh install` | 安装/部署服务 |
|
||||
| `sudo ./deploy.sh upgrade` | 升级服务(保留配置和数据)|
|
||||
| `sudo ./deploy.sh status` | 查看详细运行状态 |
|
||||
| `sudo ./deploy.sh logs` | 查看实时日志 |
|
||||
| `sudo ./deploy.sh clean-hls [天数]` | 清理 HLS 旧分片 |
|
||||
| `sudo ./deploy.sh uninstall` | 卸载服务 |
|
||||
|
||||
### Media Server 服务管理
|
||||
|
||||
```bash
|
||||
# 启动/停止/重启
|
||||
sudo systemctl start media-server
|
||||
sudo systemctl stop media-server
|
||||
sudo systemctl restart media-server
|
||||
|
||||
# 查看状态
|
||||
sudo systemctl status media-server
|
||||
|
||||
# 查看日志
|
||||
sudo journalctl -u media-server -f
|
||||
sudo journalctl -u media-server --since "1 hour ago"
|
||||
```
|
||||
|
||||
### Agent 服务管理
|
||||
|
||||
```bash
|
||||
# 启动/停止/重启(不影响 Media Server)
|
||||
sudo systemctl start rk3588-agent
|
||||
sudo systemctl stop rk3588-agent
|
||||
sudo systemctl restart rk3588-agent
|
||||
|
||||
# 查看状态
|
||||
sudo systemctl status rk3588-agent
|
||||
|
||||
# 查看日志
|
||||
sudo journalctl -u rk3588-agent -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 目录结构
|
||||
|
||||
### 程序目录 (/opt/)
|
||||
|
||||
```
|
||||
/opt/rk3588-media-server/
|
||||
├── bin/
|
||||
│ ├── media-server # 主程序
|
||||
│ ├── cleanup-hls.sh # HLS清理脚本
|
||||
│ └── plugins/ # 插件目录
|
||||
│ ├── libinput_rtsp.so
|
||||
│ ├── libai_yolo.so
|
||||
│ ├── libosd.so
|
||||
│ ├── libtracker.so
|
||||
│ └── ...
|
||||
├── lib/ # 依赖库
|
||||
├── etc/
|
||||
│ └── media-server.json # 配置文件
|
||||
├── models/ # AI模型文件
|
||||
│ ├── best-640.rknn
|
||||
│ ├── yolov5s-640-640.rknn
|
||||
│ └── ...
|
||||
└── web/ # Web静态文件
|
||||
├── index.html
|
||||
├── graph.html
|
||||
├── hls_player.html # HLS播放器
|
||||
└── hls/ # HLS输出(符号链接)
|
||||
|
||||
/opt/rk3588-agent/
|
||||
├── rk3588-agent # Agent程序
|
||||
└── agent.config.json # Agent配置
|
||||
```
|
||||
|
||||
### 运行时数据目录 (/var/lib/)
|
||||
|
||||
```
|
||||
/var/lib/rk3588-media-server/
|
||||
├── hls/ # HLS直播分片
|
||||
│ ├── cam1/
|
||||
│ │ ├── index.m3u8
|
||||
│ │ ├── index0.ts
|
||||
│ │ └── ...
|
||||
│ ├── cam2/
|
||||
│ └── ...
|
||||
├── logs/ # 应用日志
|
||||
├── alarms/ # 告警截图
|
||||
└── clips/ # 告警视频片段
|
||||
|
||||
/var/lib/rk3588-agent/
|
||||
└── device_id # 设备唯一标识
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置修改
|
||||
|
||||
编辑配置文件:
|
||||
|
||||
```bash
|
||||
sudo nano /opt/rk3588-media-server/etc/media-server.json
|
||||
```
|
||||
|
||||
修改后重启服务:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart media-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据管理
|
||||
|
||||
### HLS 分片清理
|
||||
|
||||
HLS 分片自动清理策略:
|
||||
- **默认保留**: 3天
|
||||
- **自动执行**: 每天凌晨3点
|
||||
- **手动执行**: `sudo /opt/rk3588-media-server/bin/cleanup-hls.sh [天数]`
|
||||
|
||||
### 日志轮转
|
||||
|
||||
日志自动轮转策略:
|
||||
- **保留周期**: 7天
|
||||
- **压缩**: 启用
|
||||
- **位置**: `/var/lib/rk3588-media-server/logs/`
|
||||
|
||||
### 告警数据清理
|
||||
|
||||
自动清理策略(通过 cron):
|
||||
- **告警视频** (clips): 保留30天
|
||||
- **告警图片** (alarms): 保留90天
|
||||
|
||||
查看当前存储使用:
|
||||
|
||||
```bash
|
||||
sudo ./scripts/deploy.sh status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 升级
|
||||
|
||||
升级步骤(保留配置和数据):
|
||||
|
||||
```bash
|
||||
cd ~/apps/OrangePi3588Media
|
||||
|
||||
@ -89,46 +250,16 @@ make -j$(nproc)
|
||||
cd ../agent
|
||||
go build -o rk3588-agent_linux_arm64 ./cmd/rk3588-agent
|
||||
|
||||
# 3. 重新安装
|
||||
# 3. 执行升级
|
||||
cd ..
|
||||
sudo ./scripts/manage.sh install
|
||||
sudo ./scripts/deploy.sh upgrade
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 管理命令
|
||||
## Web 管理界面
|
||||
|
||||
### Media Server(独立服务)
|
||||
|
||||
```bash
|
||||
# 启动/停止/重启
|
||||
sudo systemctl start media-server
|
||||
sudo systemctl stop media-server
|
||||
sudo systemctl restart media-server
|
||||
|
||||
# 查看状态
|
||||
sudo systemctl status media-server
|
||||
|
||||
# 查看日志
|
||||
sudo journalctl -u media-server -f
|
||||
```
|
||||
|
||||
### Agent(独立服务)
|
||||
|
||||
```bash
|
||||
# 启动/停止/重启(不影响 Media Server)
|
||||
sudo systemctl start rk3588-agent
|
||||
sudo systemctl stop rk3588-agent
|
||||
sudo systemctl restart rk3588-agent
|
||||
|
||||
# 查看状态
|
||||
sudo systemctl status rk3588-agent
|
||||
|
||||
# 查看日志
|
||||
sudo journalctl -u rk3588-agent -f
|
||||
```
|
||||
|
||||
### Web 管理界面
|
||||
### Agent 管理界面
|
||||
|
||||
```
|
||||
http://<设备IP>:9100
|
||||
@ -136,45 +267,20 @@ http://<设备IP>:9100
|
||||
|
||||
功能:
|
||||
- 查看 Media Server 运行状态
|
||||
- 启动/停止/重启 Media Server(通过 systemctl)
|
||||
- 启动/停止/重启 Media Server
|
||||
- 查看配置信息
|
||||
|
||||
---
|
||||
|
||||
## 配置修改
|
||||
|
||||
编辑配置文件:
|
||||
|
||||
```bash
|
||||
sudo nano /opt/rk3588-media-server/etc/media-server.json
|
||||
```
|
||||
|
||||
修改后重启 Media Server:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart media-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 目录结构
|
||||
### HLS 播放器
|
||||
|
||||
```
|
||||
/opt/rk3588-media-server/
|
||||
├── bin/
|
||||
│ ├── media-server # 主程序
|
||||
│ └── plugins/ # 插件
|
||||
├── etc/
|
||||
│ └── media-server.json # 配置文件
|
||||
├── models/ # AI 模型
|
||||
├── logs/ # 日志
|
||||
└── web/hls/ # HLS 输出
|
||||
|
||||
/opt/rk3588-agent/
|
||||
├── rk3588-agent # Agent 程序
|
||||
└── agent.config.json # Agent 配置
|
||||
http://<设备IP>:9000/hls_player.html
|
||||
```
|
||||
|
||||
功能:
|
||||
- 5 路视频同时播放
|
||||
- 自适应布局
|
||||
- 实时状态显示
|
||||
|
||||
---
|
||||
|
||||
## 故障排查
|
||||
@ -182,34 +288,113 @@ sudo systemctl restart media-server
|
||||
### 服务无法启动
|
||||
|
||||
```bash
|
||||
# Media Server 错误
|
||||
# 查看详细错误
|
||||
sudo journalctl -u media-server -n 50
|
||||
|
||||
# Agent 错误
|
||||
sudo journalctl -u rk3588-agent -n 50
|
||||
# 检查配置文件语法
|
||||
sudo cat /opt/rk3588-media-server/etc/media-server.json | python3 -m json.tool
|
||||
|
||||
# 检查目录权限
|
||||
ls -la /var/lib/rk3588-media-server/
|
||||
ls -la /opt/rk3588-media-server/
|
||||
```
|
||||
|
||||
### 检查 NPU
|
||||
### NPU 问题
|
||||
|
||||
```bash
|
||||
cat /sys/kernel/debug/rknpu/load
|
||||
ls /dev/rknpu
|
||||
# 查看 NPU 状态
|
||||
cat /proc/rknpu/load
|
||||
cat /proc/rknpu/version
|
||||
|
||||
# 查看设备节点
|
||||
ls -la /dev/rknpu*
|
||||
|
||||
# 查看温度
|
||||
cat /sys/class/thermal/thermal_zone6/temp
|
||||
```
|
||||
|
||||
### RTSP 测试
|
||||
### HLS 无法播放
|
||||
|
||||
```bash
|
||||
# 检查 HLS 输出目录
|
||||
ls -la /var/lib/rk3588-media-server/hls/
|
||||
|
||||
# 检查分片生成
|
||||
ls -la /var/lib/rk3588-media-server/hls/cam1/
|
||||
|
||||
# 检查服务端口
|
||||
ss -tlnp | grep 9000
|
||||
```
|
||||
|
||||
### RTSP 无法连接
|
||||
|
||||
```bash
|
||||
# 本地测试
|
||||
ffplay rtsp://localhost:8555/live/cam1_face_det
|
||||
ffplay rtsp://localhost:8555/live/cam1
|
||||
|
||||
# 远程测试
|
||||
ffplay rtsp://<设备IP>:8555/live/cam1_face_det
|
||||
# 检查端口
|
||||
ss -tlnp | grep 8555
|
||||
|
||||
# 查看编码器状态
|
||||
grep "RKVENC" /proc/mpp_service/sessions-summary
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 系统要求
|
||||
|
||||
- **硬件**: Orange Pi 5 Plus (RK3588)
|
||||
- **系统**: Ubuntu 22.04 LTS (ARM64)
|
||||
- **硬件**: Orange Pi 5 Plus (RK3588) 或其他 RK3588 设备
|
||||
- **系统**: Ubuntu 22.04 LTS (ARM64) 或 Debian 11
|
||||
- **内存**: 建议 4GB 以上
|
||||
- **存储**: 建议 32GB 以上(HLS 分片占用空间)
|
||||
- **依赖**: RKNN Runtime, MPP, FFmpeg
|
||||
|
||||
---
|
||||
|
||||
## 性能参考
|
||||
|
||||
5 路 720p@30fps 并发处理:
|
||||
|
||||
| 资源 | 使用率 | 备注 |
|
||||
|------|--------|------|
|
||||
| NPU Core0 | 70-80% | YOLO 推理 |
|
||||
| CPU | 20-30% | 预处理、编码 |
|
||||
| 编码器 | 5 路 720p | H264 CBR 2Mbps |
|
||||
| 温度 | 50-60°C | 正常范围 |
|
||||
| 内存 | 3-4GB | 包含系统 |
|
||||
|
||||
---
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
### 备份配置和数据
|
||||
|
||||
```bash
|
||||
# 创建备份
|
||||
BACKUP_DIR="/root/rk3588-backup-$(date +%Y%m%d)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# 备份配置
|
||||
cp /opt/rk3588-media-server/etc/media-server.json "$BACKUP_DIR/"
|
||||
|
||||
# 备份模型
|
||||
cp -r /opt/rk3588-media-server/models "$BACKUP_DIR/"
|
||||
|
||||
# 备份 HLS(可选,占用空间大)
|
||||
cp -r /var/lib/rk3588-media-server/hls "$BACKUP_DIR/"
|
||||
|
||||
echo "备份完成: $BACKUP_DIR"
|
||||
```
|
||||
|
||||
### 恢复
|
||||
|
||||
```bash
|
||||
# 恢复配置
|
||||
cp "$BACKUP_DIR/media-server.json" /opt/rk3588-media-server/etc/
|
||||
|
||||
# 恢复模型
|
||||
cp -r "$BACKUP_DIR/models"/* /opt/rk3588-media-server/models/
|
||||
|
||||
# 重启服务
|
||||
sudo systemctl restart media-server
|
||||
```
|
||||
|
||||
BIN
models/face_gallery_cam1.db
Normal file
BIN
models/face_gallery_cam1.db
Normal file
Binary file not shown.
BIN
models/face_gallery_cam2.db
Normal file
BIN
models/face_gallery_cam2.db
Normal file
Binary file not shown.
BIN
models/face_gallery_cam3.db
Normal file
BIN
models/face_gallery_cam3.db
Normal file
Binary file not shown.
BIN
models/face_gallery_cam4.db
Normal file
BIN
models/face_gallery_cam4.db
Normal file
Binary file not shown.
BIN
models/face_gallery_cam5.db
Normal file
BIN
models/face_gallery_cam5.db
Normal file
Binary file not shown.
737
scripts/deploy.sh
Executable file
737
scripts/deploy.sh
Executable file
@ -0,0 +1,737 @@
|
||||
#!/bin/bash
|
||||
# RK3588 Media Server + Agent 完善部署脚本
|
||||
# 部署到 /opt,包含完整的运行时目录、权限、日志轮转等
|
||||
#
|
||||
# 用法: sudo ./deploy.sh [install|upgrade|status|logs|clean-hls|uninstall]
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 目录定义
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
BUILD_DIR="$PROJECT_DIR/build"
|
||||
|
||||
# 安装目录
|
||||
INSTALL_DIR="/opt/rk3588-media-server"
|
||||
AGENT_INSTALL_DIR="/opt/rk3588-agent"
|
||||
SERVICE_DIR="/etc/systemd/system"
|
||||
LOGROTATE_DIR="/etc/logrotate.d"
|
||||
|
||||
# 运行时数据目录(持久化数据)
|
||||
RUNTIME_DIR="/var/lib/rk3588-media-server"
|
||||
HLS_DIR="$RUNTIME_DIR/hls"
|
||||
LOGS_DIR="$RUNTIME_DIR/logs"
|
||||
ALARMS_DIR="$RUNTIME_DIR/alarms"
|
||||
CLIPS_DIR="$RUNTIME_DIR/clips"
|
||||
|
||||
# 创建必要的运行时目录
|
||||
create_runtime_dirs() {
|
||||
echo -e "${CYAN}[创建运行时目录]${NC}"
|
||||
|
||||
# 主运行时目录
|
||||
mkdir -p "$RUNTIME_DIR"
|
||||
mkdir -p "$HLS_DIR"
|
||||
mkdir -p "$LOGS_DIR"
|
||||
mkdir -p "$ALARMS_DIR"
|
||||
mkdir -p "$CLIPS_DIR"
|
||||
|
||||
# 设置权限(root用户运行,但允许orangepi组读取)
|
||||
chown -R root:root "$RUNTIME_DIR"
|
||||
chmod 755 "$RUNTIME_DIR"
|
||||
chmod 755 "$HLS_DIR"
|
||||
chmod 755 "$LOGS_DIR"
|
||||
chmod 755 "$ALARMS_DIR"
|
||||
chmod 755 "$CLIPS_DIR"
|
||||
|
||||
echo -e "${GREEN}✓${NC} 运行时目录创建完成:"
|
||||
echo " HLS输出: $HLS_DIR"
|
||||
echo " 日志: $LOGS_DIR"
|
||||
echo " 告警图片: $ALARMS_DIR"
|
||||
echo " 告警视频: $CLIPS_DIR"
|
||||
}
|
||||
|
||||
# 安装日志轮转配置
|
||||
install_logrotate() {
|
||||
echo -e "${CYAN}[配置日志轮转]${NC}"
|
||||
|
||||
# Media Server 日志轮转
|
||||
cat > "$LOGROTATE_DIR/rk3588-media-server" << 'EOF'
|
||||
/var/lib/rk3588-media-server/logs/*.log {
|
||||
daily
|
||||
rotate 7
|
||||
compress
|
||||
delaycompress
|
||||
missingok
|
||||
notifempty
|
||||
create 644 root root
|
||||
sharedscripts
|
||||
postrotate
|
||||
/bin/kill -HUP $(cat /var/run/syslogd.pid 2>/dev/null) 2>/dev/null || true
|
||||
endscript
|
||||
}
|
||||
EOF
|
||||
|
||||
# HLS 分片清理(保留最近7天)
|
||||
cat > "$LOGROTATE_DIR/rk3588-hls" << 'EOF'
|
||||
/var/lib/rk3588-media-server/hls/*/index*.ts {
|
||||
daily
|
||||
rotate 1
|
||||
maxage 7
|
||||
missingok
|
||||
notifempty
|
||||
nocompress
|
||||
}
|
||||
|
||||
/var/lib/rk3588-media-server/hls/*/index*.m3u8 {
|
||||
daily
|
||||
rotate 1
|
||||
maxage 7
|
||||
missingok
|
||||
notifempty
|
||||
nocompress
|
||||
}
|
||||
EOF
|
||||
|
||||
chmod 644 "$LOGROTATE_DIR/rk3588-media-server"
|
||||
chmod 644 "$LOGROTATE_DIR/rk3588-hls"
|
||||
|
||||
echo -e "${GREEN}✓${NC} 日志轮转配置完成"
|
||||
}
|
||||
|
||||
# 安装 HLS 清理脚本
|
||||
install_hls_cleanup() {
|
||||
echo -e "${CYAN}[安装 HLS 清理脚本]${NC}"
|
||||
|
||||
cat > "$INSTALL_DIR/bin/cleanup-hls.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
# HLS 分片清理脚本 - 保留最近 N 天的分片
|
||||
|
||||
KEEP_DAYS=${1:-3}
|
||||
HLS_DIR="/var/lib/rk3588-media-server/hls"
|
||||
|
||||
if [ ! -d "$HLS_DIR" ]; then
|
||||
echo "HLS 目录不存在: $HLS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 清理旧的分片文件
|
||||
find "$HLS_DIR" -name "*.ts" -type f -mtime +$KEEP_DAYS -delete 2>/dev/null
|
||||
|
||||
# 清理空的摄像头目录
|
||||
find "$HLS_DIR" -type d -empty -delete 2>/dev/null
|
||||
|
||||
echo "$(date): HLS 清理完成 (保留最近 $KEEP_DAYS 天)"
|
||||
EOF
|
||||
|
||||
chmod +x "$INSTALL_DIR/bin/cleanup-hls.sh"
|
||||
|
||||
# 添加到 crontab(每天凌晨3点执行)
|
||||
CRON_FILE="/etc/cron.d/rk3588-media-server"
|
||||
cat > "$CRON_FILE" << 'EOF'
|
||||
# RK3588 Media Server 定时任务
|
||||
SHELL=/bin/bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
# 每天凌晨3点清理HLS旧分片(保留3天)
|
||||
0 3 * * * root /opt/rk3588-media-server/bin/cleanup-hls.sh 3 >> /var/lib/rk3588-media-server/logs/cleanup.log 2>&1
|
||||
|
||||
# 每周日凌晨4点清理告警视频(保留30天)
|
||||
0 4 * * 0 root find /var/lib/rk3588-media-server/clips -name "*.mp4" -type f -mtime +30 -delete 2>/dev/null
|
||||
|
||||
# 每周日凌晨4点清理告警图片(保留90天)
|
||||
30 4 * * 0 root find /var/lib/rk3588-media-server/alarms -name "*.jpg" -type f -mtime +90 -delete 2>/dev/null
|
||||
EOF
|
||||
|
||||
chmod 644 "$CRON_FILE"
|
||||
|
||||
echo -e "${GREEN}✓${NC} HLS 清理脚本安装完成"
|
||||
echo " 清理策略:"
|
||||
echo " - HLS分片: 保留3天"
|
||||
echo " - 告警视频: 保留30天"
|
||||
echo " - 告警图片: 保留90天"
|
||||
}
|
||||
|
||||
# 安装 Media Server
|
||||
cmd_install_media_server() {
|
||||
echo -e "${BLUE}[1/5] 安装 Media Server...${NC}"
|
||||
|
||||
# 检查编译产物
|
||||
if [ ! -f "$BUILD_DIR/media-server" ]; then
|
||||
echo -e "${RED}错误: 未找到编译好的 media-server${NC}"
|
||||
echo "请先编译: cd $PROJECT_DIR && cmake --build build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建目录结构
|
||||
mkdir -p "$INSTALL_DIR/bin/plugins"
|
||||
mkdir -p "$INSTALL_DIR/lib"
|
||||
mkdir -p "$INSTALL_DIR/etc"
|
||||
mkdir -p "$INSTALL_DIR/web"
|
||||
mkdir -p "$INSTALL_DIR/models"
|
||||
|
||||
# 复制二进制文件
|
||||
cp "$BUILD_DIR/media-server" "$INSTALL_DIR/bin/"
|
||||
chmod +x "$INSTALL_DIR/bin/media-server"
|
||||
|
||||
# 复制插件
|
||||
if [ -d "$BUILD_DIR/plugins" ]; then
|
||||
cp "$BUILD_DIR"/plugins/*.so "$INSTALL_DIR/bin/plugins/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 复制依赖库
|
||||
if ls "$BUILD_DIR"/*.so 1> /dev/null 2>&1; then
|
||||
cp "$BUILD_DIR"/*.so "$INSTALL_DIR/lib/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 复制 web 静态文件
|
||||
if [ -d "$PROJECT_DIR/web" ]; then
|
||||
cp -r "$PROJECT_DIR/web"/* "$INSTALL_DIR/web/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 复制模型文件
|
||||
if [ -d "$PROJECT_DIR/models" ]; then
|
||||
cp -r "$PROJECT_DIR/models"/* "$INSTALL_DIR/models/" 2>/dev/null || true
|
||||
fi
|
||||
if [ -d "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588" ]; then
|
||||
cp "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588"/*.rknn "$INSTALL_DIR/models/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 选择并复制配置文件
|
||||
select_config
|
||||
|
||||
# 修复配置文件路径
|
||||
fix_config_paths
|
||||
|
||||
echo -e "${GREEN}✓${NC} Media Server 安装完成"
|
||||
}
|
||||
|
||||
# 选择配置文件
|
||||
select_config() {
|
||||
echo -e "${CYAN}[选择配置文件]${NC}"
|
||||
|
||||
# 查找所有可用的配置文件
|
||||
CONFIGS=()
|
||||
for f in "$PROJECT_DIR/configs"/*.json; do
|
||||
if [ -f "$f" ]; then
|
||||
CONFIGS+=("$(basename "$f")")
|
||||
fi
|
||||
done
|
||||
|
||||
echo "可用的配置文件:"
|
||||
for i in "${!CONFIGS[@]}"; do
|
||||
printf " %2d) %s\n" $((i+1)) "${CONFIGS[$i]}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
printf "请选择 [1-${#CONFIGS[@]},默认1]: "
|
||||
read choice
|
||||
choice=${choice:-1}
|
||||
|
||||
if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -lt 1 ] || [ "$choice" -gt "${#CONFIGS[@]}" ]; then
|
||||
choice=1
|
||||
fi
|
||||
|
||||
SELECTED_CONFIG="$PROJECT_DIR/configs/${CONFIGS[$((choice-1))]}"
|
||||
cp "$SELECTED_CONFIG" "$INSTALL_DIR/etc/media-server.json"
|
||||
|
||||
echo -e "${GREEN}✓${NC} 使用配置: ${CONFIGS[$((choice-1))]}"
|
||||
}
|
||||
|
||||
# 修复配置文件中的路径
|
||||
fix_config_paths() {
|
||||
echo -e "${CYAN}[修复配置路径]${NC}"
|
||||
|
||||
python3 << 'EOF'
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
config_file = "/opt/rk3588-media-server/etc/media-server.json"
|
||||
install_dir = "/opt/rk3588-media-server"
|
||||
runtime_dir = "/var/lib/rk3588-media-server"
|
||||
project_dir = os.path.expanduser("~/apps/OrangePi3588Media")
|
||||
|
||||
def fix_path(path):
|
||||
"""修复配置文件中的路径"""
|
||||
if not path or not isinstance(path, str):
|
||||
return path
|
||||
|
||||
# 模型路径 -> 安装目录的 models
|
||||
if 'third_party/rknpu2' in path or '.rknn' in path:
|
||||
return os.path.join(install_dir, 'models', os.path.basename(path))
|
||||
|
||||
# HLS 输出路径 -> 运行时目录的 hls
|
||||
if 'web/hls' in path or path.startswith('./web/hls'):
|
||||
return os.path.join(runtime_dir, 'hls', os.path.basename(os.path.dirname(path)), 'index.m3u8')
|
||||
|
||||
# web 根目录 -> 安装目录的 web
|
||||
if path.startswith('./web/'):
|
||||
return os.path.join(install_dir, path[2:])
|
||||
|
||||
# models 目录 -> 安装目录的 models
|
||||
if path.startswith('./models/'):
|
||||
return os.path.join(install_dir, path[2:])
|
||||
|
||||
# 其他相对路径 -> 尝试解析
|
||||
if path.startswith('./'):
|
||||
abs_path = os.path.join(project_dir, path)
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
return os.path.join(install_dir, path[2:])
|
||||
|
||||
return path
|
||||
|
||||
def process_node(node):
|
||||
"""处理节点配置"""
|
||||
# 修复模型路径
|
||||
if 'model_path' in node:
|
||||
node['model_path'] = fix_path(node['model_path'])
|
||||
|
||||
# 修复图库路径
|
||||
if 'gallery' in node and isinstance(node['gallery'], dict) and 'path' in node['gallery']:
|
||||
node['gallery']['path'] = fix_path(node['gallery']['path'])
|
||||
|
||||
# 修复输出路径(HLS、报警图片等)
|
||||
if 'outputs' in node and isinstance(node['outputs'], list):
|
||||
for output in node['outputs']:
|
||||
if 'path' in output:
|
||||
output['path'] = fix_path(output['path'])
|
||||
|
||||
# 修复 MinIO 端点(如果是本地)
|
||||
if 'minio_endpoint' in node:
|
||||
endpoint = node['minio_endpoint']
|
||||
if '127.0.0.1' in endpoint or 'localhost' in endpoint:
|
||||
# 保持本地端点不变
|
||||
pass
|
||||
|
||||
return node
|
||||
|
||||
try:
|
||||
with open(config_file, 'r') as f:
|
||||
config = json.load(f)
|
||||
|
||||
# 处理 graphs 格式
|
||||
if 'graphs' in config:
|
||||
for graph in config['graphs']:
|
||||
if 'nodes' in graph:
|
||||
for node in graph['nodes']:
|
||||
process_node(node)
|
||||
|
||||
# 处理 templates + instances 格式
|
||||
if 'templates' in config and 'instances' in config:
|
||||
for template_name, template in config['templates'].items():
|
||||
if 'nodes' in template:
|
||||
for node in template['nodes']:
|
||||
process_node(node)
|
||||
|
||||
# 添加全局配置(如果不存在)
|
||||
if 'global' not in config:
|
||||
config['global'] = {}
|
||||
|
||||
# 确保 web_root 指向正确位置
|
||||
config['global']['web_root'] = os.path.join(install_dir, 'web')
|
||||
config['global']['metrics_port'] = config['global'].get('metrics_port', 9000)
|
||||
|
||||
with open(config_file, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
print(f"配置路径修复完成")
|
||||
|
||||
except Exception as e:
|
||||
print(f"配置处理出错: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
EOF
|
||||
}
|
||||
|
||||
# 安装 Agent
|
||||
cmd_install_agent() {
|
||||
echo -e "${BLUE}[2/5] 安装 Agent...${NC}"
|
||||
|
||||
# 查找 Agent 编译产物
|
||||
AGENT_SOURCE=""
|
||||
if [ -f "$PROJECT_DIR/agent/rk3588-agent_linux_arm64" ]; then
|
||||
AGENT_SOURCE="$PROJECT_DIR/agent/rk3588-agent_linux_arm64"
|
||||
elif [ -f "$PROJECT_DIR/agent/cmd/rk3588-agent/rk3588-agent" ]; then
|
||||
AGENT_SOURCE="$PROJECT_DIR/agent/cmd/rk3588-agent/rk3588-agent"
|
||||
fi
|
||||
|
||||
if [ -z "$AGENT_SOURCE" ]; then
|
||||
echo -e "${YELLOW}警告: 未找到编译好的 Agent,跳过安装${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir -p "$AGENT_INSTALL_DIR"
|
||||
mkdir -p "/var/lib/rk3588-agent"
|
||||
|
||||
cp "$AGENT_SOURCE" "$AGENT_INSTALL_DIR/rk3588-agent"
|
||||
chmod +x "$AGENT_INSTALL_DIR/rk3588-agent"
|
||||
|
||||
# Agent 配置
|
||||
cat > "$AGENT_INSTALL_DIR/agent.config.json" << EOF
|
||||
{
|
||||
"agent": {
|
||||
"listen": "0.0.0.0:9100",
|
||||
"token": "$(openssl rand -hex 16)",
|
||||
"require_token_for_read": false,
|
||||
"discovery_enable": true,
|
||||
"discovery_port": 35688,
|
||||
"device_name": "rk3588_$(hostname)",
|
||||
"device_id_path": "/var/lib/rk3588-agent/device_id",
|
||||
"models_dir": "$INSTALL_DIR/models",
|
||||
"max_upload_mb": 200,
|
||||
"config_path": "$INSTALL_DIR/etc/media-server.json",
|
||||
"media_server_process": {
|
||||
"enable": false
|
||||
},
|
||||
"media_server_base_url": "http://127.0.0.1:9000",
|
||||
"media_server_timeout_ms": 3000,
|
||||
"media_server_retry": { "max_attempts": 3, "backoff_ms": [200, 500] }
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
chown -R orangepi:orangepi "/var/lib/rk3588-agent"
|
||||
|
||||
echo -e "${GREEN}✓${NC} Agent 安装完成"
|
||||
}
|
||||
|
||||
# 安装 systemd 服务
|
||||
cmd_install_services() {
|
||||
echo -e "${BLUE}[3/5] 安装 Systemd 服务...${NC}"
|
||||
|
||||
# Media Server 服务
|
||||
cat > "$SERVICE_DIR/media-server.service" << EOF
|
||||
[Unit]
|
||||
Description=RK3588 Media Server
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
WorkingDirectory=$INSTALL_DIR
|
||||
Environment="LD_LIBRARY_PATH=$INSTALL_DIR/lib:/usr/local/lib"
|
||||
Environment="RKNPU_LOG_LEVEL=2"
|
||||
ExecStartPre=/bin/mkdir -p $HLS_DIR $LOGS_DIR $ALARMS_DIR $CLIPS_DIR
|
||||
ExecStart=$INSTALL_DIR/bin/media-server --config $INSTALL_DIR/etc/media-server.json
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StartLimitInterval=60s
|
||||
StartLimitBurst=3
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=media-server
|
||||
|
||||
# 资源限制
|
||||
LimitNOFILE=65536
|
||||
LimitNPROC=4096
|
||||
|
||||
# 优雅关闭
|
||||
TimeoutStopSec=30
|
||||
KillSignal=SIGTERM
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Agent 服务
|
||||
cat > "$SERVICE_DIR/rk3588-agent.service" << EOF
|
||||
[Unit]
|
||||
Description=RK3588 Agent Service
|
||||
After=network.target media-server.service
|
||||
Wants=media-server.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
Group=root
|
||||
WorkingDirectory=$AGENT_INSTALL_DIR
|
||||
ExecStart=$AGENT_INSTALL_DIR/rk3588-agent --config $AGENT_INSTALL_DIR/agent.config.json
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=rk3588-agent
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
echo -e "${GREEN}✓${NC} Systemd 服务安装完成"
|
||||
}
|
||||
|
||||
# 主安装流程
|
||||
cmd_install() {
|
||||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║ RK3588 Media Server 完善部署脚本 ║${NC}"
|
||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
|
||||
# 检查 root 权限
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "项目目录: $PROJECT_DIR"
|
||||
echo "安装目录: $INSTALL_DIR"
|
||||
echo "运行时目录: $RUNTIME_DIR"
|
||||
echo ""
|
||||
|
||||
# 执行安装步骤
|
||||
cmd_install_media_server
|
||||
cmd_install_agent
|
||||
create_runtime_dirs
|
||||
cmd_install_services
|
||||
install_logrotate
|
||||
install_hls_cleanup
|
||||
|
||||
# 启动服务
|
||||
echo -e "${BLUE}[启动服务]${NC}"
|
||||
systemctl enable media-server
|
||||
systemctl start media-server
|
||||
systemctl enable rk3588-agent
|
||||
systemctl start rk3588-agent
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ 部署完成! ║${NC}"
|
||||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo "目录结构:"
|
||||
echo " 程序: $INSTALL_DIR/"
|
||||
echo " 数据: $RUNTIME_DIR/"
|
||||
echo " 配置: $INSTALL_DIR/etc/media-server.json"
|
||||
echo ""
|
||||
echo "服务管理:"
|
||||
echo " 状态: sudo systemctl status media-server"
|
||||
echo " 日志: sudo journalctl -u media-server -f"
|
||||
echo " 界面: http://$(hostname -I | awk '{print $1}'):9100"
|
||||
echo ""
|
||||
echo "HLS播放:"
|
||||
echo " http://$(hostname -I | awk '{print $1}'):9000/hls_player.html"
|
||||
}
|
||||
|
||||
# 升级
|
||||
cmd_upgrade() {
|
||||
echo -e "${YELLOW}========== 升级 Media Server ==========${NC}"
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e "${RED}错误: 请使用 sudo 运行${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 备份配置
|
||||
BACKUP_DIR="/root/rk3588-backup-$(date +%Y%m%d%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
[ -f "$INSTALL_DIR/etc/media-server.json" ] && cp "$INSTALL_DIR/etc/media-server.json" "$BACKUP_DIR/"
|
||||
echo "配置已备份到: $BACKUP_DIR"
|
||||
|
||||
# 停止服务
|
||||
echo "停止服务..."
|
||||
systemctl stop media-server rk3588-agent
|
||||
|
||||
# 重新安装
|
||||
cmd_install
|
||||
|
||||
echo -e "${GREEN}升级完成${NC}"
|
||||
}
|
||||
|
||||
# 查看状态
|
||||
cmd_status() {
|
||||
echo -e "${BLUE}========== RK3588 Media Server 状态 ==========${NC}"
|
||||
echo ""
|
||||
|
||||
# 系统信息
|
||||
echo -e "${CYAN}[系统信息]${NC}"
|
||||
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo " 运行时间: $(uptime -p 2>/dev/null || uptime | awk -F',' '{print $1}')"
|
||||
echo ""
|
||||
|
||||
# NPU
|
||||
echo -e "${CYAN}[NPU 负载]${NC}"
|
||||
if [ -f /proc/rknpu/load ]; then
|
||||
cat /proc/rknpu/load | sed 's/^/ /'
|
||||
else
|
||||
echo " NPU 信息不可用"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Media Server
|
||||
echo -e "${CYAN}[Media Server]${NC}"
|
||||
if systemctl is-active --quiet media-server 2>/dev/null; then
|
||||
echo -e " 状态: ${GREEN}● 运行中${NC}"
|
||||
PID=$(systemctl show --property=MainPID --value media-server 2>/dev/null)
|
||||
echo " PID: $PID"
|
||||
if [ -n "$PID" ] && [ "$PID" != "0" ]; then
|
||||
CPU_MEM=$(ps -p $PID -o %cpu,%mem --no-headers 2>/dev/null || echo "N/A")
|
||||
echo " CPU/MEM: $CPU_MEM"
|
||||
fi
|
||||
echo " 端口:"
|
||||
ss -tlnp 2>/dev/null | grep -E "(9000|8555)" | head -3 | sed 's/^/ /'
|
||||
else
|
||||
echo -e " 状态: ${RED}○ 停止${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# HLS 输出
|
||||
echo -e "${CYAN}[HLS 输出]${NC}"
|
||||
if [ -d "$HLS_DIR" ]; then
|
||||
CHANNELS=$(find "$HLS_DIR" -maxdepth 1 -type d | wc -l)
|
||||
CHANNELS=$((CHANNELS - 1))
|
||||
echo " 通道数: $CHANNELS"
|
||||
if [ $CHANNELS -gt 0 ]; then
|
||||
echo " 分片统计:"
|
||||
for d in "$HLS_DIR"/*/; do
|
||||
[ -d "$d" ] || continue
|
||||
name=$(basename "$d")
|
||||
count=$(find "$d" -name "*.ts" | wc -l)
|
||||
size=$(du -sh "$d" 2>/dev/null | cut -f1)
|
||||
echo " $name: ${count}个分片, ${size}"
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo " HLS 目录不存在"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Agent
|
||||
echo -e "${CYAN}[RK3588 Agent]${NC}"
|
||||
if systemctl is-active --quiet rk3588-agent 2>/dev/null; then
|
||||
echo -e " 状态: ${GREEN}● 运行中${NC}"
|
||||
echo " 管理界面: http://$(hostname -I | awk '{print $1}'):9100"
|
||||
else
|
||||
echo -e " 状态: ${RED}○ 停止${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 存储使用
|
||||
echo -e "${CYAN}[存储使用]${NC}"
|
||||
echo " HLS 输出: $(du -sh "$HLS_DIR" 2>/dev/null | cut -f1)"
|
||||
echo " 日志: $(du -sh "$LOGS_DIR" 2>/dev/null | cut -f1)"
|
||||
echo " 告警图片: $(du -sh "$ALARMS_DIR" 2>/dev/null | cut -f1)"
|
||||
echo " 告警视频: $(du -sh "$CLIPS_DIR" 2>/dev/null | cut -f1)"
|
||||
echo ""
|
||||
|
||||
echo "常用命令:"
|
||||
echo " 查看日志: sudo journalctl -u media-server -f"
|
||||
echo " HLS清理: sudo $INSTALL_DIR/bin/cleanup-hls.sh"
|
||||
echo " 实时监控: watch -n 1 cat /proc/rknpu/load"
|
||||
}
|
||||
|
||||
# 查看日志
|
||||
cmd_logs() {
|
||||
SERVICE="${2:-media-server}"
|
||||
echo -e "${BLUE}查看 $SERVICE 日志 (按 Ctrl+C 退出)...${NC}"
|
||||
journalctl -u "$SERVICE" -f
|
||||
}
|
||||
|
||||
# 清理 HLS
|
||||
cmd_clean_hls() {
|
||||
echo -e "${YELLOW}清理 HLS 旧分片...${NC}"
|
||||
KEEP_DAYS="${2:-3}"
|
||||
|
||||
if [ -f "$INSTALL_DIR/bin/cleanup-hls.sh" ]; then
|
||||
"$INSTALL_DIR/bin/cleanup-hls.sh" "$KEEP_DAYS"
|
||||
else
|
||||
echo "清理脚本不存在"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 卸载
|
||||
cmd_uninstall() {
|
||||
echo -e "${YELLOW}========== 卸载 RK3588 Media Server ==========${NC}"
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo -e "${RED}错误: 请使用 sudo 运行${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -p "确定要卸载? (y/N): " -r
|
||||
[ "$REPLY" != "y" ] && [ "$REPLY" != "Y" ] && echo "已取消" && exit 0
|
||||
|
||||
echo "[1/4] 停止服务..."
|
||||
systemctl stop media-server rk3588-agent 2>/dev/null || true
|
||||
systemctl disable media-server rk3588-agent 2>/dev/null || true
|
||||
|
||||
echo "[2/4] 删除服务文件..."
|
||||
rm -f "$SERVICE_DIR/media-server.service"
|
||||
rm -f "$SERVICE_DIR/rk3588-agent.service"
|
||||
rm -f "$LOGROTATE_DIR/rk3588-media-server"
|
||||
rm -f "$LOGROTATE_DIR/rk3588-hls"
|
||||
rm -f "/etc/cron.d/rk3588-media-server"
|
||||
systemctl daemon-reload
|
||||
|
||||
echo "[3/4] 备份数据..."
|
||||
BACKUP_DIR="/root/rk3588-backup-$(date +%Y%m%d%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
[ -f "$INSTALL_DIR/etc/media-server.json" ] && cp "$INSTALL_DIR/etc/media-server.json" "$BACKUP_DIR/"
|
||||
[ -d "$HLS_DIR" ] && cp -r "$HLS_DIR" "$BACKUP_DIR/" 2>/dev/null || true
|
||||
echo "数据已备份到: $BACKUP_DIR"
|
||||
|
||||
echo "[4/4] 删除文件..."
|
||||
read -p "是否删除所有数据 (包括 HLS/日志/告警)? (y/N): " -r
|
||||
if [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]; then
|
||||
rm -rf "$INSTALL_DIR" "$AGENT_INSTALL_DIR" "$RUNTIME_DIR"
|
||||
echo "所有数据已删除"
|
||||
else
|
||||
rm -rf "$INSTALL_DIR" "$AGENT_INSTALL_DIR"
|
||||
echo "程序已删除,数据保留在: $RUNTIME_DIR"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}卸载完成${NC}"
|
||||
}
|
||||
|
||||
# 主入口
|
||||
case "${1:-install}" in
|
||||
install)
|
||||
cmd_install
|
||||
;;
|
||||
upgrade)
|
||||
cmd_upgrade
|
||||
;;
|
||||
status)
|
||||
cmd_status
|
||||
;;
|
||||
logs)
|
||||
cmd_logs "$@"
|
||||
;;
|
||||
clean-hls)
|
||||
cmd_clean_hls "$@"
|
||||
;;
|
||||
uninstall)
|
||||
cmd_uninstall
|
||||
;;
|
||||
*)
|
||||
echo "RK3588 Media Server 部署脚本"
|
||||
echo ""
|
||||
echo "用法: sudo ./deploy.sh [命令]"
|
||||
echo ""
|
||||
echo "命令:"
|
||||
echo " install 安装/部署服务 (默认)"
|
||||
echo " upgrade 升级服务 (保留配置和数据)"
|
||||
echo " status 查看运行状态"
|
||||
echo " logs 查看日志"
|
||||
echo " clean-hls 清理 HLS 旧分片"
|
||||
echo " uninstall 卸载服务"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " sudo ./deploy.sh install"
|
||||
echo " sudo ./deploy.sh status"
|
||||
echo " sudo ./deploy.sh clean-hls 7 # 保留最近7天"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Loading…
Reference in New Issue
Block a user