# todd-jvideo **Repository Path**: c-java-father/todd-jvideo ## Basic Information - **Project Name**: todd-jvideo - **Description**: todd 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-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Video Demo 基于 Spring Boot 的 Video 视频流调用示例项目。 ## 项目说明 - **服务端口**: `8081` - **Monibuca 地址**: `http://192.168.0.188:8080`(可在 `application.yml` 中修改) ## 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)拉流 国标设备无需主动拉流,Video 通过 `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 **完全一致**。停止时后端会通知 Video 向设备发送 **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 接口** | 相同 | 相同 | | **不停止的后果** | Video 持续从摄像头拉流 | 设备持续向 Video 推 RTP 流,占用带宽 | ### 6. 获取国标设备列表 ```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" ``` ### 7. 获取国标设备通道列表 ```bash curl "http://localhost:8081/api/video/gb/devices/34020000001320000005/channels" ``` --- ## 录像接口 > **前置条件**:需 Video **启用 HLS 插件**,手动录制通过 HLS 插件的 HTTP API 实现。 > > 历史录像查询(`/api/video/record/list`、`/catalog`、`/delete`)还需 Video 配置数据库 DSN,否则返回 `no database`。 ### Video 录制配置示例 在 Video 的 `config.yaml` 中启用 HLS 插件: ```yaml hls: enable: true ``` ### 8. 开始录制(手动触发) 手动触发录制任务,无需 Video 配置自动录制。 ```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" } } ``` ### 9. 停止录制(手动停止) 停止指定流的手动录制任务(不会停止流本身): ```bash curl -X POST http://localhost:8081/api/video/record/stop \ -H "Content-Type: application/json" \ -d '{ "streamPath": "live/video_cam001" }' ``` ### 10. 正在录制列表 ```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 } ] } ``` ### 11. 历史录像列表 ```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` | ### 12. 录像目录 按流路径聚合的录像统计: ```bash curl "http://localhost:8081/api/video/record/catalog?type=mp4" ``` ### 13. 删除录像 ```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` | ### 14. 录像回放播放地址 ```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": "需 Video 启用 vod 插件或配置 HTTP 静态文件服务才能正常播放" } } ``` **返回示例(无录像)**: ```json { "code": 404, "message": "该时间范围内没有录像,请检查时间参数", "data": null } ``` ## 运行 ```bash mvn spring-boot:run ``` ## 配置 修改 `src/main/resources/application.yml`: ```yaml video: addr: http://192.168.0.188:8080 max-wait: 90000 # 最大等待时间,单位毫秒 ```