# rgbplatform **Repository Path**: kingecg/rgbplatform ## Basic Information - **Project Name**: rgbplatform - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-12 - **Last Updated**: 2026-07-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RGBPlatform GB28181-2022 和 ONVIF 协议视频监控平台,使用 Rust 语言和 tokio 异步框架实现。 [![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) --- ## 功能特性 ### GB28181-2022 协议 - ✅ 设备注册 / 注销(带 Digest 鉴权) - ✅ 设备保活 (Keepalive) - ✅ 设备目录查询(MANSCDP+xml) - ✅ 报警通知 / 订阅 - ✅ 实时视频预览(INVITE / ACK / BYE / INFO 全流程) - ✅ 录像点播回放(支持 Play/Pause/Seek/Speed/Stop) - ✅ PTZ 云台控制(移动/停止/预置位/家园位) - ✅ SIP 信令 UDP / TCP 双传输(可配置) - 🚧 TLS 加密传输(接口已预留) ### ONVIF 协议 - ✅ WS-Discovery 设备发现 - ✅ SOAP 1.1 / 1.2 协议库(含 WS-Addressing) - ✅ RTSP 客户端(OPTIONS / DESCRIBE / SETUP / PLAY / PAUSE / TEARDOWN) - ✅ UDP / Interleaved (TCP) 双传输模式 - ✅ SDP 解析与多 track 控制 - 🚧 Media Service / Events Service / PTZ 控制(基础结构已建) ### 视频流处理 - ✅ **RTP 解包** - PS 流 (GB28181) 完整解析,含 PES 重组、PTS/DTS 解析 - ✅ **PS Parser** - 支持 MPEG-1 / MPEG-2 双格式、PMT 流类型识别 - ✅ **RTSP 客户端** - 自动连接、拉流、帧分发 - ✅ **Protocol Converter** - RTP→PS→ES→Muxer 全链路,含 SPS/PPS 自动注入 - ✅ **Stream Distributor** - 一输入多输出扇出 - ✅ **FFmpeg 集成** - ffmpeg-next H.264 编解码、AVCC 转换、YUV 处理 - ✅ **多格式输出** - FLV (HTTP-FLV)、MP4、HLS 分段 - 🚧 硬件加速 (NVENC/QSV) ### HTTP API (Axum) - ✅ 用户登录与会话鉴权(Bearer Token,服务端会话表) - ✅ 运行时配置读取 / 修改(脱敏返回,改动持久化到配置文件) - ✅ 设备管理(列表 / 详情 / 通道) - ✅ 直播流请求与播放 - ✅ 录像查询(时间范围 / 通道过滤 / 分页) - ✅ 录像回放控制 - ✅ 外部流拉取(RTSP / HTTP) - ✅ PTZ 控制 API - ✅ 报警管理 - ✅ 统计信息 - ✅ OpenAPI / Swagger 文档 ### 存储 - ✅ SQLite 数据库(SQLx 异步 ORM) - 🚧 文件管理 / 分段存储 / 自动清理 --- ## 技术栈 | 组件 | 技术 | 版本 | |------|------|------| | 语言 | Rust | Edition 2021 | | 异步运行时 | Tokio | 1.x (full) | | Web 框架 | Axum | 0.7 | | HTTP 客户端 | reqwest | 0.12 | | WebSocket | tokio-tungstenite | 0.24 | | 日志 | tracing / tracing-subscriber | 0.1 / 0.3 | | 序列化 | serde / serde_json | 1.0 | | XML | quick-xml | 0.37 | | 数据库 | SQLx (SQLite) | 0.8 | | API 文档 | utoipa / utoipa-swagger-ui | 4 / 6 | | 视频编解码 | ffmpeg-next | 8.1 | | 时间 | chrono | 0.4 | --- ## 项目结构 ``` rgbplatform/ ├── scripts/ │ └── build.sh # 一键构建 UI + 后端 ├── src/ │ ├── main.rs # 程序入口 │ ├── lib.rs # 库入口 │ ├── common/ # 公共组件 │ │ ├── config.rs # 配置管理(含 SIP transport 配置) │ │ ├── error.rs # 统一错误类型 │ │ └── logging.rs # 日志初始化 │ ├── gb28181/ # GB28181 协议实现 │ │ ├── sip/ # SIP 协议栈 │ │ │ ├── message.rs # SIP 消息解析 / 构建 │ │ │ ├── transport.rs # SIP 传输层 (UDP / TCP / TlsClient) │ │ │ └── transaction.rs # SIP 事务管理 │ │ ├── device/ # 设备管理 │ │ │ ├── manager.rs # 设备管理器 │ │ │ ├── session.rs # 设备会话 │ │ │ └── ptz.rs # PTZ 控制器 │ │ ├── stream/ # RTP 流处理 │ │ ├── catalog/ # 目录查询 (MANSCDP+xml) │ │ └── playback/ # 录像回放 (INVITE/INFO/BYE) │ ├── onvif/ # ONVIF 协议实现 │ │ ├── soap.rs # SOAP 协议库 │ │ ├── rtsp/ # RTSP 客户端 │ │ ├── discovery/ # WS-Discovery │ │ ├── device/ # Device Service │ │ ├── media/ # Media Service │ │ ├── ptz/ # PTZ Service │ │ └── events/ # Events Service │ ├── stream/ # 视频流处理 │ │ ├── rtp/ # RTP 解包 + PS 解析 │ │ ├── ffmpeg/ # FFmpeg 集成 │ │ ├── output/ # 输出 muxer (FLV/MP4/HLS) │ │ ├── input/ # RTSP 输入 │ │ ├── converter/ # 协议转换器 │ │ ├── distributor/ # 流分发器 │ │ └── session/ # 流会话管理 │ ├── api/ # HTTP API │ │ ├── handlers/ # 请求处理 │ │ ├── models/ # 数据模型 │ │ └── middleware/ # 中间件 │ └── storage/ # 录像存储 (SQLite) ├── doc/ # 设计文档 │ ├── architecture.md # 总体架构 │ ├── require.md # 需求说明 │ ├── tasks.md # 任务分解 (M1-M5) │ ├── design/ # 详细设计 │ └── GBT+28181-2022.pdf # GB28181 标准 ├── config.yaml # 配置文件 (YAML) ├── Cargo.toml # 项目配置 └── README.md # 本文件 ``` --- ## 快速开始 ### 环境要求 - Rust 1.70+(推荐 stable) - Node.js 18+ 与 npm(仅构建/运行 UI 时需要) - SQLite 3.x - FFmpeg 开发库(可选,仅在使用 ffmpeg feature 时) ### 编译 一站式构建 UI 与后端: ```bash # Release 模式(推荐生产部署) BUILD=release ./scripts/build.sh # 或 Debug 模式 ./scripts/build.sh ``` `scripts/build.sh` 依次执行: 1. `cd web && npm ci && npm run build` → 产出 `web/dist/` 2. `cargo build [--release]` → 产出 `target//rgbplatform` 等效手动作业: ```bash cd web && npm ci && npm run build # 构建前端 cd .. && cargo build --release # 构建后端 ``` 跳过某一步:`SKIP_UI=1 ./scripts/build.sh` 或 `SKIP_RUST=1 ./scripts/build.sh`。 仅编译后端(不构建 UI): ```bash cargo build --release cargo test --lib ``` ### 启动 ```bash # 默认(读取 ./config.yaml,从 ./web/dist 加载 UI) ./target/release/rgbplatform # 显式指定配置路径(推荐生产) ./target/release/rgbplatform --config /etc/rgbplatform/config.yaml ./target/release/rgbplatform -c ./configs/prod.yaml # 通过环境变量 RGBPLATFORM_CONFIG=/etc/rgbplatform/config.yaml ./target/release/rgbplatform # 自定义 UI 目录(CLI 优先级最高) ./target/release/rgbplatform --web-dir /opt/rgbplatform/dist RGBPLATFORM_WEB_DIR=/opt/rgbplatform/dist ./target/release/rgbplatform # 完全禁用 UI(只暴露 API),传空字符串 ./target/release/rgbplatform --web-dir "" ``` UI 目录解析顺序:`--web-dir ` > `RGBPLATFORM_WEB_DIR` > `config.web.dir` > `./web/dist`。 可通过 `--web-dir ""` 或在 config 中设置 `web.enabled=false` 来禁用 UI 托管。 配置路径解析顺序:`--config ` > `RGBPLATFORM_CONFIG` > `./config.yaml`。 更多选项: ```bash ./target/release/rgbplatform --help # 帮助 ./target/release/rgbplatform --version # 版本 ``` ### 安装到系统(systemd) `scripts/install.sh` 把构建产物(`./dist/`)安装到 `/usr/local/rgbplatform` 并注册为 systemd 服务: ```bash # 1) 先构建产物 ./scripts/build.sh # 2) 安装并启动 sudo ./scripts/install.sh # 安装 + 启用 + 启动 sudo ./scripts/install.sh --no-start # 只安装、启用,不立即启动 sudo ./scripts/install.sh --prefix /opt/rgbplatform sudo ./scripts/install.sh --user rgbplatform --service rgbplatform # 3) 卸载(停服务、删 unit、删安装目录、删服务用户) sudo ./scripts/install.sh --uninstall ``` 默认布局: ``` /usr/local/rgbplatform/ ├── bin/rgbplatform # 二进制 ├── etc/config.yaml # 配置(重装保留用户编辑) ├── data/ # SQLite 数据库(重装保留) ├── web/ # UI 静态文件(每次重装刷新) └── logs/ # 服务自有日志 ``` systemd unit 默认落在 `/etc/systemd/system/rgbplatform.service`,带 hardening (`ProtectSystem=strict`、`PrivateTmp`、`NoNewPrivileges` 等),`data/` 和 `logs/` 是 service 可写的,其余安装目录只读。`ReadWritePaths` 写死后能保证 二进制和配置不会被 service 进程意外改动。 常用运维: ```bash systemctl status rgbplatform # 看运行状态 journalctl -u rgbplatform -f # 实时日志 sudo systemctl restart rgbplatform # 改完配置后重启 curl http://localhost:8080/api/v1/health ``` `scripts/install.sh` 是幂等的:再跑一次会保留 `etc/config.yaml` 和 `data/` 里已有的内容(数据库不会被覆盖),只刷新 `bin/` 和 `web/`。 ### 配置 编辑 `config.yaml` 配置文件: ```yaml server: host: "0.0.0.0" port: 8080 auth: enabled: true # 启用后,除公开接口外所有 API 都需登录获取 Bearer Token username: "admin" password: "admin" web: enabled: true dir: "./web" gb28181: server_id: "34020000002000000001" realm: "RGBPlatform" local_ip: "192.168.1.100" sip_port: 5060 media_port_start: 58200 media_port_end: 58300 register_timeout: 3600 keepalive_interval: 30 password: "12345678" # 所有设备共用的统一 SIP 认证密码(Digest) transport: tcp_enabled: false tcp_port: 5060 tls_enabled: false max_clients: 256 connection_timeout: 120 outbound_enabled: false outbound_timeout: 10 onvif: enabled: true device_port: 8081 discovery_port: 3702 stream: output_dir: "./streams" hls_segment_size: 10 flv_chunk_size: 4096 storage: enabled: false path: "./recordings" max_size_gb: 1000 retention_days: 30 database: path: "./data/rgbplatform.db" logging: level: "info" format: "json" ``` ### 运行 ```bash # 运行二进制 cargo run --release # 或直接运行编译后的二进制 ./target/release/rgbplatform ``` 启动后可访问: - **Web 管理控制台 (UI)**: `http://localhost:8080/` — Vue SPA,含登录、设备/通道/告警/PTZ、系统配置等页面。当 `auth.enabled: true` 时,未登录访问任意页面都会被路由守卫重定向到 `/login`。 - API 服务: `http://localhost:8080/api/v1/...` - Swagger UI: `http://localhost:8080/swagger-ui/` > UI 由后端进程从 `web.dir` 直接提供,Vue Router 使用 `createWebHistory`(path 模式),因此 `/dashboard`、`/ptz/...` 等深路径会自动回退到 `index.html`。如果通过 Nginx/Caddy 等前置代理托管 UI,请同步配置 SPA fallback(`try_files $uri /index.html`)。 --- ## SIP 信令传输 平台同时支持 SIP over **UDP** 和 SIP over **TCP**,二者可独立配置。 ### 配置示例 启用 TCP 监听(与 UDP 并存): ```json "transport": { "tcp_enabled": true, "tcp_port": 5060, "tls_enabled": false, "max_clients": 256, "connection_timeout": 120, "outbound_enabled": true, "outbound_timeout": 10 } ``` ### 关键能力 | 能力 | UDP | TCP | TLS | |------|:---:|:---:|:---:| | 设备注册/注销 | ✅ | ✅ | 🚧 | | 实时视频 INVITE | ✅ | ✅ | 🚧 | | 录像回放 INVITE | ✅ | ✅ | 🚧 | | MANSCDP 消息 | ✅ | ✅ | 🚧 | | 主动出站连接 | N/A | ✅ | 🚧 | | Content-Length 帧化 | 不需要 | ✅ | 🚧 | **UDP**: 默认传输,简单可靠,适合局域网内 GB28181 设备。 **TCP**: 适合跨网段、防火墙严格限制的环境;通过 Content-Length 头进行消息帧化(RFC 3261 §18),单连接可承载多请求。 **TLS**: 加密 TCP 传输。证书路径通过 `tls_cert` / `tls_key` 配置(需 PEM 格式);接口已预留,待启用 `rustls` 依赖后即可激活。 --- ## API 接口 所有响应采用统一 JSON 格式: ```json { "code": 0, "message": "success", "data": { ... } } ``` 错误响应: ```json { "code": 404, "message": "Device not found", "data": null } ``` ### 认证与会话 当 `auth.enabled: true` 时,除以下**公开接口**外,所有 API 都需要携带登录后获得的 Bearer Token:`GET /api/v1/health`、`GET /api/v1/metrics`、`POST /api/v1/auth/login` 以及 ONVIF SOAP 服务端点。UI 静态资源始终公开(SPA 先加载再带凭证调 API)。 ``` POST /api/v1/auth/login # 登录,返回会话 Token POST /api/v1/auth/logout # 登出,使当前 Token 失效 ``` **登录**:账号密码取自 `auth.username` / `auth.password`。 ```bash curl -X POST http://localhost:8080/api/v1/auth/login \ -H 'Content-Type: application/json' \ -d '{"username":"admin","password":"admin"}' ``` 成功响应(`expires_in` 为 Token 有效期,单位秒): ```json { "code": 0, "message": "success", "data": { "token": "43c93500-...-9f2fae73f1ff", "expires_in": 3600, "username": "admin" } } ``` 账号密码错误时返回 HTTP 401 与 `{ "code": 401, "message": "用户名或密码错误", "data": null }`。 **携带 Token 访问受保护接口**: ```bash curl http://localhost:8080/api/v1/devices \ -H "Authorization: Bearer " ``` **登出**(服务端从会话表移除该 Token,随后该 Token 立即失效): ```bash curl -X POST http://localhost:8080/api/v1/auth/logout \ -H "Authorization: Bearer " ``` > 会话 Token 保存在服务端内存,**服务重启后全部失效**,需重新登录。 > 中间件同时兼容 HTTP Basic(`Authorization: Basic `)与 > `X-API-Key: `,方便脚本与 Swagger 调试。 ### 健康检查 ``` GET /api/v1/health ``` ### 设备管理 ``` GET /api/v1/devices # 获取设备列表 GET /api/v1/devices/{id} # 获取设备详情 GET /api/v1/devices/{id}/channels # 获取设备通道 ``` ### 直播流 ``` POST /api/v1/devices/{id}/live # 请求直播流 GET /api/v1/live/{stream_id} # 获取直播流 DELETE /api/v1/live/{stream_id} # 停止直播流 GET /api/v1/live/{stream_id}/status # 获取流状态(比特率、帧率、分辨率) ``` ### 录像 ``` GET /api/v1/devices/{id}/recordings # 查询录像(支持时间/通道过滤) GET /api/v1/recordings/{id} # 获取录像文件详情 POST /api/v1/recordings/{id}/playback # 开始回放 POST /api/v1/playback/{id}/control # 回放控制(play/pause/seek/speed/stop) ``` ### 录像回放控制 请求体示例: ```json { "action": "play", "speed": 1.0 } { "action": "pause" } { "action": "seek", "position": 120 } { "action": "speed", "speed": 2.0 } { "action": "stop" } ``` ### PTZ 云台控制 ``` POST /api/v1/devices/{device_id}/channels/{channel_id}/ptz/move # 连续移动 POST /api/v1/devices/{device_id}/channels/{channel_id}/ptz/stop # 停止 POST /api/v1/devices/{device_id}/channels/{channel_id}/ptz/home # 回归原点 POST /api/v1/devices/{device_id}/channels/{channel_id}/ptz/preset/{n} # 移动到预置位 POST /api/v1/devices/{device_id}/channels/{channel_id}/ptz/preset # 设置预置位 ``` 请求体: ```json { "pan": 0.5, // 水平速度 (-1.0 ~ 1.0) "tilt": 0.5, // 垂直速度 (-1.0 ~ 1.0) "zoom": 0.0, // 变倍速度 (-1.0 ~ 1.0) "timeout": 5.0 // 可选,超时(秒) } ``` ### 外部流拉取 ``` POST /api/v1/stream/pull # 拉取外部流(支持 RTSP/HTTP) DELETE /api/v1/stream/pull/{stream_id} # 停止拉流 ``` ### 报警 ``` GET /api/v1/alarms # 查询报警列表 GET /api/v1/alarms/{alarm_id} # 报警详情 PUT /api/v1/alarms/{alarm_id}/status # 更新报警状态 GET /api/v1/alarms/stats # 报警统计 ``` ### 统计 ``` GET /api/v1/stats # 系统统计(设备 / 流 / 存储) ``` ### 运行时配置 在线读取与修改配置,无需手工编辑 `config.yaml`。需登录后携带 Bearer Token 访问。 ``` GET /api/v1/config # 读取当前配置(密码字段脱敏为空) PUT /api/v1/config # 修改配置(合并 + 校验 + 持久化到配置文件) ``` **可修改的运行时安全子集**:`auth`、`gb28181`、`onvif`、`logging`、`storage`、`stream`。 需重启进程才能生效的关键项(`server`、`database`、`web`、`redis`)**不开放**在线修改。 `PUT` 请求体只需包含要修改的段(其余段保持不变)。**密码字段留空则保留原值**, 因此可以直接把 `GET /api/v1/config` 拿到的脱敏配置改动后回传,而不必重新填写密码: ```bash # 仅调整日志级别,其余配置(含各处密码)保持不变 curl -X PUT http://localhost:8080/api/v1/config \ -H "Authorization: Bearer " \ -H 'Content-Type: application/json' \ -d '{ "logging": { "level": "debug", "format": "json" } }' ``` 成功后返回脱敏的最新配置,并把完整配置写回启动时使用的配置文件(`--config` 指定的路径)。 > ⚠️ 端口、SIP 传输方式等改动会写入配置文件,但**需重启服务后才实际生效**; > 账号密码、GB28181 统一密码、日志级别、存储/流参数等即时生效。 > Web 管理控制台的「系统配置」页即基于这两个接口实现。 --- ## 架构设计 ### 协议栈分层 ``` ┌─────────────────────────────────────────────────────────┐ │ HTTP API (Axum) │ ├─────────────────────────────────────────────────────────┤ │ GB28181 │ ONVIF │ WebSocket │ │ ├─ SIP/UDP,TCP,TLS │ ├─ SOAP │ ├─ /ws │ │ ├─ MANSCDP+xml │ ├─ WS-Discov │ └─ 帧推送 │ │ ├─ RTP/RTCP │ └─ RTSP │ │ │ └─ 报警订阅 │ │ │ ├─────────────────────────────────────────────────────────┤ │ Stream Distributor (一输入多输出) │ ├─────────────────────────────────────────────────────────┤ │ PS Parser │ Protocol Converter │ RTSP Client │ ├─────────────────────────────────────────────────────────┤ │ FFmpeg 集成(编解码 / 转码) │ ├─────────────────────────────────────────────────────────┤ │ FLV Muxer │ MP4 Muxer │ HLS Muxer │ └─────────────────────────────────────────────────────────┘ ``` ### 关键流程 **实时视频点播**: ``` 客户端 → HTTP API → SIP INVITE → 设备 设备 → SIP 200 OK (SDP) → API 客户端 → ACK → 设备 设备 → RTP (PS stream) → UDP/TCP → PS Parser → Converter → Muxer → HTTP-FLV/WS ``` **录像回放**: ``` 客户端 → HTTP API → SIP INVITE (含 t= 时间范围) → 设备 设备 → SIP 200 OK → API (注册 PlaybackSession) 客户端 → POST /control {action: "play|pause|seek|speed"} → SIP INFO → 设备 客户端 → DELETE /playback/{id} → SIP BYE → 设备 ``` **目录查询**: ``` API → SIP MESSAGE (Query Catalog) → 设备 设备 → SIP MESSAGE (Response 含 Item 列表) → API API → 解析 MANSCDP+xml → 更新 DeviceManager ``` --- ## 任务进度 详细任务分解见 [doc/tasks.md](doc/tasks.md)。 ### 里程碑状态 | 里程碑 | 状态 | 任务数 | 完成率 | |--------|------|--------|--------| | **M1** 基础框架 | ✅ 完成 | 4 / 4 | 100% | | **M2** GB28181 核心 | ✅ 完成 | 8 / 8 | 100% | | **M3** 流处理 | ✅ 完成 | 9 / 9 | 100% | | **M4** API 与 ONVIF | 🚧 进行中 | 6 / 9 | 67% | | **M5** 测试与完善 | ⏳ 未开始 | 0 / 4 | 0% | ### M2 已完成(GB28181 核心) - 设备注册/注销(含 Digest 鉴权) - 设备保活(MESSAGE/Notify/Keepalive) - 目录查询(MANSCDP Query/Response 协议) - 报警通知 - 实时视频 INVITE 全流程 - 录像回放(INVITE/INFO/BYE 完整链路) - PTZ 控制(4 字节 PTZCmd + SIP INFO) - SIP BYE / MESSAGE / INFO 处理器 ### M3 已完成(流处理) - FFmpeg 集成 - 流会话管理 - FLV / MP4 / HLS 输出 - **PS Parser**(MPEG-1 / MPEG-2 双格式,PES 重组,PTS/DTS 解析) - **RTSP 客户端**(DESCRIBE/SETUP/PLAY/PAUSE/TEARDOWN) - **Protocol Converter**(RTP→PS→ES→Muxer 全链路) - **Stream Distributor**(一输入多输出扇出) --- ## 测试 ```bash # 运行所有单元测试 cargo test --lib # 运行特定模块测试 cargo test --lib gb28181 cargo test --lib stream cargo test --lib onvif # 显示测试输出 cargo test --lib -- --nocapture ``` 当前测试覆盖:**65 个单元测试**,全部通过 ✅ --- ## 文档 更多详细信息请参考: - [架构设计](doc/architecture.md) - [需求说明](doc/require.md) - [任务分解](doc/tasks.md) - 设计文档:[doc/design/](doc/design/) - GB28181 设计 - ONVIF 设计 - 流处理设计 - API 设计 --- ## 协议参考 - [GB/T 28181-2022](doc/GBT+28181-2022.pdf) — 安全防范视频监控联网系统信息传输、交换、控制技术要求 - [ONVIF Core Specification](https://www.onvif.org/specs/) — 开放网络视频接口论坛规范 - RFC 3261 — SIP: Session Initiation Protocol - RFC 2326 — RTSP: Real Time Streaming Protocol - ISO/IEC 13818-1 — MPEG-2 Systems (PS/PES) --- ## 贡献 欢迎提交 Issue 和 Pull Request。 开发流程建议: 1. 从 `master` 分支创建特性分支 2. 提交前运行 `cargo test --lib` 确保所有测试通过 3. 遵循 Rust 标准格式(`cargo fmt`) 4. 提交前运行 `cargo clippy` 检查 --- ## License MIT License Copyright (c) RGBPlatform Team