500 lines
14 KiB
Markdown
500 lines
14 KiB
Markdown
# WebRTC 与传统流媒体协议对比详解
|
||
|
||
## 一、协议类型说明
|
||
|
||
### 1. Schema(协议类型)在 ZLMediaKit 中的含义
|
||
|
||
在 ZLMediaKit 中,**schema** 是指流的**传输协议标识**,用于区分同一个流的不同协议版本。
|
||
|
||
```
|
||
完整流标识 = schema://vhost/app/stream
|
||
|
||
例如:
|
||
- rtsp://__defaultVhost__/live/test
|
||
- rtmp://__defaultVhost__/live/test
|
||
- rtc://__defaultVhost__/live/test ← WebRTC 的 schema 标识
|
||
```
|
||
|
||
**注意**: `rtc` 是 ZLMediaKit 中 WebRTC 协议的 schema 标识。
|
||
|
||
---
|
||
|
||
## 二、WebRTC vs 传统协议核心区别
|
||
|
||
### 对比表格
|
||
|
||
| 特性 | RTSP | RTMP | HLS | WebRTC (RTC) |
|
||
|------|------|------|-----|--------------|
|
||
| **传输协议** | TCP/UDP | TCP | HTTP | UDP (SRTP/DTLS) |
|
||
| **延迟** | 1-3秒 | 3-5秒 | 10-30秒 | 100-500毫秒 |
|
||
| **浏览器支持** | ❌ 需插件 | ❌ 需插件 | ✅ 原生支持 | ✅ 原生支持 |
|
||
| **NAT穿透** | ❌ 困难 | ❌ 困难 | ✅ 简单(HTTP) | ✅ 内置(ICE/STUN/TURN) |
|
||
| **双向通信** | ❌ 单向 | ❌ 单向 | ❌ 单向 | ✅ 双向 |
|
||
| **加密** | 可选(RTSPS) | 可选(RTMPS) | 可选(HTTPS) | ✅ 强制(DTLS-SRTP) |
|
||
| **带宽自适应** | ❌ | ❌ | ✅ 切换码率 | ✅ 实时调整 |
|
||
| **使用场景** | 监控/录像 | 直播推流 | 点播/直播 | 实时通信/低延迟直播 |
|
||
|
||
---
|
||
|
||
## 三、详细对比
|
||
|
||
### 1. RTSP (Real Time Streaming Protocol)
|
||
|
||
**特点**:
|
||
- 专为流媒体设计的应用层协议
|
||
- 支持 TCP 和 UDP 传输
|
||
- 常用于视频监控、IPTV
|
||
|
||
**优点**:
|
||
- 延迟低(1-3秒)
|
||
- 支持精确的流控制(暂停、快进、定位)
|
||
- 带宽占用小
|
||
|
||
**缺点**:
|
||
- 浏览器不支持(需要插件或转码)
|
||
- NAT 穿透困难(特别是 UDP 模式)
|
||
- 防火墙不友好
|
||
|
||
**典型应用**:
|
||
```bash
|
||
# 推流(需要支持 RTSP 推流的客户端)
|
||
rtsp://server:554/live/camera01
|
||
|
||
# 播放(VLC、FFplay 等)
|
||
ffplay rtsp://server:554/live/camera01
|
||
```
|
||
|
||
---
|
||
|
||
### 2. RTMP (Real-Time Messaging Protocol)
|
||
|
||
**特点**:
|
||
- Adobe 开发,基于 TCP
|
||
- 曾是直播行业标准
|
||
- Flash 时代的主流协议
|
||
|
||
**优点**:
|
||
- 延迟较低(3-5秒)
|
||
- 推流稳定
|
||
- 生态成熟(OBS、FFmpeg 等支持)
|
||
|
||
**缺点**:
|
||
- 浏览器不再支持(Flash 已淘汰)
|
||
- 只能单向传输
|
||
- 需要转码才能在浏览器播放
|
||
|
||
**典型应用**:
|
||
```bash
|
||
# 推流(OBS、FFmpeg)
|
||
rtmp://server:1935/live/stream
|
||
|
||
# 播放(需要转为 HTTP-FLV 或 HLS)
|
||
# 浏览器: http://server/live/stream.live.flv
|
||
```
|
||
|
||
---
|
||
|
||
### 3. HLS (HTTP Live Streaming)
|
||
|
||
**特点**:
|
||
- Apple 开发,基于 HTTP
|
||
- 将流切片为小文件(.ts 或 .m4s)
|
||
- 通过 .m3u8 索引文件播放
|
||
|
||
**优点**:
|
||
- 浏览器原生支持
|
||
- CDN 友好(HTTP 缓存)
|
||
- 自适应码率
|
||
|
||
**缺点**:
|
||
- 延迟高(10-30秒,取决于切片大小)
|
||
- 不适合实时互动
|
||
- 服务器需要存储切片文件
|
||
|
||
**典型应用**:
|
||
```bash
|
||
# 播放地址
|
||
http://server/live/stream/hls.m3u8
|
||
|
||
# 浏览器中使用
|
||
<video src="http://server/live/stream/hls.m3u8" controls></video>
|
||
```
|
||
|
||
---
|
||
|
||
### 4. WebRTC (Web Real-Time Communication)
|
||
|
||
**特点**:
|
||
- Google 主导的开放标准
|
||
- 专为实时通信设计
|
||
- 基于 UDP,使用 SRTP 加密
|
||
|
||
**核心技术栈**:
|
||
```
|
||
应用层: WebRTC API (getUserMedia, RTCPeerConnection)
|
||
↓
|
||
信令层: SDP (会话描述) + ICE (连接协商)
|
||
↓
|
||
传输层: SRTP (加密的 RTP) + DTLS (密钥交换)
|
||
↓
|
||
网络层: UDP + ICE/STUN/TURN (NAT 穿透)
|
||
```
|
||
|
||
**优点**:
|
||
- ✅ **超低延迟**(100-500ms,最低可达 100ms)
|
||
- ✅ **浏览器原生支持**(无需插件)
|
||
- ✅ **双向通信**(音视频通话、屏幕共享)
|
||
- ✅ **强制加密**(DTLS-SRTP)
|
||
- ✅ **NAT 穿透**(ICE/STUN/TURN)
|
||
- ✅ **带宽自适应**(实时调整码率)
|
||
- ✅ **抗丢包**(FEC、NACK、JitterBuffer)
|
||
|
||
**缺点**:
|
||
- ❌ 服务器实现复杂(需要信令服务器)
|
||
- ❌ 带宽消耗较大(UDP 开销)
|
||
- ❌ 不适合大规模单向直播(推荐用 HLS/FLV)
|
||
- ❌ 需要 HTTPS(浏览器安全限制)
|
||
|
||
**典型应用**:
|
||
```javascript
|
||
// 浏览器播放 WebRTC 流
|
||
const pc = new RTCPeerConnection();
|
||
|
||
// 1. 获取 Offer(从信令服务器)
|
||
const offer = await fetch('http://server/webrtc/offer?app=live&stream=test');
|
||
|
||
// 2. 设置远端描述
|
||
await pc.setRemoteDescription(new RTCSessionDescription(offer));
|
||
|
||
// 3. 创建 Answer
|
||
const answer = await pc.createAnswer();
|
||
await pc.setLocalDescription(answer);
|
||
|
||
// 4. 发送 Answer 到服务器
|
||
await fetch('http://server/webrtc/answer', {
|
||
method: 'POST',
|
||
body: JSON.stringify(answer)
|
||
});
|
||
|
||
// 5. 接收媒体流
|
||
pc.ontrack = (event) => {
|
||
videoElement.srcObject = event.streams[0];
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## 四、ZLMediaKit 中的 Schema 使用
|
||
|
||
### 1. Schema 的作用
|
||
|
||
在 ZLMediaKit 中,**同一个流可以同时以多种协议提供服务**,schema 用于区分:
|
||
|
||
```bash
|
||
# 同一个流的不同协议版本
|
||
rtsp://__defaultVhost__/live/test # RTSP 协议
|
||
rtmp://__defaultVhost__/live/test # RTMP 协议
|
||
rtc://__defaultVhost__/live/test # WebRTC 协议
|
||
|
||
# 它们共享同一个媒体源,只是传输协议不同
|
||
```
|
||
|
||
### 2. API 中的 Schema 参数
|
||
|
||
```bash
|
||
# 查询流信息时需要指定 schema
|
||
GET /index/api/getMediaInfo?
|
||
secret=xxx&
|
||
schema=rtsp& # 指定协议类型
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=test
|
||
|
||
# 不同 schema 返回的信息可能不同:
|
||
# - rtsp: 返回 RTSP 相关信息(RTP 统计等)
|
||
# - rtmp: 返回 RTMP 相关信息(chunk size 等)
|
||
# - rtc: 返回 WebRTC 相关信息(ICE 状态、DTLS 等)
|
||
```
|
||
|
||
### 3. 关闭流时的 Schema
|
||
|
||
```bash
|
||
# 关闭特定协议的流
|
||
GET /index/api/close_stream?
|
||
secret=xxx&
|
||
schema=rtsp& # 只关闭 RTSP 协议
|
||
vhost=__defaultVhost__&
|
||
app=live&
|
||
stream=test
|
||
|
||
# 注意:关闭一个 schema 会影响所有协议
|
||
# 因为它们共享同一个媒体源
|
||
```
|
||
|
||
---
|
||
|
||
## 五、WebRTC 在 ZLMediaKit 中的特殊性
|
||
|
||
### 1. WebRTC 的双重身份
|
||
|
||
WebRTC 在 ZLMediaKit 中既是**协议**,也是**技术栈**:
|
||
|
||
```
|
||
作为协议 (schema=rtc):
|
||
- 用于标识 WebRTC 传输的流
|
||
- 在 API 中使用 schema=rtc 查询
|
||
|
||
作为技术栈:
|
||
- 包含信令、ICE、DTLS、SRTP 等完整实现
|
||
- 需要特殊的 API 端点(/index/api/webrtc)
|
||
```
|
||
|
||
### 2. WebRTC 专用 API
|
||
|
||
ZLMediaKit 为 WebRTC 提供了专门的 API:
|
||
|
||
```bash
|
||
# 1. 播放 WebRTC 流(浏览器端)
|
||
POST /index/api/webrtc?
|
||
app=live&
|
||
stream=test&
|
||
type=play
|
||
|
||
# 请求体: SDP Offer
|
||
# 返回: SDP Answer
|
||
|
||
# 2. 推流到 WebRTC(浏览器端)
|
||
POST /index/api/webrtc?
|
||
app=live&
|
||
stream=test&
|
||
type=push
|
||
|
||
# 3. WebRTC 信令服务器相关
|
||
addWebrtcRoomKeeper # 注册到信令服务器
|
||
delWebrtcRoomKeeper # 从信令服务器注销
|
||
listWebrtcRoomKeepers # 查看注册信息
|
||
listWebrtcRooms # 查看房间信息
|
||
|
||
# 4. 广播消息(DataChannel)
|
||
broadcastMessage # 向所有 WebRTC 播放器广播消息
|
||
```
|
||
|
||
### 3. WebRTC 流的生命周期
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ WebRTC 推流(浏览器 → 服务器) │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ 1. 浏览器创建 RTCPeerConnection │
|
||
│ 2. 生成 SDP Offer │
|
||
│ 3. POST /index/api/webrtc?type=push │
|
||
│ 4. 服务器返回 SDP Answer │
|
||
│ 5. ICE 候选交换 │
|
||
│ 6. DTLS 握手 + SRTP 密钥协商 │
|
||
│ 7. 媒体流传输(UDP/SRTP) │
|
||
│ 8. 流注册为: rtc://__defaultVhost__/live/test │
|
||
└─────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ 协议自动转换(ZLMediaKit 核心能力) │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ WebRTC 推流后,自动提供多协议播放: │
|
||
│ - rtc://server/live/test (WebRTC) │
|
||
│ - rtsp://server/live/test (RTSP) │
|
||
│ - rtmp://server/live/test (RTMP) │
|
||
│ - http://server/live/test.flv (HTTP-FLV) │
|
||
│ - http://server/live/test/hls.m3u8 (HLS) │
|
||
└─────────────────────────────────────────────────────┘
|
||
↓
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ WebRTC 播放(服务器 → 浏览器) │
|
||
├─────────────────────────────────────────────────────┤
|
||
│ 1. 浏览器创建 RTCPeerConnection │
|
||
│ 2. 生成 SDP Offer │
|
||
│ 3. POST /index/api/webrtc?type=play │
|
||
│ 4. 服务器返回 SDP Answer │
|
||
│ 5. ICE 候选交换 │
|
||
│ 6. DTLS 握手 + SRTP 密钥协商 │
|
||
│ 7. 接收媒体流(UDP/SRTP) │
|
||
│ 8. 渲染到 <video> 元素 │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 六、使用场景选择
|
||
|
||
### 1. 视频监控系统
|
||
```
|
||
推荐: RTSP (推流) + HTTP-FLV/HLS (播放)
|
||
原因:
|
||
- 摄像头通常支持 RTSP
|
||
- 浏览器播放用 HTTP-FLV(低延迟)或 HLS(兼容性好)
|
||
- 不需要 WebRTC 的双向通信能力
|
||
```
|
||
|
||
### 2. 直播平台
|
||
```
|
||
推荐: RTMP (推流) + HTTP-FLV/HLS (播放)
|
||
原因:
|
||
- OBS 等工具支持 RTMP 推流
|
||
- HTTP-FLV 延迟低(3-5秒)
|
||
- HLS 兼容性好,CDN 友好
|
||
- 大规模分发,WebRTC 成本高
|
||
```
|
||
|
||
### 3. 视频会议/在线教育
|
||
```
|
||
推荐: WebRTC (双向)
|
||
原因:
|
||
- 需要双向音视频通信
|
||
- 延迟要求极低(<500ms)
|
||
- 浏览器原生支持,无需插件
|
||
- 需要屏幕共享、白板等互动功能
|
||
```
|
||
|
||
### 4. 低延迟直播(电商带货、游戏直播)
|
||
```
|
||
推荐: WebRTC (播放) + RTMP (推流)
|
||
原因:
|
||
- 主播用 OBS 推 RTMP 流
|
||
- 观众用 WebRTC 播放(延迟 <500ms)
|
||
- 实现"秒级"互动
|
||
- ZLMediaKit 自动协议转换
|
||
```
|
||
|
||
### 5. 录像回放
|
||
```
|
||
推荐: HLS 或 HTTP-FLV
|
||
原因:
|
||
- 不需要实时性
|
||
- HLS 支持拖拽、快进
|
||
- CDN 缓存友好
|
||
```
|
||
|
||
---
|
||
|
||
## 七、实战示例
|
||
|
||
### 示例 1: RTMP 推流 + WebRTC 播放(低延迟直播)
|
||
|
||
```bash
|
||
# 1. OBS 推 RTMP 流
|
||
推流地址: rtmp://server:1935/live/anchor01
|
||
|
||
# 2. 流自动注册,支持多协议
|
||
rtmp://server/live/anchor01
|
||
rtsp://server/live/anchor01
|
||
rtc://server/live/anchor01
|
||
http://server/live/anchor01.live.flv
|
||
http://server/live/anchor01/hls.m3u8
|
||
|
||
# 3. 浏览器用 WebRTC 播放(超低延迟)
|
||
```
|
||
|
||
```html
|
||
<!-- 浏览器端代码 -->
|
||
<video id="video" autoplay controls></video>
|
||
|
||
<script>
|
||
async function playWebRTC() {
|
||
const pc = new RTCPeerConnection();
|
||
|
||
// 创建 Offer
|
||
const offer = await pc.createOffer({
|
||
offerToReceiveAudio: true,
|
||
offerToReceiveVideo: true
|
||
});
|
||
await pc.setLocalDescription(offer);
|
||
|
||
// 发送 Offer 到服务器
|
||
const response = await fetch('http://server/index/api/webrtc?app=live&stream=anchor01&type=play', {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify({
|
||
sdp: offer.sdp,
|
||
type: offer.type
|
||
})
|
||
});
|
||
|
||
const answer = await response.json();
|
||
|
||
// 设置 Answer
|
||
await pc.setRemoteDescription(new RTCSessionDescription({
|
||
type: 'answer',
|
||
sdp: answer.sdp
|
||
}));
|
||
|
||
// 接收媒体流
|
||
pc.ontrack = (event) => {
|
||
document.getElementById('video').srcObject = event.streams[0];
|
||
};
|
||
}
|
||
|
||
playWebRTC();
|
||
</script>
|
||
```
|
||
|
||
### 示例 2: 查询不同协议的流信息
|
||
|
||
```bash
|
||
# 查询 RTSP 协议的流信息
|
||
curl "http://server/index/api/getMediaInfo?secret=xxx&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test"
|
||
|
||
# 返回:
|
||
{
|
||
"code": 0,
|
||
"schema": "rtsp",
|
||
"vhost": "__defaultVhost__",
|
||
"app": "live",
|
||
"stream": "test",
|
||
"tracks": [...],
|
||
"rtsp_url": "rtsp://server:554/live/test",
|
||
"rtp_info": {...}
|
||
}
|
||
|
||
# 查询 WebRTC 协议的流信息
|
||
curl "http://server/index/api/getMediaInfo?secret=xxx&schema=rtc&vhost=__defaultVhost__&app=live&stream=test"
|
||
|
||
# 返回:
|
||
{
|
||
"code": 0,
|
||
"schema": "rtc",
|
||
"vhost": "__defaultVhost__",
|
||
"app": "live",
|
||
"stream": "test",
|
||
"tracks": [...],
|
||
"webrtc_url": "webrtc://server/live/test",
|
||
"ice_servers": [...]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 八、总结
|
||
|
||
### Schema 的本质
|
||
- **Schema 是协议标识符**,用于区分同一个流的不同传输协议
|
||
- 在 ZLMediaKit 中,`rtc` 是 WebRTC 的 schema 标识
|
||
- 同一个流可以同时支持多个 schema(协议转换)
|
||
|
||
### WebRTC 的特殊性
|
||
- **WebRTC 不仅是协议,更是完整的实时通信技术栈**
|
||
- 包含信令、NAT 穿透、加密、拥塞控制等完整解决方案
|
||
- 适合低延迟、双向通信场景
|
||
|
||
### 协议选择原则
|
||
```
|
||
延迟要求 < 500ms → WebRTC
|
||
需要双向通信 → WebRTC
|
||
浏览器播放 + 延迟 3-5秒 → HTTP-FLV
|
||
浏览器播放 + 延迟 10秒+ → HLS
|
||
监控/录像 → RTSP
|
||
推流 → RTMP/RTSP
|
||
```
|
||
|
||
### ZLMediaKit 的优势
|
||
- **自动协议转换**: 一次推流,多协议播放
|
||
- **统一管理**: 通过 schema 参数区分不同协议
|
||
- **灵活组合**: RTMP 推流 + WebRTC 播放 = 低延迟直播
|