706 lines
17 KiB
Markdown
706 lines
17 KiB
Markdown
# 配置文件编写指南
|
||
|
||
本文档详细说明如何编写和定制 RK3588 Media Server 的配置文件。
|
||
|
||
---
|
||
|
||
## 1. 配置文件结构
|
||
|
||
配置文件采用 **JSON 格式**,分为四个主要部分:
|
||
|
||
```json
|
||
{
|
||
"global": { ... }, // 全局设置
|
||
"queue": { ... }, // 队列策略
|
||
"templates": { ... }, // 节点模板定义
|
||
"instances": [ ... ] // 实例化配置
|
||
}
|
||
```
|
||
|
||
### 1.1 全局设置 (global)
|
||
|
||
```json
|
||
{
|
||
"global": {
|
||
"metrics_port": 9000, // HTTP 服务端口(监控/HLS)
|
||
"web_root": "web" // Web 静态文件根目录
|
||
}
|
||
}
|
||
```
|
||
|
||
### 1.2 队列策略 (queue)
|
||
|
||
```json
|
||
{
|
||
"queue": {
|
||
"size": 4, // 队列长度
|
||
"strategy": "drop_oldest" // 队列满时的策略
|
||
}
|
||
}
|
||
```
|
||
|
||
**strategy 选项:**
|
||
- `drop_oldest` - 丢弃最旧的帧(推荐,实时性好)
|
||
- `drop_newest` - 丢弃最新的帧
|
||
- `block` - 阻塞等待(可能导致延迟累积)
|
||
|
||
---
|
||
|
||
## 2. 模板定义 (templates)
|
||
|
||
模板定义了一组节点和连接关系,可以被多个实例复用。
|
||
|
||
### 2.1 模板基本结构
|
||
|
||
```json
|
||
{
|
||
"templates": {
|
||
"template_name": {
|
||
"nodes": [ ... ], // 节点列表
|
||
"edges": [ ... ] // 连接关系
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 节点 (nodes)
|
||
|
||
每个节点必须包含以下字段:
|
||
|
||
```json
|
||
{
|
||
"id": "node_id", // 节点唯一标识
|
||
"type": "node_type", // 节点类型
|
||
"role": "source/filter/sink", // 角色
|
||
"enable": true // 是否启用
|
||
}
|
||
```
|
||
|
||
**节点类型说明:**
|
||
|
||
| 类型 | 角色 | 功能 |
|
||
|------|------|------|
|
||
| `input_rtsp` | source | 拉取 RTSP 视频流 |
|
||
| `input_file` | source | 读取本地视频文件 |
|
||
| `preprocess` | filter | 图像预处理(缩放/格式转换)|
|
||
| `ai_yolo` | filter | YOLO 目标检测 |
|
||
| `ai_face_det` | filter | 人脸检测 |
|
||
| `ai_face_recog` | filter | 人脸识别 |
|
||
| `tracker` | filter | 目标跟踪 |
|
||
| `osd` | filter | 绘制检测框/文字 |
|
||
| `alarm` | sink | 报警规则处理 |
|
||
| `publish` | sink | 视频编码输出 |
|
||
| `storage` | sink | 录像存储 |
|
||
|
||
---
|
||
|
||
## 3. 节点详细配置
|
||
|
||
### 3.1 输入节点
|
||
|
||
#### input_rtsp(RTSP 拉流)
|
||
|
||
```json
|
||
{
|
||
"id": "in",
|
||
"type": "input_rtsp",
|
||
"role": "source",
|
||
"enable": true,
|
||
"url": "rtsp://10.0.0.49:8554/cam", // RTSP 地址
|
||
"fps": 30, // 预期帧率
|
||
"width": 1920, // 预期宽度
|
||
"height": 1080, // 预期高度
|
||
"use_mpp": true, // 使用 MPP 硬件解码
|
||
"use_ffmpeg": false, // 是否使用 FFmpeg
|
||
"force_tcp": true, // 强制 TCP 传输
|
||
"reconnect_sec": 5, // 重连间隔
|
||
"reconnect_backoff_max_sec": 30 // 最大重连间隔
|
||
}
|
||
```
|
||
|
||
#### input_file(文件输入)
|
||
|
||
```json
|
||
{
|
||
"id": "in",
|
||
"type": "input_file",
|
||
"role": "source",
|
||
"enable": true,
|
||
"path": "/path/to/video.mp4",
|
||
"loop": true, // 循环播放
|
||
"fps": 30
|
||
}
|
||
```
|
||
|
||
### 3.2 预处理节点
|
||
|
||
#### preprocess(图像预处理)
|
||
|
||
```json
|
||
{
|
||
"id": "pre",
|
||
"type": "preprocess",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"dst_w": 768, // 输出宽度
|
||
"dst_h": 768, // 输出高度
|
||
"dst_format": "rgb", // 输出格式
|
||
"dst_packed": true, // 是否 packed 格式
|
||
"resize_mode": "stretch", // 缩放模式(推荐)
|
||
"rga_gate": "cam1", // RGA 资源锁(同名互斥)
|
||
"use_rga": true // 使用 RGA 硬件
|
||
}
|
||
```
|
||
|
||
**resize_mode 选项:**
|
||
- `stretch` - 拉伸填充(**推荐**,生产环境默认使用)
|
||
- `keep_ratio` - 保持比例(可能留黑边)
|
||
- `letterbox` - 保持比例,边缘填充黑色(保留功能,当前有稳定性问题)
|
||
|
||
> **注意**:`stretch` 模式在输入输出比例相同时(如 16:9→16:9)不会有明显变形。当输入 16:9 拉伸到模型 1:1 再拉伸回 16:9 输出时,两次变形相互抵消,最终画面正常。该模式性能更好、画面更稳定,推荐生产环境使用。
|
||
|
||
**dst_format 选项:**
|
||
- `rgb` - RGB24
|
||
- `bgr` - BGR24
|
||
- `nv12` - NV12 (YUV420SP)
|
||
- `yuv420` - YUV420P
|
||
|
||
### 3.3 AI 节点
|
||
|
||
#### ai_yolo(YOLO 目标检测)
|
||
|
||
```json
|
||
{
|
||
"id": "ai",
|
||
"type": "ai_yolo",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"infer_fps": 10, // 推理帧率
|
||
"model_path": "./models/best-768.rknn",
|
||
"model_version": "v8", // v5 或 v8
|
||
"model_w": 768, // 模型输入宽度
|
||
"model_h": 768, // 模型输入高度
|
||
"num_classes": 11, // 类别数
|
||
"conf": 0.35, // 置信度阈值
|
||
"nms": 0.45, // NMS IoU 阈值
|
||
"class_filter": [3, 6] // 只检测指定类别
|
||
}
|
||
```
|
||
|
||
#### ai_face_det(人脸检测)
|
||
|
||
```json
|
||
{
|
||
"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" // 输入格式
|
||
}
|
||
```
|
||
|
||
#### ai_face_recog(人脸识别)
|
||
|
||
```json
|
||
{
|
||
"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": "./models/face_gallery.db", // 人脸库路径
|
||
"load_on_start": true,
|
||
"expected_dim": 512,
|
||
"dtype": "auto"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.4 跟踪节点
|
||
|
||
#### tracker(目标跟踪)
|
||
|
||
```json
|
||
{
|
||
"id": "trk",
|
||
"type": "tracker",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"mode": "bytetrack_lite", // 跟踪算法
|
||
"per_class": true, // 按类别分别跟踪
|
||
"state_key": "cam1", // 状态键(多路隔离)
|
||
"track_classes": [3, 6], // 跟踪的类别
|
||
"high_th": 0.5, // 高分阈值
|
||
"low_th": 0.1, // 低分阈值
|
||
"iou_th": 0.3, // IOU 阈值
|
||
"max_age_ms": 1500, // 最大丢失时间
|
||
"min_hits": 2, // 最小确认帧数
|
||
"max_tracks": 128 // 最大跟踪数
|
||
}
|
||
```
|
||
|
||
### 3.5 显示节点
|
||
|
||
#### osd(屏幕显示)
|
||
|
||
```json
|
||
{
|
||
"id": "osd",
|
||
"type": "osd",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"draw_bbox": true, // 绘制检测框
|
||
"draw_text": true, // 绘制文字
|
||
"draw_face_det": true, // 绘制人脸框
|
||
"draw_face_bbox": true, // 绘制人脸边框
|
||
"line_width": 2, // 线宽
|
||
"font_scale": 1, // 字体缩放
|
||
"use_rga_bbox": false, // 使用 RGA 绘制框
|
||
"labels": ["helmet", "gloves", "vest", "boots", ...] // 类别标签
|
||
}
|
||
```
|
||
|
||
### 3.6 报警节点
|
||
|
||
#### alarm(报警处理)
|
||
|
||
```json
|
||
{
|
||
"id": "alarm",
|
||
"type": "alarm",
|
||
"role": "sink",
|
||
"enable": true,
|
||
"eval_fps": 10, // 评估帧率
|
||
"labels": ["helmet", "gloves", ...], // 类别标签
|
||
"rules": [
|
||
{
|
||
"name": "ppe_violation", // 规则名称
|
||
"class_ids": [3, 6], // 触发类别
|
||
"roi": {"x": 0.0, "y": 0.0, "w": 1.0, "h": 1.0}, // ROI
|
||
"min_score": 0.4, // 最小置信度
|
||
"min_box_area_ratio": 0.02, // 最小框面积比
|
||
"require_track_id": true, // 需要跟踪ID
|
||
"min_duration_ms": 1500, // 最小持续时间
|
||
"min_hits": 3, // 最小命中次数
|
||
"hit_window_ms": 1500, // 命中窗口
|
||
"cooldown_ms": 5000 // 冷却时间
|
||
}
|
||
],
|
||
"actions": {
|
||
"log": {"enable": true, "level": "info"},
|
||
"snapshot": {
|
||
"enable": true,
|
||
"min_interval_ms": 15000,
|
||
"format": "jpg",
|
||
"quality": 85,
|
||
"upload": {
|
||
"type": "minio",
|
||
"endpoint": "http://10.0.0.49:9000",
|
||
"bucket": "myminio",
|
||
"access_key": "minioadmin",
|
||
"secret_key": "minioadmin"
|
||
}
|
||
},
|
||
"clip": {
|
||
"enable": true,
|
||
"min_interval_ms": 15000,
|
||
"pre_sec": 5,
|
||
"post_sec": 10,
|
||
"format": "mp4",
|
||
"upload": { ... }
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.7 输出节点
|
||
|
||
#### publish(视频输出)
|
||
|
||
```json
|
||
{
|
||
"id": "pub",
|
||
"type": "publish",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"queue": {"size": 2, "policy": "drop_oldest"},
|
||
"codec": "h264", // 编码格式
|
||
"fps": 30, // 输出帧率
|
||
"gop": 60, // GOP 大小
|
||
"bitrate_kbps": 4000, // 码率
|
||
"use_mpp": true, // 使用 MPP 编码
|
||
"use_ffmpeg_mux": true, // 使用 FFmpeg 封装
|
||
"outputs": [
|
||
{
|
||
"proto": "rtsp_server", // RTSP 输出
|
||
"port": 8555,
|
||
"path": "/live/cam1"
|
||
},
|
||
{
|
||
"proto": "hls", // HLS 输出
|
||
"path": "./web/hls/cam1/index.m3u8",
|
||
"segment_sec": 2 // 切片时长
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### logic_gate(逻辑门 - PPE合规检测)
|
||
|
||
用于空间关联检测和颜色分析,典型场景:检测人是否穿劳保鞋及颜色是否合规。
|
||
|
||
```json
|
||
{
|
||
"id": "logic_ppe",
|
||
"type": "logic_gate",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"mode": "ppe_boots_check", // 工作模式
|
||
"anchor_class": 6, // 基准类别:人(Person)
|
||
"boots_class": 3, // 目标类别:鞋(boots)
|
||
"color_check": {
|
||
"enable": true, // 启用颜色检测
|
||
"method": "hsv", // 颜色空间:hsv/rgb/brightness
|
||
"dark_threshold": 80, // 深色阈值(0-255)
|
||
"roi_expand": 1.0 // 检测框扩大系数
|
||
},
|
||
"debug": false // 调试输出
|
||
}
|
||
```
|
||
|
||
**颜色阈值调整建议:**
|
||
|
||
| 阈值 | 效果 | 适用场景 |
|
||
|------|------|----------|
|
||
| **60** | 很严格,只有纯黑才算深色 | 环境光很暗 |
|
||
| **80** (默认) | 适中,黑色/深灰通过 | 正常室内光 |
|
||
| **100** | 较宽松,灰色也算深色 | 环境光很亮 |
|
||
| **120** | 很宽松,浅灰也算深色 | 强光/反光环境 |
|
||
|
||
**判断逻辑:**
|
||
```
|
||
is_dark = (平均亮度 < dark_threshold) && (深色像素比例 > 60%)
|
||
```
|
||
|
||
**使用示例流程:**
|
||
```
|
||
input → preprocess → ai_yolo(Person+boots) → tracker → logic_gate → osd → publish
|
||
↓
|
||
判断:人+鞋同时存在?
|
||
↓
|
||
是 → 检查鞋颜色
|
||
↓
|
||
深色 → 合规
|
||
浅色 → 告警
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 连接关系 (edges)
|
||
|
||
edges 定义了数据流向:
|
||
|
||
```json
|
||
{
|
||
"edges": [
|
||
["in", "pre"], // in -> pre
|
||
["pre", "ai"], // pre -> ai
|
||
["ai", "trk"], // ai -> trk
|
||
["trk", "osd"], // trk -> osd
|
||
["osd", "post"], // osd -> post
|
||
["post", "pub"], // post -> pub
|
||
["pub", "alarm"] // pub -> alarm
|
||
]
|
||
}
|
||
```
|
||
|
||
**注意:** 数据流是单向的,从 source 到 sink。
|
||
|
||
---
|
||
|
||
## 5. 实例化 (instances)
|
||
|
||
实例化将模板应用到具体配置:
|
||
|
||
```json
|
||
{
|
||
"instances": [
|
||
{
|
||
"name": "cam1", // 实例名称
|
||
"template": "ppe_detection_pipeline", // 使用的模板
|
||
"params": { // 参数替换
|
||
"name": "cam1",
|
||
"url": "rtsp://10.0.0.49:8554/cam1",
|
||
"face_gallery_path": "./models/face_gallery.db",
|
||
"minio_endpoint": "http://10.0.0.49:9000",
|
||
"minio_bucket": "myminio",
|
||
"minio_ak": "minioadmin",
|
||
"minio_sk": "minioadmin"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 5.1 变量替换
|
||
|
||
模板中使用 `${variable}` 定义变量,在实例的 `params` 中提供值:
|
||
|
||
**模板中:**
|
||
```json
|
||
"url": "${url}",
|
||
"face_gallery_path": "${face_gallery_path}"
|
||
```
|
||
|
||
**实例中:**
|
||
```json
|
||
"params": {
|
||
"url": "rtsp://10.0.0.49:8554/cam1",
|
||
"face_gallery_path": "./models/face_gallery.db"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 完整配置示例
|
||
|
||
### 6.1 单路 PPE 检测(完整)
|
||
|
||
```json
|
||
{
|
||
"global": {
|
||
"metrics_port": 9000,
|
||
"web_root": "web"
|
||
},
|
||
"queue": {
|
||
"size": 4,
|
||
"strategy": "drop_oldest"
|
||
},
|
||
"templates": {
|
||
"ppe_pipeline": {
|
||
"nodes": [
|
||
{
|
||
"id": "in",
|
||
"type": "input_rtsp",
|
||
"role": "source",
|
||
"enable": true,
|
||
"url": "${url}",
|
||
"fps": 30,
|
||
"use_mpp": true,
|
||
"force_tcp": true,
|
||
"reconnect_sec": 5
|
||
},
|
||
{
|
||
"id": "pre",
|
||
"type": "preprocess",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"dst_w": 768,
|
||
"dst_h": 768,
|
||
"dst_format": "rgb",
|
||
"resize_mode": "stretch",
|
||
"use_rga": true
|
||
},
|
||
{
|
||
"id": "ai",
|
||
"type": "ai_yolo",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"infer_fps": 10,
|
||
"model_path": "./models/best-768.rknn",
|
||
"model_version": "v8",
|
||
"model_w": 768,
|
||
"model_h": 768,
|
||
"num_classes": 11,
|
||
"conf": 0.35,
|
||
"nms": 0.45,
|
||
"class_filter": [3, 6]
|
||
},
|
||
{
|
||
"id": "trk",
|
||
"type": "tracker",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"mode": "bytetrack_lite",
|
||
"per_class": true,
|
||
"track_classes": [3, 6],
|
||
"max_age_ms": 1500
|
||
},
|
||
{
|
||
"id": "osd",
|
||
"type": "osd",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"draw_bbox": true,
|
||
"draw_text": true
|
||
},
|
||
{
|
||
"id": "post",
|
||
"type": "preprocess",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"dst_w": 1920,
|
||
"dst_h": 1080,
|
||
"dst_format": "nv12",
|
||
"resize_mode": "keep_ratio",
|
||
"use_rga": true
|
||
},
|
||
{
|
||
"id": "alarm",
|
||
"type": "alarm",
|
||
"role": "sink",
|
||
"enable": true,
|
||
"eval_fps": 10,
|
||
"rules": [
|
||
{
|
||
"name": "ppe_violation",
|
||
"class_ids": [3, 6],
|
||
"min_score": 0.4,
|
||
"min_duration_ms": 1500
|
||
}
|
||
],
|
||
"actions": {
|
||
"log": {"enable": true}
|
||
}
|
||
},
|
||
{
|
||
"id": "pub",
|
||
"type": "publish",
|
||
"role": "filter",
|
||
"enable": true,
|
||
"codec": "h264",
|
||
"fps": 30,
|
||
"bitrate_kbps": 4000,
|
||
"outputs": [
|
||
{"proto": "rtsp_server", "port": 8555, "path": "/live/${name}"},
|
||
{"proto": "hls", "path": "./web/hls/${name}/index.m3u8", "segment_sec": 2}
|
||
]
|
||
}
|
||
],
|
||
"edges": [
|
||
["in", "pre"],
|
||
["pre", "ai"],
|
||
["ai", "trk"],
|
||
["trk", "osd"],
|
||
["osd", "post"],
|
||
["post", "pub"],
|
||
["pub", "alarm"]
|
||
]
|
||
}
|
||
},
|
||
"instances": [
|
||
{
|
||
"name": "cam1",
|
||
"template": "ppe_pipeline",
|
||
"params": {
|
||
"name": "cam1",
|
||
"url": "rtsp://10.0.0.49:8554/cam1"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 6.2 多路复用模板
|
||
|
||
```json
|
||
{
|
||
"instances": [
|
||
{
|
||
"name": "cam1",
|
||
"template": "ppe_pipeline",
|
||
"params": {
|
||
"name": "cam1",
|
||
"url": "rtsp://10.0.0.49:8554/cam1"
|
||
}
|
||
},
|
||
{
|
||
"name": "cam2",
|
||
"template": "ppe_pipeline",
|
||
"params": {
|
||
"name": "cam2",
|
||
"url": "rtsp://10.0.0.49:8554/cam2"
|
||
}
|
||
},
|
||
{
|
||
"name": "cam3",
|
||
"template": "ppe_pipeline",
|
||
"params": {
|
||
"name": "cam3",
|
||
"url": "rtsp://10.0.0.49:8554/cam3"
|
||
}
|
||
},
|
||
{
|
||
"name": "cam4",
|
||
"template": "ppe_pipeline",
|
||
"params": {
|
||
"name": "cam4",
|
||
"url": "rtsp://10.0.0.49:8554/cam4"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 常见问题
|
||
|
||
### Q: 如何禁用某个节点?
|
||
|
||
```json
|
||
"enable": false
|
||
```
|
||
|
||
### Q: 如何修改日志级别?
|
||
|
||
节点级别的 debug 配置:
|
||
```json
|
||
"debug": {
|
||
"stats": false, // 关闭统计日志
|
||
"stats_interval": 100, // 统计间隔(帧数)
|
||
"detections": false // 关闭检测日志
|
||
}
|
||
```
|
||
|
||
### Q: 配置错误如何排查?
|
||
|
||
```bash
|
||
# 检查 JSON 格式
|
||
python3 -m json.tool config.json > /dev/null
|
||
|
||
# 启动时查看错误日志
|
||
./build/media-server --config config.json 2>&1 | grep -i error
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 参考配置
|
||
|
||
| 配置文件 | 说明 |
|
||
|----------|------|
|
||
| `configs/production_4ch.json` | 4路生产环境配置(1080p)|
|
||
| `configs/stress_5ch_face_recog.json` | 5路压力测试配置 |
|
||
| `configs/sample_cam_ppe11.json` | 单路 PPE 检测示例 |
|
||
|
||
---
|
||
|
||
**版本**:v1.0
|
||
**更新日期**:2026-02-28
|