# 配置文件编写指南 本文档详细说明如何编写和定制 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