增加一些部署脚本和必要的文档

This commit is contained in:
tian 2026-02-25 11:00:40 +08:00
parent 4940926866
commit 02c5dd2f6d
16 changed files with 1126 additions and 18 deletions

View File

@ -474,6 +474,7 @@ GraphMgr 负责:
```
> 说明:如果不需要后处理:
>
> - **推荐**:保留 `pp_cam1` 节点(`enable:true`),并确保其不启用任何处理链(例如:`default.enable=false` 且 `per_class` 为空),此时 `det_post` 会作为轻量透传。
> - 若确实要移除该节点:需要**同时删除并重连拓扑**(例如改回 `ai_cam1 -> osd_cam1``ai_cam1 -> alarm_cam1`),仅设置 `enable=false` 会导致下游节点无输入而构图失败。
@ -588,6 +589,7 @@ GraphMgr 负责:
`det_post` 是一个 **Filter** 节点,位于 `ai_yolo` 之后,负责对 `frame->det->items` 做**按类别可配置**的后处理。
**设计目标:**
- 不同类别可以挂不同的处理器链Processor/Strategy Registry避免“一个类别一个插件”。
- 默认改写 `frame->det`,让 `osd` / `alarm` 读到一致结果。
@ -634,6 +636,7 @@ GraphMgr 负责:
```
**内置 processors当前实现**
- `conf_gate`:按置信度过滤(`conf_min`
- `bbox_gate`:按框尺寸过滤(`min_w`, `min_h`
- `roi_gate`:按 ROI 过滤(`roi:{x,y,w,h}` 归一化;`mode:center` 使用 bbox 中心点判断)
@ -643,6 +646,7 @@ GraphMgr 负责:
> 注意:`hsv_ratio/lab_kmeans` 需要 `Frame` 提供可读的像素数据(`frame->data` 可访问)。若上游是纯 DMA-BUF 且未映射到 CPU这两类处理器会自然退化为“不过滤”。
**ai_yolo 参数说明:**
- `model_version`: `"v5"`, `"v8"``"auto"`(自动检测)
- `num_classes`: 模型类别数(默认 80
- `class_filter`: 只检测指定类别 ID 的数组,如 `[0, 1, 2]`
@ -671,6 +675,7 @@ GraphMgr 负责:
```
**参数说明:**
- `model_path`: RetinaFace RKNN 模型路径
- `conf`: 置信度阈值(默认 0.6
- `nms`: NMS 阈值(默认 0.4
@ -711,6 +716,7 @@ GraphMgr 负责:
```
**参数说明:**
- `model_path`: ArcFace/MobileFaceNet RKNN 模型路径(输入 112x112输出 512D embedding
- `align`: 是否使用 5 点关键点做仿射对齐(推荐开启)
- `emit_embedding`: 是否在结果中输出 embedding调试用生产关闭以省内存
@ -721,6 +727,7 @@ GraphMgr 负责:
- `gallery.expected_dim`: embedding 维度(需与模型匹配)
**判定规则:**
- `top1_sim >= accept` 且(可选)`top1_sim - top2_sim >= margin` → 识别为该人
- 否则标记为 `unknown`
@ -779,6 +786,7 @@ CREATE TABLE embedding (
```
**检索实现:**
- 小库≤几千人CPU 暴力点积,无需额外索引
- 大库(≥几万人):可扩展 HNSW/Faiss 等 ANN 索引
@ -795,6 +803,7 @@ CREATE TABLE embedding (
> 说明:当前实现中 `publish``proto:"hls"` 为**落盘生成 m3u8/ts 文件**`path` 应指向 `index.m3u8` 文件路径;若需要通过网络播放,建议新增 `zlm_http` 节点启动内嵌 HTTP并将 `root` 指向 HLS 父目录(如 `/data/hls`)。
**osd 参数说明:**
- `labels`: 自定义类别标签数组,如 `["cat", "dog", "bird"]`,为空则使用 COCO 默认标签
### 6.4 alarm 插件详细说明
@ -802,6 +811,7 @@ CREATE TABLE embedding (
alarm 插件采用**模块化 Actions 架构**,支持多种报警动作的灵活组合:
**架构设计:**
```
┌─────────────────────────────────────────────────────────┐
│ AlarmNode │
@ -822,6 +832,7 @@ alarm 插件采用**模块化 Actions 架构**,支持多种报警动作的灵
```
**完整配置示例:**
```json
{
"id": "alarm_cam1",
@ -904,11 +915,13 @@ alarm 插件采用**模块化 Actions 架构**,支持多种报警动作的灵
- `alarmContent`:若配置中未提供 `alarmContent`,默认使用 `rule_name`
**external_api 参数说明:**
- 必填:`getTokenUrl`, `putMessageUrl`, `tenantCode`, `channelNo`
- 常用可选:`timeout_ms`(默认 3000、`include_media_url`(默认 true、`token_cache_sec`(默认 600为 0 时仅在 401/403 时刷新 token
- 其它可选:`token_header`、`token_json_path`、`alarmContent`、`max_queue_size` / `queue_policy`、`max_retries` / `retry_backoff_ms`
**规则参数说明:**
- `class_ids`: 要监控的类别 ID 数组(与模型输出对应)
- `objects`: 要监控的类别名称数组(需配合 `labels` 使用)
- `roi`: 感兴趣区域,归一化坐标 (0-1)
@ -917,6 +930,7 @@ alarm 插件采用**模块化 Actions 架构**,支持多种报警动作的灵
- `schedule`: 有效时间段,格式 "HH:MM-HH:MM"
**上传器类型:**
- `local`: 保存到本地文件系统
- `minio`: 上传到 MinIO 对象存储
- `s3`: 上传到 AWS S3兼容 MinIO
@ -926,6 +940,7 @@ alarm 插件采用**模块化 Actions 架构**,支持多种报警动作的灵
storage 插件用于**持续录像**7x24 小时),与 alarm 的事件录像功能互补。
**配置示例:**
```json
{
"id": "storage_cam1",
@ -943,6 +958,7 @@ storage 插件用于**持续录像**7x24 小时),与 alarm 的事件录
```
**参数说明:**
- `mode`: 录像模式,当前支持 `continuous`(持续录像)
- `format`: 输出格式,`mp4` 或 `ts`
- `segment_sec`: 单个文件时长(秒)

View File

@ -1,6 +1,7 @@
# PRD ① 设备端rk3588-agent + media-server远程管理能力V1
## 1. 背景
当前 `media-server` 已提供 HTTP 控制台与配置热更新能力(`/api/*`、`/api/config/reload`、`/api/config/rollback` 等)。由于 **大文件模型上传** 在现有 C++ 自研 HTTP Server 上实现成本较高(需要流式接收/写盘/校验/限流),本期采用更工程化的拆分:
- `media-server`:继续专注业务图(推理/推流/报警)与热更新。
@ -9,18 +10,21 @@
> 本 PRD 覆盖“轻量热更新/重载/回滚业务图级”。systemd/重启系统等运维级操作可作为后续扩展,但不作为 V1 验收项。
## 2. 目标
1. 管理端可通过 UDP 广播在 1 秒内发现同网段 10 台设备(由 `rk3588-agent` 响应)。
2. 管理端可通过 `rk3588-agent` 上传配置 JSON设备端原子写入后触发 `media-server` reload 生效。
3. 管理端可通过 `rk3588-agent` 上传模型文件到设备固定目录,并返回可直接在配置中引用的 `model_path`
4. 所有对外写操作必须鉴权Token读操作默认可不鉴权可配置
## 3. 非目标V1 不做)
- systemd start/stop/restart `media-server`(可在 agent 后续扩展)
- 设备重启/固件升级/插件升级
- 跨网段发现(保留后端可做网段扫描 fallback
- 完整 RBAC/用户体系
## 4. 现状可复用能力(不修改语义)
- HTTP Server`src/http_server.cpp`
- Graph/热更新:`GraphManager::ReloadFromFile`、`GraphManager::RollbackFromLastGood`
- 配置 Expand + Validate`utils/config_expand.*`、`utils/config_schema.h`
@ -29,6 +33,7 @@
## 5. 新增功能范围V1
### 5.1 新增进程rk3588-agentGo
`rk3588-agent` 作为常驻服务,提供:
- UDP 广播发现Option A对管理端 Search 做响应。
@ -36,6 +41,7 @@
- 本地调用 `media-server`:通过 `http://127.0.0.1:<media_port>/api/...` 触发 reload/rollback/读取 graphs/logs。
#### 5.1.1 agent 代码目录结构(建议,开发可直接照此建工程)
建议以 Go module 形式独立工程(可放在同仓库 `agent/` 目录,也可独立仓库)。
```text
@ -56,6 +62,7 @@ agent/
```
### 5.2 media-server 变更范围V1
V1 目标是将大文件上传从 `media-server` 移出,因此 **media-server 可不新增大文件上传接口**。仅要求:
- 保持现有 `/api/config/reload`、`/api/config/rollback`、`/api/graphs`、`/api/logs/recent` 等接口可用。
@ -64,6 +71,7 @@ V1 目标是将大文件上传从 `media-server` 移出,因此 **media-server
## 6. 配置与落盘约定
### 6.1 新增 agent 配置项(建议)
agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议:
```json
@ -87,6 +95,7 @@ agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议:
```
字段说明V1 关键字段):
- `config_path`agent 写入配置文件的目标路径(与 media-server `--config` 一致)。
- `device_id_path`device_id 持久化文件路径(不存在则自动生成并写入)。
- `media_server_base_url`agent 调用 media-server 的本机地址,建议固定 `127.0.0.1`
@ -94,6 +103,7 @@ agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议:
- `media_server_retry`仅对“控制类请求”reload/rollback启用的重试策略。
### 6.2 设备侧文件系统布局(部署约定)
为保证权限与可维护性,约定如下路径:
- 可执行文件:
@ -113,6 +123,7 @@ agent 需要独立配置(例如 `/etc/rk3588-agent/config.json`)。建议:
### 6.3 systemd service部署字段开发/运维可直接照抄)
#### 6.3.1 rk3588-agent.service
路径建议:`/etc/systemd/system/rk3588-agent.service`
```ini
@ -142,6 +153,7 @@ WantedBy=multi-user.target
```
#### 6.3.2 media-server.service建议统一纳入部署约定
路径建议:`/etc/systemd/system/media-server.service`
```ini
@ -169,20 +181,24 @@ WantedBy=multi-user.target
> V1 不要求 agent 控制 systemd但要求两服务可开机自启。
### 6.5 性能调参说明(新增)
- `RK3588_RKNN_CTX_POOL_SIZE`:同一模型的 RKNN context 池大小(默认 3
- `RK3588_RGA_MAX_INFLIGHT`RGA 全局并发上限(默认 2
### 6.4 模型目录结构
- `${models_dir}/manifest.json`
- `${models_dir}/files/<name>__<sha256>.<ext>``ext` 默认 `rknn`,白名单控制)
## 7. 约束与安全
- agent 对外写接口必须 `X-RK-Token`
- 上传限制:必须 `Content-Length`;大小不得超过 `max_upload_mb`
- agent 写盘采用原子写(临时文件 + rename
- agent 与 `media-server` 的本地通信固定走 `127.0.0.1`(避免暴露内部控制面)。
### 7.1 agent 内部调用 media-server 的 URL/超时/重试策略
agent 只调用 media-server 的既有接口(对内 base URL = `media_server_base_url`
- Reload`POST {base}/api/config/reload`
@ -192,27 +208,32 @@ agent 只调用 media-server 的既有接口(对内 base URL = `media_server_b
- Logs`GET {base}/api/logs/recent?limit=...`
超时策略(建议默认值):
- 读接口graphs/logs总超时 `1000ms`(不重试)
- 控制接口reload/rollback总超时 `media_server_timeout_ms`(默认 `3000ms`),允许重试
重试策略(仅控制接口):
- `max_attempts = 3`(首次 + 2 次重试)
- 触发条件:连接失败/超时/5xx不对 4xx 重试)
- backoff`[200ms, 500ms]`
配置下发联动策略(`PUT /v1/config`
1) agent 原子写入 `config_path`
2) 调用 reload按控制接口重试策略
3) 若 reload 最终失败:调用 rollback按控制接口重试策略
4) 返回 500错误消息包含 reload 与 rollback 的结果(便于定位)
### 7.2 启动顺序与可用性
- 建议 systemd 启动顺序:两者都 After network-online。
- agent 对外可先起来;当 media-server 尚未启动时:
- `/v1/graphs`、`/v1/logs/recent` 返回 500error=connect refused/timeout
- `/v1/config` 返回 500写盘可成功但 reload 失败会触发 rollback错误信息提示 media-server 不可用)
## 8. 验收标准Acceptance Criteria
1. 同网段 10 台设备,管理端 SearchUDP broadcast在 1 秒内都能发现;列表包含 `device_id/ip/agent_port/media_port/version/git_sha`
2. agent `PUT /v1/config`
- 发送合法 config设备写盘并触发 `media-server` reload 成功graphs 状态正常。
@ -221,6 +242,7 @@ agent 只调用 media-server 的既有接口(对内 base URL = `media_server_b
4. 无 token 调用写接口返回 401错误返回 JSON`{"error":"..."}`。
## 9. 开发任务拆分(建议)
- [ ] 新增 `rk3588-agent`HTTP 服务 + Token 鉴权 + 日志
- [ ] UDP discovery协议解析/回复、device_id 获取与持久化、停止逻辑
- [ ] `GET /v1/info`:聚合 device/version/git_sha/ports/uptime

View File

@ -1,16 +1,19 @@
# PRD ② 管理端前端React Web UIV1
## 1. 产品形态
- 用户在 PC 上启动 `managerd`Go 后端),浏览器打开:`http://127.0.0.1:<port>/`。
- 前端只与本机 `managerd` 通信(不直连设备),避免跨域与安全复杂度。
## 2. 目标
1. 一键 Search 发现设备并展示在线状态。
2. 单设备:查看 graphs 状态、查看 logs、执行 reload/rollback。
3. 单设备:上传模型、下发配置并生效。
4. 多设备:批量下发配置(任务化显示进度与失败原因)。
## 3. UI 风格V1
- 风格:极简运维控制台(表格 + 抽屉/弹窗 + 表单),信息密度优先。
- 主题:浅色默认;无需复杂动效。
- 组件库Ant Design推荐
@ -21,6 +24,7 @@
- 失败:红色提示 + 可展开错误详情
## 4. 技术选型与工程要求
- React 18 + TypeScript + Vite
- 路由React Router
- 请求与缓存React Query或 SWR
@ -30,13 +34,16 @@
## 5. 页面与交互
### 5.1 设备列表页 `/devices`
**组件**:表格(可搜索/排序)
**顶部操作**
- `Search`(触发发现)
- `Batch Apply Config`(进入批量配置向导/弹窗)
**表格列**
- StatusOnline/Offline
- Device Name
- IP:AgentPort可在详情页展示 MediaPort
@ -46,35 +53,43 @@
- ActionsDetail / Reload / Rollback
**交互**
- Search 点击后 1~2 秒 loading完成后刷新列表。
- Reload/Rollback弹确认框提交后显示 toast失败显示 error 文本。
### 5.2 设备详情页 `/devices/:deviceId`
使用 Tabs
1) **Overview**
- 展示 `info`device_id、device_name、hostname、ip、version、git_sha、uptime
- 展示 graphs 概览(通过后端代理设备 agent 的 graphs 数据)
2) **Graphs**
1) **Graphs**
- Graph 列表name/running/fps/alarm_total/publish_clients
- 点击某 graph 展开详情nodes/edges按后端数据渲染
3) **Logs**
1) **Logs**
- 最近日志(默认 200 行)
- 刷新按钮;(可选)自动刷新开关
4) **Models**
1) **Models**
- 已上传模型列表name/sha256/size/mtime/path
- 上传:选择文件 + 填 name默认用文件名去扩展名
- 上传进度条;成功后自动刷新列表
5) **Config**
1) **Config**
- JSON 编辑器Monaco 或轻量 textarea + 格式化按钮)
- `Apply` 按钮(调用后端创建任务或直接 apply
- 失败时展示 error并提示可执行 rollback
### 5.3 模板/配置生成 `/templates`
**目标**:减少手写 JSON。
- 模板列表(后端提供 templates
@ -84,12 +99,15 @@
- 点击 Apply创建任务跳转任务详情
### 5.4 任务中心 `/tasks`
- 任务列表类型、创建时间、状态running/success/failed/partial
- 任务详情每台设备结果pending/running/success/failed + error
- 实时更新SSEEventSource订阅 `/api/tasks/:id/events`
## 6. 前端对接 API本机 managerd
前端只调用以下(具体字段见后端 PRD
- `POST /api/discovery/search`
- `GET /api/devices`
- `GET /api/devices/:id`
@ -103,6 +121,7 @@
- `POST /api/tasks`、`GET /api/tasks/:id`、`GET /api/tasks/:id/events`
## 7. 验收标准
1. 可 Search 并展示设备列表,状态正确。
2. 设备详情可查看 graphs、logs且 reload/rollback 可用。
3. 可上传模型并在 Models 列表看到。

View File

@ -1,6 +1,7 @@
# PRD ③ 管理端后端Go managerdV1
## 1. 目标与运行方式
- 提供本机 HTTP API 给 React UI 使用。
- 负责 UDP 广播发现Option A维护设备缓存与在线状态。
- 通过设备端 `rk3588-agent` 完成配置/模型等运维操作,并可通过 agent 代理读取 graphs/logs。
@ -9,6 +10,7 @@
运行:单可执行 `managerd`,默认监听 `127.0.0.1:18080`(可配置)。
## 2. 外部依赖与约束
- Go 版本:>= 1.22(建议)
- 标准库优先Web 框架可选 `chi`/`gin`(建议 chi + net/http
- 不需要数据库V1 用内存 + 可选本地 JSON 持久化)。
@ -16,17 +18,20 @@
## 3. 模块划分
### 3.1 Discovery
- 向所有可用网卡的广播地址发送 UDP discover。
- 监听本地 UDP socket 收集 replies时间窗默认 1200ms
- 去重规则:按 `device_id` 去重,以最新 reply 为准。
### 3.2 Device Registry
- 内存缓存:
- `device_id -> {ip, agent_port, media_port, device_name, version, git_sha, last_seen_ms, online}`
- 定时刷新(可配置间隔):对 online 设备拉取 `GET /v1/graphs`agent 代理),更新摘要。
- Offline 规则:超过 `offline_after_ms`(如 10000ms未见到则标记离线。
### 3.3 Device Client
- 统一超时connect 1s、overall 3s可配置
- 统一错误包装:返回 `error_code + message + device_id`
- Token
@ -34,12 +39,14 @@
- 可预留 per-device tokenP1
### 3.4 Templates/Config Builder
- 模板库来源:
- V1managerd 内置embed或本地 `templates/` 目录读取
- 返回前端表单 schemaV1 允许手工维护(避免解析占位符带来的不确定性)。
- 生成 root config基于模板与 params产出 `{global,templates,instances}`
### 3.5 Task Runner
- 任务类型:
- `config_apply`(对 N 台设备下发 config
- `reload`
@ -52,28 +59,39 @@
## 4. managerd 对前端 API 规格V1
### 4.1 Discovery
#### `POST /api/discovery/search`
Request:
```json
{ "timeout_ms": 1200 }
```
Response:
```json
{ "items": [ {"device_id":"...","ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"..."} ] }
```
### 4.2 Devices
#### `GET /api/devices`
Response:
```json
{ "items": [ {"device_id":"...","online":true,"last_seen_ms":0,"ip":"...","agent_port":9100,"media_port":9000,"device_name":"...","version":"...","git_sha":"...","graphs":[...]} ] }
```
#### `GET /api/devices/:id`
Response包含 `info`、`graphs_summary`、`last_seen`。
### 4.3 Device actions代理调用
以下全部通过 agent
- `POST /api/devices/:id/reload` → agent `POST /v1/media-server/reload`
- `POST /api/devices/:id/rollback` → agent `POST /v1/media-server/rollback`
- `GET /api/devices/:id/graphs` → agent `GET /v1/graphs`
@ -81,28 +99,39 @@ Response包含 `info`、`graphs_summary`、`last_seen`。
- `GET /api/devices/:id/logs?limit=200` → agent `GET /v1/logs/recent?limit=200`
### 4.4 Config apply
#### `POST /api/devices/:id/config/apply`
Request:
```json
{ "config": { } }
```
Behavior调用 agent `PUT /v1/config`
### 4.5 Model upload
#### `POST /api/devices/:id/models/upload`
Request`multipart/form-data`,字段:
- `name`: string
- `file`: binary
Behavior读取文件流转发为 agent `PUT /v1/models/{name}`raw body
### 4.6 Templates
- `GET /api/templates`
- `GET /api/templates/:name`
### 4.7 Tasks
#### `POST /api/tasks`
Request:
```json
{
"type": "config_apply",
@ -110,25 +139,32 @@ Request:
"payload": { "config": {} }
}
```
Response:
```json
{ "task_id": "..." }
```
#### `GET /api/tasks/:id/events` (SSE)
Event `device_update` data:
```json
{ "device_id":"...","status":"running|success|failed","progress":0.0,"error":"" }
```
## 5. 错误处理规范managerd → 前端)
- 成功2xx + `{"ok":true}` 或正常业务 JSON
- 失败4xx/5xx +
```json
{ "error": { "code": "...", "message": "...", "device_id": "...", "detail": "..." } }
```
建议错误码:
- `DISCOVERY_FAILED`
- `DEVICE_NOT_FOUND`
- `DEVICE_OFFLINE`
@ -138,7 +174,9 @@ Event `device_update` data:
- `VALIDATION_ERROR`
## 6. 配置文件managerd建议
`managerd.json`
```json
{
"listen": "127.0.0.1:18080",
@ -151,6 +189,7 @@ Event `device_update` data:
```
## 7. 验收标准
1. Search 可发现设备并更新 registry离线判断正确。
2. 可通过 agent 读取 graphs/logs`GET /v1/graphs`、`GET /v1/logs/recent`)。
3. 单设备 `config/apply`、`reload`、`rollback` 可用,错误可定位。

View File

@ -3,6 +3,7 @@
> 适用版本V12026-01
>
> 范围:**仅控制端 GUI/managerd 如何调用设备端 rk3588-agent**。
>
> - 本项目中已在 `agent + media-server` 实现本文档所需能力。
> - **不包含**配置程序(前端/后端)具体 UI 代码实现细节。
@ -36,15 +37,18 @@
## 3. 鉴权与错误处理
### 3.1 鉴权
- Header`X-RK-Token: <token>`
- 写接口(会写盘/改状态)必须鉴权。
- 读接口默认可不鉴权;若设备端配置 `agent.require_token_for_read=true`,则读接口也必须鉴权。
### 3.2 统一错误返回
- 成功:`2xx`,一般为 `{"ok":true,...}` 或业务 JSON
- 失败:`4xx/5xx`,返回 `{"error":"..."}`
常见 HTTP
- `401`unauthorized
- `400`validation failed / invalid json
- `404`not found
@ -56,6 +60,7 @@
## 4. GUI 页面与调用流程
### 4.1 设备详情页(只读)
1) 设备信息:`GET /v1/info`
2) 运行态通道摘要:`GET /v1/graphs`
3) 单通道详情(可选):`GET /v1/graphs/{name}`
@ -64,16 +69,20 @@
### 4.2 通道配置页核心instances
#### 4.2.1 初始化
1) 获取 schema渲染表单`GET /v1/config/ui/schema`
2) 获取当前 state回显`GET /v1/config/ui/state`
GUI 侧以 `instances[]` 为“通道列表”。
#### 4.2.2 校验/预览dry-run
用户编辑完成后:
- `POST /v1/config/ui/plan`
返回:
- `generated_config`:生成出来的 root config可用于预览/导出)
- `diff`added/removed/changed实例级别
@ -81,15 +90,18 @@ GUI 侧以 `instances[]` 为“通道列表”。
> 真正的构图/插件/模型加载等校验发生在 apply → media-server reload 阶段。
#### 4.2.3 应用配置
- `POST /v1/config/ui/apply`
行为:
1) agent 生成新的 root config只包含 `global/queue/templates/instances`
2) 写盘到 `agent.config_path`
3) 调用 media-server reload
4) reload 失败则自动 rollback 并返回 500
#### 4.2.4 回滚(手动)
- `POST /v1/media-server/rollback`
> 回滚语义:回滚到“上一次成功的**源配置**”(保留 templates/instances不会被 expanded 覆盖),便于 GUI 二次编辑。
@ -97,6 +109,7 @@ GUI 侧以 `instances[]` 为“通道列表”。
### 4.3 人脸库管理页
#### 4.3.1 上传人脸库
- `PUT /v1/face-gallery`
- Content-Type`application/octet-stream`
- BodySQLite 文件二进制(`face_gallery.db`
@ -104,9 +117,11 @@ GUI 侧以 `instances[]` 为“通道列表”。
保存位置:`<agent.models_dir>/face_gallery.db`
#### 4.3.2 立即生效(无需重启)
- `POST /v1/face-gallery/reload`
行为:
- agent 遍历所有 graphs找到 `type==ai_face_recog` 的节点
- 对每个节点下发 runtime config patchbump `gallery.reload_seq`
- 节点收到后会重新加载 SQLite db
@ -118,49 +133,69 @@ GUI 侧以 `instances[]` 为“通道列表”。
> Base`http://<device_ip>:<agent_port>`(默认 9100
### 5.1 设备信息
#### `GET /v1/info`
用于设备列表/详情。
### 5.2 运行态(只读代理)
#### `GET /v1/graphs`
#### `GET /v1/graphs/{name}`
#### `GET /v1/logs/recent?limit=200`
### 5.3 配置文件root config
#### `GET /v1/config`
返回 `agent.config_path` 对应 JSON用于导出/高级查看)。
#### `PUT /v1/config`
上传完整 root config JSON写盘 + reload失败自动 rollback
### 5.4 语义化配置GUI 推荐使用)
#### `GET /v1/config/ui/schema`
返回:可选模板列表 + 字段 schema类型/默认/必填)。
#### `GET /v1/config/ui/state`
返回:当前 config 映射到 GUI state主要是 `instances[]`+ 内置模板列表。
#### `POST /v1/config/ui/plan`
输入 desired stateinstances 列表),返回生成 config 与 diff。
#### `POST /v1/config/ui/apply`
同 plan但会写盘并 reload失败自动 rollback
### 5.5 模型管理(可选,但建议 GUI 支持)
#### `PUT /v1/models/{name}`
上传模型(.rknn返回可引用的 `path`
#### `GET /v1/models`
列出已上传模型(包含 `name/path/sha256/mtime_ms`)。
### 5.6 人脸库
#### `GET /v1/face-gallery`
返回当前 db 文件信息exists/size/mtime/path
#### `PUT /v1/face-gallery`
上传 `face_gallery.db`
#### `POST /v1/face-gallery/reload`
让所有 `ai_face_recog` 节点热加载新 db。
---
@ -198,6 +233,7 @@ GUI 侧以 `instances[]` 为“通道列表”。
```
说明:
- `global/queue` 可省略agent 会沿用当前 config 中的值。
- `instances` 为全量期望状态:控制端应把当前列表 + 修改后的列表一起提交。
- 当前实现会生成新的 root config只包含 `global/queue/templates/instances`),不会保留 `graphs`
@ -220,20 +256,25 @@ GUI 侧以 `instances[]` 为“通道列表”。
> 模板名来自 `GET /v1/config/ui/schema``templates[]`
### 7.1 `transcode_rtsp_hls`
- 必填:`url`
- 常用:`fps,src_w,src_h,gop,bitrate_kbps,rtsp_port,hls_path`
### 7.2 `yolo_rtsp_hls`
- 必填:`url, model_path`
### 7.3 `yolo_alarm_minio`
- 必填:`url, model_path, minio_endpoint, minio_bucket, minio_ak, minio_sk`
- 常用:`cooldown_ms`(默认 3000
### 7.4 `face_det_rtsp_hls`
- 必填:`url, det_model_path`
### 7.5 `face_det_recog_rtsp_hls`
- 必填:`url, det_model_path, recog_model_path`
- 默认:`gallery_path=./models/face_gallery.db``thr_accept=0.45``thr_margin=0.05`
@ -242,6 +283,7 @@ GUI 侧以 `instances[]` 为“通道列表”。
## 8. 性能调优参数(可选,建议 GUI 以“高级设置”方式暴露)
### 8.1 `preprocess`AI 分支减拷贝 / RGA 并发)
- `dst_packed`bool默认 `false`
- 说明:当 `dst_format``rgb/bgr` 时,若开启则输出紧凑 packed`stride = width * 3`),可避免下游(如 `ai_yolo`)对齐 stride 导致的逐行 memcpy。
- `rga_max_inflight`int默认 `0`(表示不在配置里覆盖全局值)。
@ -249,12 +291,14 @@ GUI 侧以 `instances[]` 为“通道列表”。
- 备注:也可通过环境变量 `RK3588_RGA_MAX_INFLIGHT` 设置。
### 8.2 `publish/storage`(一次编码,多处复用)
- `publish.attach_encoded_meta`bool默认 `true`(当 publish 有下游 output_queues 时)。
- 说明:将已编码视频包(含 codec extradata/pts/key挂在 `frame.user_meta`,供下游复用(例如报警 clip、storage 复用码流)。
- `storage.reuse_encoded_meta`bool默认 `true`
- 说明:若收到 `EncodedVideoFrameMeta`storage 将直接 remux 写文件(避免再次 MPP 编码若未收到则保持原逻辑MPP 编码录制)。
### 8.3 推理并发(环境变量,部署侧配置)
- `RK3588_RKNN_CTX_POOL_SIZE`:默认 `3`
- 说明:同一模型创建的 RKNN context 数量(多路同模型推理可并发,避免被单 context 串行化)。
@ -263,11 +307,13 @@ GUI 侧以 `instances[]` 为“通道列表”。
## 9. 人脸库路径对齐建议(避免“上传了但识别不到”)
1) 默认推荐(最省事):
- media-server work_dir`/opt/rk3588sys`
- agent.models_dir`/opt/rk3588sys/models`
- ai_face_recog.gallery.path`./models/face_gallery.db`
2) 若你们的 work_dir/models_dir 不是这种关系:
1) 若你们的 work_dir/models_dir 不是这种关系:
- 控制端在 instances params 里把 `gallery_path` 设置为**绝对路径**(例如 `/opt/rk3588sys/models/face_gallery.db`)。
---

View File

@ -1,30 +1,37 @@
# PRD_05Device 侧轻量级 Tracker 节点(可插拔)
## 1. 背景与问题
当前 Device 侧媒体服务采用“配置驱动 DAGGraph+ 插件节点Node+ SPSC 队列”的流水线架构输入RTSP/文件)→ 预处理 → AI 推理(检测/识别等)→ OSD/推流/告警。
在实际部署中常见三类痛点:
1) **重复报警**:同一目标在画面连续出现时,规则可能在采样频率下重复触发。
2) **重复上传MinIO/HTTP 等)**:报警动作触发后在短时间内重复上传同类素材。
3) **推理开销过高**:虽然已有 `infer_fps` 等限频,但在低推理频率下希望仍保持事件稳定性与可解释性。
现有代码中:
- `Frame::det``DetectionResult`)包含 `Detection{cls_id, score, bbox, track_id}`,其中 `track_id` 当前默认 `-1`(未做追踪)。
- `alarm` 侧已有 `rules.cooldown_ms`、`min_duration_ms` 与 `actions.*.min_interval_ms` 的时间窗限流,但属于“按规则/动作的时间窗”粒度。
## 2. 目标Goals
提供一个 **可选、可插拔**`tracker` 插件节点,用于为检测结果补充稳定的 `track_id`,以支持:
1) **按目标实例去重**(基于 `track_id`):同一目标在持续存在期间不重复触发/上传。
2) **稳定性/精准性优先,资源占用尽可能低**:不引入 ReID/特征网络,主要使用几何与置信度关联。
3) **按类别选择性追踪**:并非所有类别都追踪,可由配置指定哪些 `cls_id` 参与追踪。
4) **架构适配**:完全符合现有 Graph/Node 插件机制,插入与否由 `configs/*.json` 决定;不插入则不改变任何行为。
## 3. 非目标Non-Goals
1) 不做跨摄像头/跨 Graph 的关联(不做全局 ID
2) 不做基于外观特征ReID的强一致性追踪如 DeepSORT+ReID
3) 不保证对极端遮挡/快速运动/密集重叠场景达到 SOTA 跟踪指标;本 PRD 目标是“工程可用+低资源”。
## 4. 现有架构约束(必须遵守)
1) Node 单输入、多输出Graph 当前限制每个节点 **只能有一个 input queue**
2) Node 的 `Process(FramePtr)` 由框架线程调用(`Graph::Start()` 中的 worker loopTracker 节点不应引入额外线程(除非明确需求)。
3) Tracker 节点不得破坏 `Frame` 上其他元信息(尤其是 `publish` 节点可能写入 `frame->user_meta` 用于 clip
@ -32,6 +39,7 @@
## 5. 功能设计
### 5.1 节点定义
- Node type`tracker`
- role`filter`
- 输入:`FramePtr`(读取 `frame->det`
@ -39,43 +47,54 @@
- 当 `frame->det == nullptr``items` 为空:直接透传。
### 5.2 追踪算法推荐ByteTrack-lite + IOU 关联)
在不引入外观特征的前提下,为提高稳定性,采用“两段式关联”策略:
**核心思想**
1) 将 det 按置信度分成高置信(`score >= high_th`)与低置信(`low_th <= score < high_th`
2) 优先用高置信 det 去匹配已有 tracks未匹配的 tracks 再用低置信 det 做二次匹配(减少断轨)。
3) 匹配度量使用 IOU可加入 gating中心点距离/面积比等轻量约束)。
**匹配策略**
- 为降低资源占用:默认使用 greedy matching按 IOU 从高到低选择不冲突匹配),不强制使用匈牙利算法。
- 允许后续通过配置切换到 Hungarian可选增强项但不作为本 PRD 必需。
**Track 生命周期**
- 创建:未匹配到现有 track 的高置信 det → 创建新 track。
- 更新:匹配成功 → 更新 bbox、last_seen、hit_streak。
- 丢失:超过 `max_age_ms`(或 `max_age_frames`)未匹配 → 删除。
**分类策略**
- 默认按 `cls_id` 分组匹配(避免不同类别互相抢 track
- 可配置 `per_class=false` 以允许跨类别匹配(默认不建议)。
### 5.3 按类别选择性追踪
支持以下配置(至少实现其一,推荐两者都实现):
- `track_classes`: `int[]`:白名单。非空时仅追踪这些 `cls_id`
- `ignore_classes`: `int[]`:黑名单。用于排除某些 `cls_id`
规则:
- 若 `track_classes` 非空,则优先按白名单过滤。
- 否则按 `ignore_classes` 排除。
- 未参与追踪的 det 必须保持 `track_id = -1`
### 5.4 按模型类型/推理类型启用(可选,但推荐)
`DetectionResult.model_name` 已存在Tracker 支持:
- `allowed_models`: `string[]`:当非空时,仅对 `model_name` 在集合内的帧启用。
用途:同一 pipeline 可能挂多种推理节点yolo/face_det/自定义模型),避免对不需要的输出做追踪。
### 5.5 插入位置建议(不强制)
1) 仅为“告警去重/上传去重”服务:
- 推荐 `publish -> tracker -> alarm`
- 原因:不影响推流;不破坏 `publish` 写入的 `frame->user_meta`clip 仍可用)。
@ -83,8 +102,11 @@
- 推荐 `ai_* -> tracker -> osd -> ...`
## 6. 配置Config Schema
### 6.1 tracker 节点配置字段
节点 JSON 示例:
```json
{
"id": "trk_cam1",
@ -113,6 +135,7 @@
```
字段说明:
- `mode``"off" | "bytetrack_lite"`(最少实现这两种)
- `per_class`:默认 `true`
- `track_classes`:白名单;默认空(表示全类别)。
@ -125,7 +148,9 @@
- `max_tracks`:上限保护,避免极端场景内存增长。
### 6.2 Graph 接入示例
在现有 graph 中插入(示例:`pub -> tracker -> alarm`
```json
"nodes": [
{"id":"pub_cam1","type":"publish","role":"filter","enable":true, ...},
@ -140,7 +165,9 @@
```
## 7. 对外接口与数据契约
### 7.1 输入输出契约
- 输入:`frame->det` 必须由上游检测节点填充Tracker 不负责生成 det。
- 输出:
- `frame` 本体不变;
@ -148,12 +175,16 @@
- 不修改 `frame->user_meta`、不修改 `frame->data/planes`
### 7.2 与 alarm/http/minio 的配合
- `plugins/alarm/actions/http_action.cpp` 已会输出 `track_id` 字段(现有实现),因此 Tracker 生效后 HTTP 报警可以自然携带 `track_id`
- MinIO 上传去重当前依赖 `actions.*.min_interval_ms`;后续可扩展为 per-track 去重(见第 10 节增强建议)。
## 8. 指标与可观测性
### 8.1 Custom Metrics
Tracker 节点建议实现 `GetCustomMetrics()` 输出:
- `tracks_active`
- `tracks_created_total`
- `tracks_removed_total`
@ -162,15 +193,19 @@ Tracker 节点建议实现 `GetCustomMetrics()` 输出:
- `avg_process_time_ms`
### 8.2 Debug
- `debug.stats`:周期打印关键统计。
- 不输出过多 per-frame 日志,避免影响实时性。
## 9. 性能与资源约束
目标(以单路为单位,具体需实测校准):
- `N_det <= 64` 时,每帧 Tracker 处理耗时应为毫秒级以下(通常 < 1ms依平台不同)。
- 内存track 状态结构固定上限 `max_tracks`,避免无界增长。
## 10. 验收标准Acceptance Criteria
1) **可插拔**:不配置 `tracker` 节点时,系统行为与当前版本一致。
2) **正确写入 track_id**:配置启用时,目标类别的 det `track_id` 在连续帧中稳定且可复用。
3) **按类别控制有效**:不在白名单/在黑名单的 `cls_id` 必须保持 `track_id=-1`
@ -178,6 +213,7 @@ Tracker 节点建议实现 `GetCustomMetrics()` 输出:
5) **资源可控**`max_tracks` 生效;极端场景不会导致内存持续增长。
## 11. 开发拆解(实现步骤)
1) 新增插件目录与编译接入:`plugins/tracker/`,更新 `plugins/CMakeLists.txt` 注册编译。
2) 实现 `TrackerNode`
- `Init()` 解析配置。
@ -187,6 +223,7 @@ Tracker 节点建议实现 `GetCustomMetrics()` 输出:
3) 增加一个示例配置(不强制提交到 README可在现有 `configs/*` 中添加一份测试 json若产品流程允许
## 12. 增强建议(不属于本 PRD 必做,但推荐路线)
1) **Alarm 去重升级为 per-track**:在 `alarm` 节点内部维护 `(rule_name, track_id)` 的冷却/状态机enter/stay/leave
2) **自适应推理频率**:结合最近 N 秒的命中情况动态调整 `infer_fps`(需与现有热更新机制配合)。
3) **Hungarian 可选开关**:当 det 数量大且遮挡多时提升一致性,但要评估 CPU 成本。

View File

@ -1,25 +1,31 @@
# PRD_06 多硬件解耦计划RK3588/Atlas/Jetson
## 1. 背景与目标
当前工程深度绑定 RK3588RKNN/RGA/MPP/DMA-BUF限制了 Atlas、Jetson 等平台的接入。目标是在**不破坏现有功能**的前提下,通过接口解耦与默认实现保留现有行为,实现多硬件可插拔支持。
### 目标
- 以接口层抽象 **推理、图像处理、编解码、缓冲区** 四个核心模块。
- 默认实现保持 RK3588 行为与性能路径(零拷贝/DMA-BUF
- 逐步迁移现有节点,避免一次性大改。
### 非目标
- 不改变业务逻辑(检测/识别流程、RTSP/HLS 业务)。
- 不在本阶段引入新 UI/协议或跨平台发布流程。
## 2. 现状摘要(关键路径)
- 推理:`include/ai_scheduler.h`, `src/ai_scheduler.cpp`RKNN + DMA-BUF 输入)
- 图像处理:`plugins/preprocess/preprocess_node.cpp`RGA 或 swscale
- 编解码:`plugins/input_rtsp/*`, `plugins/input_file/*`, `plugins/publish/*`MPP + FFmpeg 混用)
- 缓冲:`include/frame/frame.h`dma_fd/planes/data_owner
## 3. 总体方案
引入四类接口与默认实现:
- **IInferBackend**:推理后端抽象(默认 RKNN
- **IImageProcessor**:图像预处理抽象(默认 RGA + swscale 兜底)
- **IDecoder / IEncoder**:编解码抽象(默认 MPP必要时 FFmpeg
@ -30,7 +36,9 @@
## 4. 实施步骤、里程碑与单元测试
### Step 1建立基础抽象与工厂
**实施内容**
- 新建 `include/hw/` 下接口定义:`i_infer_backend.h`, `i_image_processor.h`, `i_decoder.h`, `i_encoder.h`, `frame_buffer.h`
- 定义最小能力集:
- IInferBackend: `LoadModel`, `Infer`, `InferBorrowed`
@ -40,58 +48,72 @@
- 新建工厂:`hw_factory.h/cpp`,根据配置返回默认实现
**关键里程碑**
- 接口头文件编译通过;工程无行为变化
- 工厂默认返回 RK3588 实现(空实现也可先用占位)
**单元测试GTest**
- `HwFactory_Defaults_ReturnsRk3588Impls`
- `FrameBuffer_Metadata_Preserved`dma_fd/planes 赋值一致性)
---
### Step 2推理模块解耦RKNN → IInferBackend
**实施内容**
- 将 `AiScheduler` 包装为 `RknnInferBackend` 实现
- `ai_*` 节点依赖 `IInferBackend` 接口注入(保留默认行为)
- 保留 `InferBorrowed` 以支持零拷贝输入
**关键里程碑**
- 现有模型推理链路无回归,性能基准一致(同配置)
- RKNN 仍可多上下文并发
**单元测试GTest**
- `InferBackend_LoadModel_Smoke`(加载模型返回成功)
- `InferBackend_BorrowedInput_UsesDmaFd`(检查传入 dma_fd 路径被调用)
---
### Step 3图像预处理解耦RGA/CPU → IImageProcessor
**实施内容**
- 抽取 RGA 路径为 `RgaImageProcessor`
- 抽取 swscale 路径为 `SwscaleImageProcessor`
- `preprocess_node` 仅面向接口调用
**关键里程碑**
- `use_rga=true/false` 行为完全一致
- RGA 限流逻辑RgaGate保留
**单元测试GTest**
- `ImageProcessor_RgaVsSwscale_OutputShape`(输出尺寸一致)
- `ImageProcessor_ColorConversion_Nv12ToRgb`(像素格式转换)
---
### Step 4编解码解耦MPP/FFmpeg → IDecoder/IEncoder
**实施内容**
- `MppDecoder`, `FfmpegDecoder` 实现 `IDecoder`
- `MppEncoder`, `FfmpegEncoder` 实现 `IEncoder`
- `input_rtsp/input_file/publish/storage` 节点仅面向接口
**关键里程碑**
- RTSP 输入与 HLS 输出链路不变
- MPP 仍为默认路径FFmpeg 作为兜底/平台适配
**单元测试GTest**
- `Decoder_Open_Close_Smoke`
- `Encoder_Open_Close_Smoke`
- `Codec_Pipeline_EncodeDecode_OneFrame`(小尺寸样例帧)
@ -99,47 +121,59 @@
---
### Step 5缓冲区抽象Frame → FrameBuffer
**实施内容**
- 新增 `FrameBuffer`,替代直接使用 `Frame` 的 dma_fd/data_owner
- `Frame` 保留为业务结构,内部持有 `FrameBuffer`
- 统一 DMA 同步接口以便多硬件适配
**关键里程碑**
- DMA-BUF 与内存缓冲区均可通过统一接口访问
- `Frame` 兼容旧字段,最小侵入替换完成
**单元测试GTest**
- `FrameBuffer_Sync_NoCrash`
- `FrameBuffer_PlaneAccess_Consistent`
---
### Step 6多硬件适配接入Atlas/Jetson
**实施内容**
- 新增 `AtlasInferBackend/AtlasImageProcessor/AtlasCodec` 实现(占位/实验性)
- 新增 `JetsonInferBackend/JetsonImageProcessor/JetsonCodec` 实现
- 通过配置切换平台实现
**关键里程碑**
- 不影响 RK3588 默认路径
- 新平台可在单机完成 smoke 测试
**单元测试GTest**
- `HwFactory_SelectsBackend_ByConfig`
- `PlatformImpls_Smoke_Construct`(构造/释放)
## 5. 风险与缓解
- **接口过宽导致迁移成本增加** → 控制最小接口集,逐步扩展
- **性能回退** → 保留 RK3588 默认实现与 DMA-BUF 快路径
- **迁移破坏现有节点** → 节点逐个替换,保持旧路径可回退
## 6. 验证与回滚
### 验证命令
```
scripts/build_host.sh
ctest --test-dir build/host --output-on-failure
```
### 回滚策略
- 以编译开关/配置切换回旧路径
- 保留 RK3588 实现作为默认后端

View File

@ -0,0 +1,2 @@
# 部署环境需求

View File

@ -1,5 +1,5 @@
# 开发和部署所需的命令
ffmpeg -f dshow -i video="1080P USB Camera" -c:v libx264 -preset ultrafast -pix_fmt yuv420p -f rtsp rtsp://localhost:8554/cam
@ -19,9 +19,6 @@
cmake --build build -j$(nproc)
//退出
pidof media-server
@ -29,19 +26,16 @@
ss -lntp | grep ':9000'
http://10.0.0.81:9000/hls/cam1/index.m3u8
<http://10.0.0.81:9000/hls/cam1/index.m3u8>
rtsp://10.0.0.81:8555/live/cam1
D:\minio\bin>minio.exe server D:\minio\data --address ":9000" --console-address ":9001"
//生成人脸模型
python build_gallery.py --dataset "D:\App\python\AddFaceTo3588\faces\dataset" --db_out "D:\App\python\AddFaceTo3588\faces\face_gallery.db" --det_model "D:\App\python\AddFaceTo3588\models\RetinaFace_mobile320.onnx" --recog_model "D:\App\python\AddFaceTo3588\models\mobilefacenet_arcface_prenorm.onnx" --det_outputs_config "D:\App\python\AddFaceTo3588\models\retinaface_mobile320_config.json" --det_score_thresh 0.6 --max_imgs_per_person 10 --pick_face largest --min_face_size 80 --expected_dim 512 --fail_on_empty true
编译
cd /d D:\App\C++\Rk3588Sys\agent
@ -101,13 +95,13 @@ ls -l ./rk3588-agent_linux_arm64
sudo systemctl daemon-reload
sudo systemctl enable --now rk3588-agent
4) 查看状态与日志
1) 查看状态与日志
sh
sudo systemctl status rk3588-agent --no-pager
sudo journalctl -u rk3588-agent -f
5) 停止/重启
1) 停止/重启
sh
sudo systemctl stop rk3588-agent
@ -116,10 +110,9 @@ ls -l ./rk3588-agent_linux_arm64
这样运行后SSH 断开不会影响进程(由 systemd 托管)。如果你的 agent.config.json 里有相对路径(如 models 目录),记得写成绝对路径,或放到
/opt/rk3588-agent/ 并按配置调整。
## 后端启动命令
## 后端启动命令
go run .\cmd\managerd\main.go .\managerd.json
##查看npu占用
sudo watch -n 1 cat /sys/kernel/debug/rknpu/load
sudo watch -n 1 cat /sys/kernel/debug/rknpu/load

284
scripts/systemd/Mannual.md Normal file
View File

@ -0,0 +1,284 @@
# RK3588 Media Server Systemd 集成
本目录包含 RK3588 Media Server 和 Agent 的 systemd 服务配置和管理脚本。
## 概述
| 服务 | 描述 | 默认端口 |
|------|------|----------|
| `media-server` | C++ 媒体服务器(视频流处理) | 9000 (HTTP), 8554/8555 (RTSP) |
| `rk3588-agent` | Go 管理代理HTTP API | 9100 |
## 快速开始
### 方法一:快速设置(推荐用于开发板)
如果你已经在 Orange Pi 上编译好项目,直接运行:
```bash
cd /path/to/OrangePi3588Media
sudo ./scripts/systemd/quick-setup.sh
```
此脚本会自动:
1. 检查并编译项目(如需要)
2. 安装 systemd 服务
3. 启动服务
4. 显示访问地址
### 方法二:手动安装
```bash
cd /path/to/OrangePi3588Media
# 安装服务
sudo ./scripts/systemd/install-systemd.sh
# 或指定自定义路径
sudo ./scripts/systemd/install-systemd.sh \
--media-bin ./build/media-server \
--media-config ./configs/sample_cam1.json \
--agent-bin ./agent/rk3588-agent_linux_arm64 \
--agent-config ./agent/agent_cam1.config.json
```
### 方法三:手动步骤(了解细节)
```bash
# 1. 复制服务文件
sudo cp scripts/systemd/media-server.service /etc/systemd/system/
sudo cp scripts/systemd/rk3588-agent.service /etc/systemd/system/
# 2. 创建安装目录并复制文件
sudo mkdir -p /opt/rk3588-media-server/{bin,lib,etc,logs}
sudo cp build/media-server /opt/rk3588-media-server/bin/
sudo cp configs/sample_cam1.json /opt/rk3588-media-server/etc/media-server.json
sudo mkdir -p /opt/rk3588-agent
sudo cp agent/rk3588-agent_linux_arm64 /opt/rk3588-agent/rk3588-agent
sudo cp agent/agent_cam1.config.json /opt/rk3588-agent/agent.config.json
# 3. 重载 systemd
sudo systemctl daemon-reload
# 4. 启动并启用服务
sudo systemctl enable --now media-server
sudo systemctl enable --now rk3588-agent
```
## 服务管理
### 查看状态
```bash
# 使用便捷脚本
./scripts/systemd/status.sh
# 或手动查看
sudo systemctl status media-server
sudo systemctl status rk3588-agent
# 查看 NPU 负载
sudo watch -n 1 cat /sys/kernel/debug/rknpu/load
```
### 启动/停止/重启
```bash
# Media Server
sudo systemctl start media-server
sudo systemctl stop media-server
sudo systemctl restart media-server
# Agent
sudo systemctl start rk3588-agent
sudo systemctl stop rk3588-agent
sudo systemctl restart rk3588-agent
# 同时重启两者
sudo systemctl restart media-server rk3588-agent
```
### 开机自启
```bash
# 启用开机自启
sudo systemctl enable media-server
sudo systemctl enable rk3588-agent
# 禁用开机自启
sudo systemctl disable media-server
sudo systemctl disable rk3588-agent
```
### 查看日志
```bash
# 实时跟踪日志
sudo journalctl -u media-server -f
sudo journalctl -u rk3588-agent -f
# 查看最近 100 行
sudo journalctl -u media-server -n 100 --no-pager
# 查看今天的日志
sudo journalctl -u media-server --since today
# 按时间范围查看
sudo journalctl -u media-server --since "2024-01-01 10:00:00" --until "2024-01-01 12:00:00"
```
## 配置文件
### Media Server
位置: `/opt/rk3588-media-server/etc/media-server.json`
```bash
# 编辑配置
sudo nano /opt/rk3588-media-server/etc/media-server.json
# 验证 JSON 格式
python3 -m json.tool /opt/rk3588-media-server/etc/media-server.json
# 重启生效
sudo systemctl restart media-server
```
### Agent
位置: `/opt/rk3588-agent/agent.config.json`
```bash
sudo nano /opt/rk3588-agent/agent.config.json
sudo systemctl restart rk3588-agent
```
## 卸载
```bash
# 使用卸载脚本(保留配置备份)
sudo ./scripts/systemd/uninstall-systemd.sh
# 或手动卸载
sudo systemctl stop media-server rk3588-agent
sudo systemctl disable media-server rk3588-agent
sudo rm -f /etc/systemd/system/media-server.service
sudo rm -f /etc/systemd/system/rk3588-agent.service
sudo systemctl daemon-reload
# 然后手动删除 /opt/rk3588-media-server/ 和 /opt/rk3588-agent/
```
## 故障排查
### 服务无法启动
```bash
# 1. 查看详细错误信息
sudo journalctl -u media-server -n 50 --no-pager
# 2. 检查配置文件
sudo /opt/rk3588-media-server/bin/media-server --config /opt/rk3588-media-server/etc/media-server.json --version
# 3. 检查端口占用
sudo ss -tlnp | grep -E '(9000|8554|8555|9100)'
# 4. 检查权限
ls -la /opt/rk3588-media-server/bin/media-server
```
### 端口冲突
如果 9000/8554/8555 端口被占用,修改配置文件:
```json
// media-server.json
{
"http": {
"port": 9001 // 修改为其他端口
},
"rtsp": {
"port": 8556 // 修改为其他端口
}
}
```
### NPU 相关问题
```bash
# 检查 NPU 驱动
cat /sys/kernel/debug/rknpu/version
# 检查 NPU 负载
watch -n 1 cat /sys/kernel/debug/rknpu/load
# 检查设备节点
ls -la /dev/rknpu*
```
## 文件说明
```
scripts/systemd/
├── README.md # 本文件
├── media-server.service # Media Server systemd 服务文件
├── rk3588-agent.service # Agent systemd 服务文件
├── install-systemd.sh # 安装脚本
├── uninstall-systemd.sh # 卸载脚本
├── status.sh # 状态查看脚本
└── quick-setup.sh # 快速设置脚本(一键部署)
```
## 服务文件详解
### media-server.service
```ini
[Unit]
Description=RK3588 Media Server
After=network-online.target
[Service]
Type=simple
User=root
ExecStart=/opt/rk3588-media-server/bin/media-server --config /opt/rk3588-media-server/etc/media-server.json
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
```
关键配置:
- `Restart=on-failure`: 崩溃后自动重启
- `LimitNOFILE=65535`: 增加文件描述符限制(视频流需要)
- `After=network-online.target`: 确保网络就绪后启动
### rk3588-agent.service
```ini
[Unit]
Description=RK3588 Agent
After=media-server.service # 可选:确保 media-server 先启动
[Service]
Type=simple
ExecStart=/opt/rk3588-agent/rk3588-agent --config /opt/rk3588-agent/agent.config.json
Restart=always
RestartSec=2
```
## 注意事项
1. **首次启动**: 确保配置文件路径正确,特别是模型路径和摄像头配置
2. **权限**: 服务以 root 运行,需要访问 `/dev/rknpu` 设备
3. **依赖**: Agent 可选依赖 media-server可根据需要调整 `After=``Requires=`
4. **日志**: 使用 `journalctl` 查看日志,日志大小由 systemd 管理
## 参考
- [命令.md](../../docs/命令.md) - 开发和部署命令参考
- [API_Device_RemoteMgmt_InterfaceTable.md](../../API_Device_RemoteMgmt_InterfaceTable.md) - Agent API 文档

View File

@ -0,0 +1,271 @@
#!/bin/bash
# RK3588 Media Server & Agent Systemd 服务安装脚本
# 适用于 Orange Pi 5 Plus (RK3588)
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 默认路径
MEDIA_SERVER_BIN="${MEDIA_SERVER_BIN:-$(pwd)/build/media-server}"
AGENT_BIN="${AGENT_BIN:-$(pwd)/agent/rk3588-agent_linux_arm64}"
MEDIA_SERVER_CONFIG="${MEDIA_SERVER_CONFIG:-$(pwd)/configs/sample_cam1.json}"
AGENT_CONFIG="${AGENT_CONFIG:-$(pwd)/agent/agent_cam1.config.json}"
INSTALL_DIR="/opt"
SERVICE_DIR="/etc/systemd/system"
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ RK3588 Media Server & Agent Systemd 安装 ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
echo ""
# 检查 root 权限
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
exit 1
fi
# 检查 systemd
if ! command -v systemctl &> /dev/null; then
echo -e "${RED}错误: 未找到 systemctl此系统可能不支持 systemd${NC}"
exit 1
fi
# 函数:安装 media-server
install_media_server() {
echo -e "${YELLOW}[1/6] 安装 Media Server...${NC}"
# 检查二进制文件
if [ ! -f "$MEDIA_SERVER_BIN" ]; then
echo -e "${RED}错误: 未找到 media-server 二进制文件: $MEDIA_SERVER_BIN${NC}"
echo "请确认已编译,或设置 MEDIA_SERVER_BIN 环境变量"
return 1
fi
# 创建目录
mkdir -p "$INSTALL_DIR/rk3588-media-server"/{bin,lib,etc,logs}
# 复制二进制文件
cp "$MEDIA_SERVER_BIN" "$INSTALL_DIR/rk3588-media-server/bin/"
chmod +x "$INSTALL_DIR/rk3588-media-server/bin/media-server"
# 复制依赖库(如果有)
if [ -d "$(dirname $MEDIA_SERVER_BIN)/../lib" ]; then
cp -r "$(dirname $MEDIA_SERVER_BIN)/../lib"/* "$INSTALL_DIR/rk3588-media-server/lib/" 2>/dev/null || true
fi
# 复制或创建配置文件
if [ -f "$MEDIA_SERVER_CONFIG" ]; then
cp "$MEDIA_SERVER_CONFIG" "$INSTALL_DIR/rk3588-media-server/etc/media-server.json"
echo -e "${GREEN}${NC} 配置文件: $INSTALL_DIR/rk3588-media-server/etc/media-server.json"
else
echo -e "${YELLOW}⚠ 未找到配置文件,请手动创建: $INSTALL_DIR/rk3588-media-server/etc/media-server.json${NC}"
fi
# 安装服务文件
cp "$(dirname $0)/media-server.service" "$SERVICE_DIR/"
echo -e "${GREEN}${NC} Media Server 安装完成"
}
# 函数:安装 agent
install_agent() {
echo -e "${YELLOW}[2/6] 安装 RK3588 Agent...${NC}"
# 检查二进制文件
if [ ! -f "$AGENT_BIN" ]; then
# 尝试其他可能的名称
if [ -f "$(dirname $AGENT_BIN)/rk3588-agent" ]; then
AGENT_BIN="$(dirname $AGENT_BIN)/rk3588-agent"
else
echo -e "${YELLOW}⚠ 未找到 Agent 二进制文件,跳过 Agent 安装${NC}"
return 0
fi
fi
# 创建目录
mkdir -p "$INSTALL_DIR/rk3588-agent"/{logs,models}
# 复制二进制文件
cp "$AGENT_BIN" "$INSTALL_DIR/rk3588-agent/rk3588-agent"
chmod +x "$INSTALL_DIR/rk3588-agent/rk3588-agent"
# 复制或创建配置文件
if [ -f "$AGENT_CONFIG" ]; then
cp "$AGENT_CONFIG" "$INSTALL_DIR/rk3588-agent/agent.config.json"
echo -e "${GREEN}${NC} 配置文件: $INSTALL_DIR/rk3588-agent/agent.config.json"
else
echo -e "${YELLOW}⚠ 未找到 Agent 配置文件,请手动创建${NC}"
fi
# 安装服务文件
cp "$(dirname $0)/rk3588-agent.service" "$SERVICE_DIR/"
echo -e "${GREEN}${NC} RK3588 Agent 安装完成"
}
# 函数:重载 systemd
reload_systemd() {
echo -e "${YELLOW}[3/6] 重载 systemd...${NC}"
systemctl daemon-reload
echo -e "${GREEN}${NC} systemd 已重载"
}
# 函数:启动服务
start_services() {
echo -e "${YELLOW}[4/6] 启动服务...${NC}"
# 启动 media-server
if [ -f "$SERVICE_DIR/media-server.service" ]; then
echo " 启动 media-server..."
systemctl enable media-server
systemctl start media-server
sleep 2
if systemctl is-active --quiet media-server; then
echo -e "${GREEN}${NC} media-server 运行中"
else
echo -e "${RED}${NC} media-server 启动失败,请检查日志"
fi
fi
# 启动 agent
if [ -f "$SERVICE_DIR/rk3588-agent.service" ] && [ -f "$INSTALL_DIR/rk3588-agent/rk3588-agent" ]; then
echo " 启动 rk3588-agent..."
systemctl enable rk3588-agent
systemctl start rk3588-agent
sleep 1
if systemctl is-active --quiet rk3588-agent; then
echo -e "${GREEN}${NC} rk3588-agent 运行中"
else
echo -e "${RED}${NC} rk3588-agent 启动失败,请检查日志"
fi
fi
}
# 函数:显示状态
show_status() {
echo -e "${YELLOW}[5/6] 服务状态...${NC}"
echo ""
if [ -f "$SERVICE_DIR/media-server.service" ]; then
echo -e "${BLUE}Media Server:${NC}"
systemctl status media-server --no-pager | head -5
echo ""
fi
if [ -f "$SERVICE_DIR/rk3588-agent.service" ]; then
echo -e "${BLUE}RK3588 Agent:${NC}"
systemctl status rk3588-agent --no-pager | head -5
echo ""
fi
}
# 函数:显示使用说明
show_usage() {
echo -e "${YELLOW}[6/6] 使用说明${NC}"
echo ""
echo "┌─────────────────────────────────────────────────────────────┐"
echo "│ 管理命令 │"
echo "├─────────────────────────────────────────────────────────────┤"
echo "│ 查看状态 │"
echo "│ systemctl status media-server │"
echo "│ systemctl status rk3588-agent │"
echo "│ │"
echo "│ 启动/停止/重启 │"
echo "│ systemctl start media-server │"
echo "│ systemctl stop media-server │"
echo "│ systemctl restart media-server │"
echo "│ │"
echo "│ 开机自启 │"
echo "│ systemctl enable media-server # 启用 │"
echo "│ systemctl disable media-server # 禁用 │"
echo "│ │"
echo "│ 查看日志 │"
echo "│ journalctl -u media-server -f # 实时跟踪 │"
echo "│ journalctl -u media-server -n 100 # 最近100行 │"
echo "│ journalctl -u rk3588-agent -f │"
echo "│ │"
echo "│ 文件位置 │"
echo "│ 安装目录: /opt/rk3588-media-server/ │"
echo "│ 配置文件: /opt/rk3588-media-server/etc/media-server.json │"
echo "│ Agent目录: /opt/rk3588-agent/ │"
echo "│ Agent配置: /opt/rk3588-agent/agent.config.json │"
echo "└─────────────────────────────────────────────────────────────┘"
}
# 主流程
main() {
# 如果传入了参数,解析环境变量
while [[ $# -gt 0 ]]; do
case $1 in
--media-bin)
MEDIA_SERVER_BIN="$2"
shift 2
;;
--agent-bin)
AGENT_BIN="$2"
shift 2
;;
--media-config)
MEDIA_SERVER_CONFIG="$2"
shift 2
;;
--agent-config)
AGENT_CONFIG="$2"
shift 2
;;
--help|-h)
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " --media-bin <路径> Media Server 二进制文件路径"
echo " --agent-bin <路径> Agent 二进制文件路径"
echo " --media-config <路径> Media Server 配置文件路径"
echo " --agent-config <路径> Agent 配置文件路径"
echo ""
echo "环境变量:"
echo " MEDIA_SERVER_BIN Media Server 二进制文件路径"
echo " AGENT_BIN Agent 二进制文件路径"
echo " MEDIA_SERVER_CONFIG Media Server 配置文件路径"
echo " AGENT_CONFIG Agent 配置文件路径"
exit 0
;;
*)
echo "未知选项: $1"
exit 1
;;
esac
done
echo "安装路径: $INSTALL_DIR"
echo "Media Server: $MEDIA_SERVER_BIN"
echo "Agent: $AGENT_BIN"
echo ""
read -p "确认安装? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "安装已取消"
exit 0
fi
install_media_server
install_agent
reload_systemd
start_services
show_status
show_usage
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ 安装完成! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
}
main "$@"

View File

@ -0,0 +1,40 @@
[Unit]
Description=RK3588 Media Server
Documentation=https://github.com/your-org/OrangePi3588Media
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/opt/rk3588-media-server
ExecStart=/opt/rk3588-media-server/bin/media-server --config /opt/rk3588-media-server/etc/media-server.json
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=30
Restart=on-failure
RestartSec=5
StartLimitInterval=60s
StartLimitBurst=3
# 资源限制
LimitNOFILE=65535
LimitNPROC=4096
# 环境变量
Environment="LD_LIBRARY_PATH=/opt/rk3588-media-server/lib:$LD_LIBRARY_PATH"
# 日志输出
StandardOutput=journal
StandardError=journal
SyslogIdentifier=media-server
# 安全设置(根据实际需求调整)
# NoNewPrivileges=false
# ProtectSystem=false
# ProtectHome=false
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,102 @@
#!/bin/bash
# RK3588 Media Server 快速设置脚本
# 适用于开发板直接编译部署
set -e
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}========== RK3588 Media Server 快速设置 ==========${NC}"
echo ""
# 检测是否在 Orange Pi 上
if [[ "$(uname -m)" != "aarch64" ]]; then
echo "警告: 当前不是 ARM64 架构,此脚本适用于 RK3588 开发板"
read -p "是否继续? (y/N): " -n 1 -r
echo
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi
# 检查 sudo
if [ "$EUID" -ne 0 ]; then
echo "请使用 sudo 运行"
exit 1
fi
PROJECT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
BUILD_DIR="$PROJECT_DIR/build"
echo "项目目录: $PROJECT_DIR"
echo ""
# 步骤1: 检查编译
echo "[1/4] 检查编译状态..."
if [ ! -f "$BUILD_DIR/media-server" ]; then
echo "未找到编译好的 media-server开始编译..."
echo ""
echo "CMake 配置:"
cmake -S "$PROJECT_DIR" -B "$BUILD_DIR" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTS=OFF \
-DBUILD_SAMPLES=ON \
-DRK3588_ENABLE_FFMPEG=ON \
-DRK3588_ENABLE_MPP=ON \
-DRK3588_ENABLE_RGA=ON \
-DRK3588_ENABLE_ZLMEDIAKIT=ON \
-DRK3588_ENABLE_RKNN=ON \
-DRK_ZLMK_API_LIB_PATH="$PROJECT_DIR/third_party/rknpu2/examples/3rdparty/zlmediakit/aarch64/libmk_api.so" \
-DRK_ZLMEDIAKIT_INCLUDE_DIR="$PROJECT_DIR/third_party/rknpu2/examples/3rdparty/zlmediakit/include"
echo ""
echo "开始编译(使用 $(nproc) 线程)..."
cmake --build "$BUILD_DIR" -j$(nproc)
else
echo -e "${GREEN}${NC} 已编译"
fi
echo ""
# 步骤2: 安装 systemd 服务
echo "[2/4] 安装 Systemd 服务..."
"$(dirname "$0")/install-systemd.sh" \
--media-bin "$BUILD_DIR/media-server" \
--media-config "$PROJECT_DIR/configs/sample_cam1.json" \
--agent-bin "$PROJECT_DIR/agent/rk3588-agent_linux_arm64" \
--agent-config "$PROJECT_DIR/agent/agent_cam1.config.json"
echo ""
# 步骤3: 检查端口
echo "[3/4] 检查端口..."
for port in 9000 8554 8555 9100; do
if ss -tln | grep -q ":$port "; then
echo -e " ${GREEN}${NC} 端口 $port 监听正常"
else
echo " 端口 $port 未监听"
fi
done
echo ""
# 步骤4: 测试
echo "[4/4] 快速测试..."
sleep 2
if systemctl is-active --quiet media-server; then
echo -e "${GREEN}Media Server 运行正常${NC}"
echo ""
echo "测试地址:"
IP=$(hostname -I | awk '{print $1}')
echo " HLS: http://$IP:9000/hls/cam1/index.m3u8"
echo " RTSP: rtsp://$IP:8555/live/cam1"
else
echo "Media Server 可能未正常启动,请检查日志:"
echo " journalctl -u media-server -n 20"
fi
echo ""
echo -e "${GREEN}设置完成!${NC}"
echo ""
echo "常用命令:"
echo " 查看状态: $(dirname "$0")/status.sh"
echo " 查看日志: journalctl -u media-server -f"
echo " 重启服务: systemctl restart media-server"

View File

@ -0,0 +1,40 @@
[Unit]
Description=RK3588 Agent (Management API)
Documentation=https://github.com/your-org/OrangePi3588Media
After=network-online.target media-server.service
Wants=network-online.target
# 如果 agent 依赖 media-server取消下面这行的注释
# Requires=media-server.service
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/opt/rk3588-agent
ExecStart=/opt/rk3588-agent/rk3588-agent --config /opt/rk3588-agent/agent.config.json
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGTERM
TimeoutStopSec=30
Restart=always
RestartSec=2
StartLimitInterval=60s
StartLimitBurst=5
# 资源限制
LimitNOFILE=65535
LimitNPROC=4096
# 日志输出
StandardOutput=journal
StandardError=journal
SyslogIdentifier=rk3588-agent
# 安全设置
# NoNewPrivileges=true
# ProtectSystem=strict
# ProtectHome=true
# ReadWritePaths=/opt/rk3588-agent
[Install]
WantedBy=multi-user.target

82
scripts/systemd/status.sh Normal file
View File

@ -0,0 +1,82 @@
#!/bin/bash
# RK3588 Media Server & Agent 状态查看脚本
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}========== RK3588 Media Server & Agent 状态 ==========${NC}"
echo ""
# 显示系统信息
echo -e "${YELLOW}[系统信息]${NC}"
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo " 运行时间: $(uptime -p 2>/dev/null || uptime)"
echo ""
# NPU 负载
echo -e "${YELLOW}[NPU 负载]${NC}"
if [ -f /sys/kernel/debug/rknpu/load ]; then
cat /sys/kernel/debug/rknpu/load | while read line; do
echo " $line"
done
else
echo " NPU 信息不可用"
fi
echo ""
# Media Server 状态
echo -e "${YELLOW}[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)
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|8554|8555)" | head -3 | while read line; do
echo " $line"
done
else
echo -e " 状态: ${RED}○ 停止${NC}"
fi
echo ""
# Agent 状态
echo -e "${YELLOW}[RK3588 Agent]${NC}"
if systemctl is-active --quiet rk3588-agent 2>/dev/null; then
echo -e " 状态: ${GREEN}● 运行中${NC}"
PID=$(systemctl show --property=MainPID --value rk3588-agent)
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
else
echo -e " 状态: ${RED}○ 停止${NC}"
fi
echo ""
# 日志摘要
echo -e "${YELLOW}[最近日志]${NC}"
echo "Media Server (最后3行):"
journalctl -u media-server --no-pager -n 3 2>/dev/null | tail -3 || echo " 无日志"
echo ""
echo "Agent (最后3行):"
journalctl -u rk3588-agent --no-pager -n 3 2>/dev/null | tail -3 || echo " 无日志"
echo ""
# 操作提示
echo -e "${YELLOW}[管理命令]${NC}"
echo " 重启服务: sudo systemctl restart media-server"
echo " 查看日志: sudo journalctl -u media-server -f"
echo " 查看NPU: sudo watch -n 1 cat /sys/kernel/debug/rknpu/load"

View File

@ -0,0 +1,81 @@
#!/bin/bash
# RK3588 Media Server & Agent Systemd 服务卸载脚本
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}========== RK3588 Media Server & Agent 卸载 ==========${NC}"
echo ""
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}错误: 请使用 sudo 运行${NC}"
exit 1
fi
# 确认
read -p "确定要卸载并停止所有服务? 数据将保留。 (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "卸载已取消"
exit 0
fi
# 停止服务
echo "[1/4] 停止服务..."
systemctl stop media-server 2>/dev/null || true
systemctl stop rk3588-agent 2>/dev/null || true
systemctl disable media-server 2>/dev/null || true
systemctl disable rk3588-agent 2>/dev/null || true
echo -e "${GREEN}${NC} 服务已停止并禁用"
# 删除服务文件
echo "[2/4] 删除服务文件..."
rm -f /etc/systemd/system/media-server.service
rm -f /etc/systemd/system/rk3588-agent.service
systemctl daemon-reload
echo -e "${GREEN}${NC} 服务文件已删除"
# 备份配置
echo "[3/4] 备份配置..."
BACKUP_DIR="/root/rk3588-backup-$(date +%Y%m%d%H%M%S)"
mkdir -p "$BACKUP_DIR"
if [ -f "/opt/rk3588-media-server/etc/media-server.json" ]; then
cp "/opt/rk3588-media-server/etc/media-server.json" "$BACKUP_DIR/"
echo " 已备份 media-server 配置"
fi
if [ -f "/opt/rk3588-agent/agent.config.json" ]; then
cp "/opt/rk3588-agent/agent.config.json" "$BACKUP_DIR/"
echo " 已备份 agent 配置"
fi
echo -e "${GREEN}${NC} 配置已备份到: $BACKUP_DIR"
# 提示删除文件
echo "[4/4] 清理文件..."
echo ""
echo "以下目录需要手动删除(如需完全清理):"
echo " /opt/rk3588-media-server/"
echo " /opt/rk3588-agent/"
echo ""
read -p "是否删除这些目录? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf /opt/rk3588-media-server/
rm -rf /opt/rk3588-agent/
echo -e "${GREEN}${NC} 目录已删除"
else
echo "保留目录,如需删除请手动执行:"
echo " sudo rm -rf /opt/rk3588-media-server/"
echo " sudo rm -rf /opt/rk3588-agent/"
fi
echo ""
echo -e "${GREEN}卸载完成${NC}"
echo "备份位置: $BACKUP_DIR"