562 lines
17 KiB
Markdown
562 lines
17 KiB
Markdown
# ZLMediaKit API 核心概念与使用指南
|
||
|
||
## 一、核心概念解析
|
||
|
||
### 1. 流(Stream)的概念
|
||
在 ZLMediaKit 中,**流**是指一个媒体数据源,由四元组唯一标识:
|
||
- **schema**: 协议类型(rtsp/rtmp/rtc等)
|
||
- **vhost**: 虚拟主机(通常是 `__defaultVhost__`)
|
||
- **app**: 应用名(如 live、rtp)
|
||
- **stream**: 流ID(如 test、camera01)
|
||
|
||
**完整流标识**: `schema://vhost/app/stream`
|
||
例如: `rtsp://__defaultVhost__/live/test`
|
||
|
||
### 2. Session(会话)
|
||
**Session** 是指客户端与服务器之间的 **TCP/UDP 连接**。
|
||
- 每个播放器连接、推流连接都会创建一个 Session
|
||
- Session 包含:连接ID、本地端口、对端IP、协议类型等信息
|
||
- 通过 `getAllSession` 可以查看所有活跃连接
|
||
- 通过 `kick_session` 可以断开指定连接
|
||
|
||
**Session 与 Stream 的关系**:
|
||
- 一个 Stream 可以有多个 Session(多个播放器观看同一个流)
|
||
- 一个 Session 只对应一个 Stream
|
||
|
||
### 3. 拉流代理(StreamProxy)
|
||
**拉流代理**是指 ZLMediaKit 作为客户端,从远程服务器拉取流,然后在本地提供服务。
|
||
|
||
**使用场景**:
|
||
- 从其他流媒体服务器拉取流到本地
|
||
- 协议转换(拉取 RTMP 流,提供 RTSP/HLS 等多协议播放)
|
||
- 流的中转和分发
|
||
|
||
**API**: `addStreamProxy`
|
||
```
|
||
GET /index/api/addStreamProxy?
|
||
secret=xxx&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=test&
|
||
url=rtmp://remote.server.com/live/stream
|
||
```
|
||
|
||
**工作原理**:
|
||
```
|
||
远程服务器 --拉流--> ZLMediaKit --提供多协议--> 播放器
|
||
(RTMP源) (代理) (RTSP/RTMP/HLS/FLV等)
|
||
```
|
||
|
||
### 4. FFmpeg 拉流代理(FFmpegSource)
|
||
**FFmpeg 代理**是通过调用 FFmpeg 进程来拉取流,支持更多格式和协议。
|
||
|
||
**与普通拉流代理的区别**:
|
||
- **StreamProxy**: 使用 ZLMediaKit 内置播放器,性能高,但支持协议有限
|
||
- **FFmpegSource**: 使用 FFmpeg,支持任意协议/格式,但性能较低,占用资源多
|
||
|
||
**使用场景**:
|
||
- 拉取 ZLMediaKit 不支持的协议(如某些特殊 HLS、DASH)
|
||
- 需要 FFmpeg 的转码能力
|
||
- 拉取文件流
|
||
|
||
**API**: `addFFmpegSource`
|
||
```
|
||
GET /index/api/addFFmpegSource?
|
||
secret=xxx&
|
||
src_url=http://example.com/live.m3u8&
|
||
dst_url=rtmp://127.0.0.1/live/stream&
|
||
timeout_ms=10000
|
||
```
|
||
|
||
### 5. 推流代理(StreamPusherProxy)
|
||
**推流代理**是指将 ZLMediaKit 上的流推送到其他流媒体服务器。
|
||
|
||
**使用场景**:
|
||
- 将本地流推送到 CDN
|
||
- 多平台分发(同时推送到多个平台)
|
||
- 流的备份
|
||
|
||
**API**: `addStreamPusherProxy`
|
||
```
|
||
GET /index/api/addStreamPusherProxy?
|
||
secret=xxx&
|
||
schema=rtmp&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=test&
|
||
dst_url=rtmp://cdn.server.com/live/push
|
||
```
|
||
|
||
### 6. 断流(close_stream)
|
||
**断流**是指关闭一个媒体流源,而不是断开客户端连接。
|
||
|
||
**断流的含义**:
|
||
- 停止流的源头(推流端或拉流代理)
|
||
- 所有观看该流的播放器会断开
|
||
- 流从服务器上移除
|
||
|
||
**与 kick_session 的区别**:
|
||
- `close_stream`: 关闭流源,影响所有观看者
|
||
- `kick_session`: 只断开某个客户端连接,不影响流本身
|
||
|
||
### 7. RTP 服务器
|
||
**RTP 服务器**用于接收 GB28181 设备推送的 RTP 流。
|
||
|
||
**工作流程**:
|
||
1. `openRtpServer`: 创建 RTP 接收端口
|
||
2. GB28181 设备推送 RTP 流到该端口
|
||
3. ZLMediaKit 自动将 RTP 流转换为标准流
|
||
4. 可通过 RTSP/RTMP/HLS 等协议播放
|
||
|
||
---
|
||
|
||
## 二、完整使用流程示例
|
||
|
||
### 场景 1: GB28181 设备推流
|
||
```bash
|
||
# 1. 创建 RTP 服务器(监听端口接收 GB28181 推流)
|
||
GET /index/api/openRtpServer?
|
||
secret=xxx&
|
||
port=10000&
|
||
tcp_mode=1&
|
||
stream_id=camera01
|
||
|
||
# 返回: {"code":0, "port":10000}
|
||
|
||
# 2. GB28181 设备推流到 10000 端口(设备端配置)
|
||
|
||
# 3. 查看流是否在线
|
||
GET /index/api/isMediaOnline?
|
||
secret=xxx&
|
||
schema=rtsp&
|
||
vhost=__defaultVhost__&
|
||
app=rtp&
|
||
stream=camera01
|
||
|
||
# 4. 获取流信息(包含所有播放地址)
|
||
GET /index/api/getMediaInfo?
|
||
secret=xxx&
|
||
schema=rtsp&
|
||
vhost=__defaultVhost__&
|
||
app=rtp&
|
||
stream=camera01
|
||
|
||
# 返回包含:
|
||
# - RTSP: rtsp://server:554/rtp/camera01
|
||
# - RTMP: rtmp://server:1935/rtp/camera01
|
||
# - HTTP-FLV: http://server:80/rtp/camera01.live.flv
|
||
# - HLS: http://server:80/rtp/camera01/hls.m3u8
|
||
# - WebRTC: webrtc://server/rtp/camera01
|
||
```
|
||
|
||
### 场景 2: RTMP 推流
|
||
```bash
|
||
# 1. 使用 OBS 或 FFmpeg 推流
|
||
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server:1935/live/mystream
|
||
|
||
# 推流地址格式: rtmp://服务器IP:端口/app/stream
|
||
# - app: 应用名(如 live)
|
||
# - stream: 流ID(如 mystream)
|
||
|
||
# 2. 查看流列表
|
||
GET /index/api/getMediaList?secret=xxx
|
||
|
||
# 返回所有在线流,包含:
|
||
# {
|
||
# "code": 0,
|
||
# "data": [{
|
||
# "app": "live",
|
||
# "stream": "mystream",
|
||
# "vhost": "__defaultVhost__",
|
||
# "schema": "rtmp",
|
||
# "readerCount": 0, // 观看人数
|
||
# "totalReaderCount": 0,
|
||
# "originType": 0, // 0=推流,1=拉流代理,2=点播
|
||
# "originUrl": "",
|
||
# "createStamp": 1234567890
|
||
# }]
|
||
# }
|
||
|
||
# 3. 获取该流的详细信息和播放地址
|
||
GET /index/api/getMediaInfo?
|
||
secret=xxx&
|
||
schema=rtmp&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream
|
||
|
||
# 4. 播放地址:
|
||
# - RTSP: rtsp://server:554/live/mystream
|
||
# - RTMP: rtmp://server:1935/live/mystream
|
||
# - HTTP-FLV: http://server:80/live/mystream.live.flv
|
||
# - HLS: http://server:80/live/mystream/hls.m3u8
|
||
# - WebSocket-FLV: ws://server:80/live/mystream.live.flv
|
||
```
|
||
|
||
### 场景 3: 录制流
|
||
```bash
|
||
# 1. 开始录制(MP4 格式)
|
||
GET /index/api/startRecord?
|
||
secret=xxx&
|
||
type=1& # 0=HLS, 1=MP4
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream&
|
||
max_second=3600 # 每小时切片
|
||
|
||
# 2. 检查是否正在录制
|
||
GET /index/api/isRecording?
|
||
secret=xxx&
|
||
type=1&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream
|
||
|
||
# 3. 获取录像文件列表
|
||
GET /index/api/getMp4RecordFile?
|
||
secret=xxx&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream&
|
||
period=2025-12-09 # 指定日期
|
||
|
||
# 返回:
|
||
# {
|
||
# "code": 0,
|
||
# "data": {
|
||
# "paths": [
|
||
# "/path/to/record/live/mystream/2025-12-09/10-30-00.mp4",
|
||
# "/path/to/record/live/mystream/2025-12-09/11-30-00.mp4"
|
||
# ],
|
||
# "rootPath": "/path/to/record"
|
||
# }
|
||
# }
|
||
|
||
# 4. 停止录制
|
||
GET /index/api/stopRecord?
|
||
secret=xxx&
|
||
type=1&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream
|
||
```
|
||
|
||
### 场景 4: 截图
|
||
```bash
|
||
# 1. 获取实时截图
|
||
GET /index/api/getSnap?
|
||
secret=xxx&
|
||
url=rtsp://server/live/mystream&
|
||
timeout_sec=10&
|
||
expire_sec=60 # 缓存时间
|
||
|
||
# 返回: JPEG 图片数据
|
||
|
||
# 2. 如果配置了定时截图,查看截图列表
|
||
# 截图通常保存在配置的 snap 目录下
|
||
# 目录结构: /snap/vhost/app/stream/timestamp.jpg
|
||
|
||
# 3. 删除截图
|
||
GET /index/api/deleteSnapDirectory?
|
||
secret=xxx&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream&
|
||
file=1234567890.jpg # 可选,不指定则删除整个目录
|
||
```
|
||
|
||
### 场景 5: 下载录像文件
|
||
```bash
|
||
# 1. 获取录像文件列表(见场景3)
|
||
GET /index/api/getMp4RecordFile?
|
||
secret=xxx&
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=mystream&
|
||
period=2025-12-09
|
||
|
||
# 2. 下载指定文件
|
||
GET /index/api/downloadFile?
|
||
file_path=/path/to/record/live/mystream/2025-12-09/10-30-00.mp4&
|
||
save_name=mystream_20251209_103000.mp4
|
||
|
||
# 浏览器会直接下载该文件
|
||
```
|
||
|
||
---
|
||
|
||
## 三、API 分类与关系图
|
||
|
||
### 1. 流管理类
|
||
```
|
||
getMediaList # 获取所有流列表
|
||
getMediaInfo # 获取单个流详细信息
|
||
isMediaOnline # 检查流是否在线
|
||
close_stream # 关闭单个流
|
||
close_streams # 批量关闭流
|
||
getMediaPlayerList # 获取流的播放者列表
|
||
```
|
||
|
||
### 2. 连接管理类
|
||
```
|
||
getAllSession # 获取所有TCP/UDP连接
|
||
kick_session # 断开单个连接
|
||
kick_sessions # 批量断开连接
|
||
```
|
||
|
||
### 3. 代理管理类
|
||
```
|
||
# 拉流代理
|
||
addStreamProxy # 添加拉流代理
|
||
delStreamProxy # 删除拉流代理
|
||
listStreamProxy # 列出所有拉流代理
|
||
getProxyInfo # 获取代理详细信息
|
||
|
||
# 推流代理
|
||
addStreamPusherProxy # 添加推流代理
|
||
delStreamPusherProxy # 删除推流代理
|
||
listStreamPusherProxy # 列出所有推流代理
|
||
getProxyPusherInfo # 获取推流代理信息
|
||
|
||
# FFmpeg 代理
|
||
addFFmpegSource # 添加 FFmpeg 拉流
|
||
delFFmpegSource # 删除 FFmpeg 拉流
|
||
listFFmpegSource # 列出所有 FFmpeg 拉流
|
||
```
|
||
|
||
### 4. RTP/GB28181 类
|
||
```
|
||
openRtpServer # 创建 RTP 接收端口
|
||
closeRtpServer # 关闭 RTP 端口
|
||
connectRtpServer # TCP 主动连接模式
|
||
listRtpServer # 列出所有 RTP 服务器
|
||
getRtpInfo # 获取 RTP 推流信息
|
||
updateRtpServerSSRC # 更新 SSRC 过滤
|
||
pauseRtpCheck # 暂停超时检查
|
||
resumeRtpCheck # 恢复超时检查
|
||
```
|
||
|
||
### 5. RTP 推流类
|
||
```
|
||
startSendRtp # 主动模式推送 RTP
|
||
startSendRtpPassive # 被动模式推送 RTP
|
||
startSendRtpTalk # 双向对讲
|
||
stopSendRtp # 停止推送 RTP
|
||
listRtpSender # 列出 RTP 发送器
|
||
```
|
||
|
||
### 6. 录制类
|
||
```
|
||
startRecord # 开始录制
|
||
stopRecord # 停止录制
|
||
isRecording # 检查录制状态
|
||
getMp4RecordFile # 获取录像文件列表
|
||
deleteRecordDirectory # 删除录像目录
|
||
setRecordSpeed # 设置录像播放速度
|
||
seekRecordStamp # 设置录像播放位置
|
||
startRecordTask # 事件录制(前后录制)
|
||
```
|
||
|
||
### 7. 截图类
|
||
```
|
||
getSnap # 获取实时截图
|
||
deleteSnapDirectory # 删除截图目录
|
||
```
|
||
|
||
### 8. 文件类
|
||
```
|
||
loadMP4File # 点播 MP4 文件
|
||
downloadFile # 下载文件
|
||
```
|
||
|
||
### 9. 系统管理类
|
||
```
|
||
getApiList # 获取 API 列表
|
||
getServerConfig # 获取服务器配置
|
||
setServerConfig # 设置服务器配置
|
||
restartServer # 重启服务器
|
||
getStatistic # 获取统计信息
|
||
getThreadsLoad # 获取网络线程负载
|
||
getWorkThreadsLoad # 获取后台线程负载
|
||
version # 获取版本信息
|
||
```
|
||
|
||
---
|
||
|
||
## 四、关键流程图
|
||
|
||
### 流的生命周期
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 流的来源 │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ 1. 推流: RTMP/RTSP/WebRTC 推流 │
|
||
│ 2. 拉流代理: addStreamProxy │
|
||
│ 3. FFmpeg 代理: addFFmpegSource │
|
||
│ 4. GB28181: openRtpServer + 设备推流 │
|
||
│ 5. 点播: loadMP4File │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 流在 ZLMediaKit 中 │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ - 唯一标识: vhost/app/stream │
|
||
│ - 自动协议转换: RTSP/RTMP/HLS/FLV/WebRTC 等 │
|
||
│ - 可被多个客户端同时播放 │
|
||
│ - 可被录制、截图、转推 │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 流的消费 │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ 1. 播放: 多协议播放地址 │
|
||
│ 2. 录制: startRecord │
|
||
│ 3. 截图: getSnap │
|
||
│ 4. 转推: addStreamPusherProxy │
|
||
│ 5. RTP 推送: startSendRtp │
|
||
└─────────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 流的结束 │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ 1. 推流端断开 │
|
||
│ 2. 主动关闭: close_stream │
|
||
│ 3. 无人观看超时(配置决定) │
|
||
│ 4. 删除代理: delStreamProxy/delFFmpegSource │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### GB28181 完整流程
|
||
```
|
||
1. 创建 RTP 服务器
|
||
openRtpServer(port=10000, stream_id=camera01)
|
||
↓
|
||
2. 配置 GB28181 设备推流到 10000 端口
|
||
↓
|
||
3. 流自动注册为: rtsp://__defaultVhost__/rtp/camera01
|
||
↓
|
||
4. 查看流信息
|
||
getMediaInfo(schema=rtsp, app=rtp, stream=camera01)
|
||
↓
|
||
5. 获取所有播放地址并播放
|
||
- RTSP: rtsp://server:554/rtp/camera01
|
||
- RTMP: rtmp://server:1935/rtp/camera01
|
||
- HTTP-FLV: http://server/rtp/camera01.live.flv
|
||
- HLS: http://server/rtp/camera01/hls.m3u8
|
||
↓
|
||
6. 录制/截图/转推
|
||
startRecord(app=rtp, stream=camera01)
|
||
getSnap(url=rtsp://server/rtp/camera01)
|
||
addStreamPusherProxy(app=rtp, stream=camera01, dst_url=...)
|
||
↓
|
||
7. 关闭流
|
||
closeRtpServer(stream_id=camera01)
|
||
```
|
||
|
||
---
|
||
|
||
## 五、常见问题
|
||
|
||
### Q1: 如何知道流的 stream_id?
|
||
**A**:
|
||
- **推流时**: stream_id 由推流端指定(推流地址的最后一部分)
|
||
- **GB28181**: 在 `openRtpServer` 时指定
|
||
- **拉流代理**: 在 `addStreamProxy` 时指定
|
||
- **查询**: 使用 `getMediaList` 查看所有在线流
|
||
|
||
### Q2: 流的各种播放地址如何获取?
|
||
**A**: 使用 `getMediaInfo` 接口,返回结果包含所有协议的播放地址。
|
||
|
||
### Q3: 录像文件保存在哪里?
|
||
**A**:
|
||
- 默认路径在配置文件中设置(通常是 `./www/record`)
|
||
- 目录结构: `record/vhost/app/stream/日期/时间.mp4`
|
||
- 可通过 `getMp4RecordFile` 查询
|
||
|
||
### Q4: 如何实现多平台推流?
|
||
**A**: 使用 `addStreamPusherProxy`,同一个流可以添加多个推流代理(不同 dst_url)。
|
||
|
||
### Q5: 拉流代理和 FFmpeg 代理如何选择?
|
||
**A**:
|
||
- **优先使用拉流代理**: 性能高,资源占用少
|
||
- **使用 FFmpeg 代理的场景**:
|
||
- 源协议 ZLMediaKit 不支持
|
||
- 需要转码
|
||
- 需要 FFmpeg 的特殊功能
|
||
|
||
### Q6: 如何实现按需拉流?
|
||
**A**: 配置 `on_play` hook,当有人播放时才调用 `addStreamProxy` 拉取源流。
|
||
|
||
---
|
||
|
||
## 六、最佳实践
|
||
|
||
### 1. 流命名规范
|
||
```
|
||
app: 按业务分类(live, record, vod, gb28181)
|
||
stream: 使用有意义的ID(camera_01, user_123_live)
|
||
```
|
||
|
||
### 2. 录制策略
|
||
```
|
||
- 重要流: 实时录制(startRecord)
|
||
- 事件流: 使用 startRecordTask(前后录制)
|
||
- 定时录制: 通过配置文件设置
|
||
```
|
||
|
||
### 3. 性能优化
|
||
```
|
||
- 使用拉流代理而非 FFmpeg 代理
|
||
- 合理设置录制切片时间
|
||
- 使用 HLS 时注意切片数量
|
||
- 监控 getThreadsLoad 和 getWorkThreadsLoad
|
||
```
|
||
|
||
### 4. 安全建议
|
||
```
|
||
- 修改默认 secret
|
||
- 启用推流鉴权(on_publish hook)
|
||
- 启用播放鉴权(on_play hook)
|
||
- 限制 API 访问 IP
|
||
```
|
||
|
||
---
|
||
|
||
## 七、快速参考
|
||
|
||
### 推流地址格式
|
||
```
|
||
RTMP: rtmp://server:1935/app/stream
|
||
RTSP: rtsp://server:554/app/stream (需要服务器支持 RTSP 推流)
|
||
```
|
||
|
||
### 播放地址格式
|
||
```
|
||
RTSP: rtsp://server:554/app/stream
|
||
RTMP: rtmp://server:1935/app/stream
|
||
HTTP-FLV: http://server:80/app/stream.live.flv
|
||
WebSocket-FLV: ws://server:80/app/stream.live.flv
|
||
HLS: http://server:80/app/stream/hls.m3u8
|
||
HTTP-TS: http://server:80/app/stream.live.ts
|
||
HTTP-fMP4: http://server:80/app/stream.live.mp4
|
||
WebRTC: webrtc://server/app/stream
|
||
```
|
||
|
||
### 常用 API 速查
|
||
```bash
|
||
# 查看所有流
|
||
curl "http://server:80/index/api/getMediaList?secret=xxx"
|
||
|
||
# 查看流信息
|
||
curl "http://server:80/index/api/getMediaInfo?secret=xxx&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test"
|
||
|
||
# 开始录制
|
||
curl "http://server:80/index/api/startRecord?secret=xxx&type=1&vhost=__defaultVhost__&app=live&stream=test"
|
||
|
||
# 获取截图
|
||
curl "http://server:80/index/api/getSnap?secret=xxx&url=rtsp://server/live/test&timeout_sec=10" -o snap.jpg
|
||
|
||
# 关闭流
|
||
curl "http://server:80/index/api/close_stream?secret=xxx&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test"
|
||
```
|