# todd-gvideo **Repository Path**: c-java-father/todd-gvideo ## Basic Information - **Project Name**: todd-gvideo - **Description**: video test - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-16 - **Last Updated**: 2026-07-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GST GVideo Service 基于 Go (Gin) 的视频流服务,提供 RTSP 拉流、GB28181 国标设备管理、录像管理等功能。 ## 项目说明 - **服务端口**: `8081` - **Monibuca 地址**: `http://192.168.0.188:8080`(可在 `config.yaml` 中修改) --- ## RTSP 品牌编码 | brand | 品牌 | URL 格式 | |-------|------|---------| | `1` | 海康威视(含 OEM) | `rtsp://user:pass@ip:554/Streaming/Channels/XY` | | `2` | 大华(Dahua) | `rtsp://user:pass@ip:554/cam/realmonitor?channel=X&subtype=Y` | | `3` | 宇视-旧 | `rtsp://user:pass@ip:554/videoX` | | `4` | 宇视-新 | `rtsp://user:pass@ip:554/unicast/cX/sY/live` | | `5` | 天地伟业-旧 | `rtsp://user:pass@ip:554/X/Y` | | `6` | 天地伟业-新 | `rtsp://user:pass@ip:554/live/chX_Y` | ### 码流类型(streamType) | streamType | 含义 | 适用品牌 | |-----------|------|---------| | `main`(默认) | 主码流 | 全部品牌 | | `sub` | 子码流 | 全部品牌 | | `third` | 三码流 | **仅海康(brand=1)和宇视-旧(brand=3)支持** | **品牌对三码流的支持情况:** | brand | 品牌 | 主码流 | 子码流 | 三码流 | |-------|------|--------|--------|--------| | `1` | 海康 | 支持 | 支持 | **支持** | | `2` | 大华 | 支持 | 支持 | 不支持 | | `3` | 宇视-旧 | 支持 | 支持 | **支持** | | `4` | 宇视-新 | 支持 | 支持 | 不支持 | | `5` | 天地伟业-旧 | 支持 | 支持 | 不支持 | | `6` | 天地伟业-新 | 支持 | 支持 | 不支持 | > **注意**:传入 `third` 时,不支持三码流的品牌会自动降级为**子码流**。 ### 默认值 | 字段 | 为空时的默认值 | |------|---------------| | `port` | `554` | | `channel` | `1` | | `streamType` | `main` | --- ## 接口列表 | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/api/video/pull` | 拉流(RTSP / 国标),返回 HTTP/WS/WebRTC 播放链接 | | `POST` | `/api/video/heartbeat` | 心跳(30秒发送一次,保持流存活) | | `POST` | `/api/video/stop` | 停止流 | | `GET` | `/api/video/gb/devices?status=-1` | 国标设备列表(-1=全部, 0=离线, 1=在线) | | `GET` | `/api/video/gb/devices/{deviceId}/channels` | 国标设备通道列表 | | `POST` | `/api/video/record/start` | 开始录制(检查流状态并返回录制信息) | | `POST` | `/api/video/record/stop` | 停止录制任务 | | `GET` | `/api/video/record/recording` | 正在录制的流列表 | | `GET` | `/api/video/record/list` | 历史录像列表(需配置数据库 DSN) | | `GET` | `/api/video/record/catalog` | 录像目录(按流路径聚合) | | `POST` | `/api/video/record/delete` | 删除录像 | | `GET` | `/api/video/record/play` | 录像回放播放地址 | --- ## 请求示例 ### 1. RTSP 拉流 **海康威视(brand=1)** ```bash curl -X POST http://localhost:8081/api/video/pull \ -H "Content-Type: application/json" \ -d '{ "deviceId": "cam001", "linkWay": "rtsp", "brand": 1, "ip": "192.168.1.100", "port": "554", "channel": "1", "streamType": "main", "user": "admin", "password": "12345" }' ``` **大华(brand=2)** ```bash curl -X POST http://localhost:8081/api/video/pull \ -H "Content-Type: application/json" \ -d '{ "deviceId": "cam002", "linkWay": "rtsp", "brand": 2, "ip": "192.168.1.101", "channel": "1", "streamType": "sub", "user": "admin", "password": "12345" }' ``` **宇视-新(brand=4)** ```bash curl -X POST http://localhost:8081/api/video/pull \ -H "Content-Type: application/json" \ -d '{ "deviceId": "cam004", "linkWay": "rtsp", "brand": 4, "ip": "192.168.1.103", "channel": "1", "user": "admin", "password": "admin" }' ``` **海康三码流(brand=1, streamType=third)** ```bash curl -X POST http://localhost:8081/api/video/pull \ -H "Content-Type: application/json" \ -d '{ "deviceId": "cam005", "linkWay": "rtsp", "brand": 1, "ip": "192.168.1.104", "channel": "2", "streamType": "third", "user": "admin", "password": "12345" }' ``` **返回示例**: ```json { "code": 0, "message": "success", "data": { "flvUrl": "http://192.168.0.188:8080/flv/live/video_cam001", "wsFlvUrl": "ws://192.168.0.188:8080/flv/live/video_cam001", "webrtcUrl": "http://192.168.0.188:8080/webrtc/live/video_cam001", "hlsUrl": "http://192.168.0.188:8080/hls/live/video_cam001.m3u8", "rtmpUrl": "rtmp://192.168.0.188:1935/live/video_cam001", "streamPath": "live/video_cam001" } } ``` ### 2. 国标(GB28181)拉流 国标设备无需主动拉流,Monibuca 通过 `onsub.pull` 自动处理,直接返回播放地址即可。 ```bash curl -X POST http://localhost:8081/api/video/pull \ -H "Content-Type: application/json" \ -d '{ "deviceId": "gb001", "linkWay": "gb28181", "code": "34020000001320000005", "gbChannel": "34020000001320000001", "brand": 1 }' ``` **返回示例**: ```json { "code": 0, "message": "success", "data": { "flvUrl": "http://192.168.0.188:8080/flv/34020000002000000002/34020000002000000001.flv", "wsFlvUrl": "ws://192.168.0.188:8080/flv/34020000002000000002/34020000002000000001.flv", "webrtcUrl": "http://192.168.0.188:8080/webrtc/34020000002000000002/34020000002000000001", "hlsUrl": "http://192.168.0.188:8080/hls/34020000002000000002/34020000002000000001.m3u8", "rtmpUrl": "rtmp://192.168.0.188:1935/34020000002000000002/34020000002000000001", "streamPath": "34020000002000000002/34020000002000000001" } } ``` ### 3. 心跳(保持流存活) 播放期间每 **30 秒** 发送一次心跳,超过 **90 秒** 未收到心跳后端将自动停止该流。 ```bash curl -X POST http://localhost:8081/api/video/heartbeat \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001" }' ``` **前端集成示例**(JavaScript): ```javascript // 每 30 秒心跳 const heartbeatTimer = setInterval(() => { fetch('/api/video/heartbeat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ streamPath: 'live/video_cam001' }) }); }, 30000); // 页面关闭前发送停止 window.addEventListener('beforeunload', () => { clearInterval(heartbeatTimer); navigator.sendBeacon('/api/video/stop', JSON.stringify({ streamPath: 'live/video_cam001' })); }); ``` ### 4. 停止流 #### RTSP 停止 ```bash curl -X POST http://localhost:8081/api/video/stop \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001" }' ``` #### 国标(GB28181)停止 国标流同样需要停止,调用方式与 RTSP **完全一致**。停止时后端会通知 Monibuca 向设备发送 **SIP BYE**,设备收到后停止 RTP 推流。 ```bash curl -X POST http://localhost:8081/api/video/stop \ -H "Content-Type: application/json" \ -d '{ "streamPath": "34020000001320000005/34020000001320000001" }' ``` | | RTSP | GB28181 | |--|------|---------| | **停止机制** | 断开 Pull Proxy 的 RTSP 连接 | 发送 SIP BYE 终止设备推流 | | **stop 接口** | 相同 | 相同 | | **不停止的后果** | Monibuca 持续从摄像头拉流 | 设备持续向 Monibuca 推 RTP 流,占用带宽 | ### 5. 获取国标设备列表 ```bash # 全部设备 curl "http://localhost:8081/api/video/gb/devices?status=-1" # 在线设备 curl "http://localhost:8081/api/video/gb/devices?status=1" # 离线设备 curl "http://localhost:8081/api/video/gb/devices?status=0" ``` ### 6. 获取国标设备通道列表 ```bash curl "http://localhost:8081/api/video/gb/devices/34020000001320000005/channels" ``` --- ## 录像接口 > **前置条件**:需 Monibuca **启用 HLS 插件**,手动录制通过 HLS 插件的 HTTP API 实现。 > > 历史录像查询(`/api/video/record/list`、`/catalog`、`/delete`)还需 Monibuca 配置数据库 DSN,否则返回 `no database`。 ### Monibuca 录制配置示例 在 Monibuca 的 `config.yaml` 中启用 HLS 插件: ```yaml hls: enable: true ``` ### 7. 开始录制(手动触发) 手动触发录制任务,无需 Monibuca 配置自动录制。 ```bash curl -X POST http://localhost:8081/api/video/record/start \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001", "fragment": "60s", "filePath": "record/live/video_cam001" }' ``` | 字段 | 说明 | 默认值 | |------|------|--------| | `streamPath` | 流路径 | 必填 | | `fragment` | 分片时长:`20s`、`1m`、`1h30m` 等 | `10s` | | `filePath` | 录像保存路径 | `record/{streamPath}` | **返回示例**: ```json { "code": 0, "message": "success", "data": { "streamPath": "live/video_cam001", "pointer": 1234567890, "fragment": "10s", "filePath": "record/live/video_cam001", "status": "recording" } } ``` ### 8. 停止录制(手动停止) 停止指定流的手动录制任务(不会停止流本身): ```bash curl -X POST http://localhost:8081/api/video/record/stop \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001" }' ``` ### 9. 正在录制列表 ```bash curl "http://localhost:8081/api/video/record/recording" ``` **返回示例**: ```json { "code": 0, "message": "success", "data": [ { "streamPath": "live/video_cam001", "startTime": "2026-06-03T10:00:00Z", "type": "*mp4.Recorder", "pointer": 1234567890 } ] } ``` ### 10. 历史录像列表 ```bash curl "http://localhost:8081/api/video/record/list?streamPath=live/video_cam001&start=2026-06-01+00:00:00&end=2026-06-03+23:59:59&pageNum=1&pageSize=10&type=mp4" ``` | 参数 | 说明 | 默认值 | |------|------|--------| | `streamPath` | 流路径 | 必填 | | `start` | 开始时间 `yyyy-MM-dd HH:mm:ss` | 可选 | | `end` | 结束时间 `yyyy-MM-dd HH:mm:ss` | 可选 | | `pageNum` | 页码 | `1` | | `pageSize` | 每页条数 | `10` | | `type` | 录制类型:`mp4`/`flv`/`hls` | `mp4` | ### 11. 录像目录 按流路径聚合的录像统计: ```bash curl "http://localhost:8081/api/video/record/catalog?type=mp4" ``` ### 12. 删除录像 ```bash curl -X POST http://localhost:8081/api/video/record/delete \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001", "startTime": "2026-06-01 00:00:00", "endTime": "2026-06-03 23:59:59", "type": "mp4" }' ``` | 参数 | 说明 | |------|------| | `streamPath` | 流路径(必填) | | `ids` | 指定录像 ID 列表(可选) | | `startTime` | 开始时间(可选) | | `endTime` | 结束时间(可选) | | `type` | 录制类型 | `mp4` | ### 13. 录像回放播放地址 ```bash curl "http://localhost:8081/api/video/record/play?streamPath=live/video_cam001&startTime=2026-06-03+10:00:00&endTime=2026-06-03+11:00:00" ``` **返回示例(有录像)**: ```json { "code": 0, "message": "success", "data": { "streamPath": "live/video_cam001", "startTime": "2026-06-03 10:00:00", "endTime": "2026-06-03 11:00:00", "hasRecord": true, "recordCount": 5, "actualStartTime": "2026-06-03 10:05:00", "actualEndTime": "2026-06-03 10:55:00", "vodFlvUrl": "http://192.168.0.188:8080/vod/live/video_cam001.flv?start=2026-06-03 10:00:00&end=2026-06-03 11:00:00", "vodHlsUrl": "http://192.168.0.188:8080/vod/live/video_cam001.m3u8?start=2026-06-03 10:00:00&end=2026-06-03 11:00:00", "tip": "需 Monibuca 启用 vod 插件或配置 HTTP 静态文件服务才能正常播放" } } ``` **返回示例(无录像)**: ```json { "code": 404, "message": "该时间范围内没有录像,请检查时间参数", "data": null } ``` --- ## 项目结构 ``` gst-gvideo/ ├── main.go # 主程序入口 ├── internal/ │ ├── config/config.go # 配置管理 │ ├── controller/video_controller.go # HTTP控制器 │ ├── dto/ │ │ ├── requests.go # 请求DTO │ │ ├── responses.go # 响应DTO │ │ └── response.go # 通用响应 │ └── service/ │ ├── monibuca_service.go # Monibuca服务 │ └── heartbeat_service.go # 心跳服务 ├── config.yaml # 配置文件 ├── build.sh # 编译脚本 ├── curl.sh # 启动脚本 ├── .air.toml # air热重载配置 ├── go.mod └── README.md ``` --- ## 运行 ```bash # 开发模式运行(支持air热重载) go run main.go # 或使用air air ``` ## 编译 ```bash # 开发编译 ./build.sh dev # 当前平台 # 跨平台编译 ./build.sh linux # Linux amd64 ./build.sh linux-arm64 # Linux arm64 ./build.sh windows # Windows amd64 ./build.sh mac # macOS arm64 ``` ## 部署 ```bash # 启动服务 ./curl.sh start # 停止服务 ./curl.sh stop # 重启服务 ./curl.sh restart # 查看状态 ./curl.sh status # 查看日志 ./curl.sh tail ``` --- ## 配置 修改 `config.yaml`: ```yaml server: port: 8081 video: addr: http://192.168.0.188:8080 # Monibuca地址 max_wait: 90000 # 心跳超时时间(毫秒) logging: level: info ``` --- ## 从Java版本迁移 本项目从 `gst-jvideo` (Java Spring Boot) 迁移而来,保持了相同的API接口和功能。 主要变化: - 使用 Gin 框架替代 Spring Boot - 使用 Resty 替代 RestTemplate - 使用标准库的并发原语替代 Spring 的定时任务 - 配置格式从 YAML 保持不变 - 主程序入口移到根目录,方便 air 热重载开发