# 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 播放 = 低延迟直播
