音视频与实时通信
用生活化的比喻,让你从"只会发文字消息"到"能实现游戏内语音聊天和流媒体"
前置知识:3_1 第14章 游戏实时通信优化(WebSocket 基础)
阅读指南(初学者必看)
为什么你需要学习音视频与实时通信?
越来越多游戏需要实时音视频:
- MOBA/FPS 的队内语音
- 社交游戏的视频通话
- 游戏直播功能
- 云游戏的视频流
学完本章,你能回答:
- WebRTC 的核心组件和连接流程是什么?
- 语音聊天架构有哪几种?怎么选?
- 音视频编解码的基本原理?
- 第三方音视频 SDK 怎么选?
本文结构
第一部分:WebRTC 基础
第二部分:实时语音架构
第三部分:音视频编解码
第四部分:第三方服务选型
一、WebRTC 基础
生活类比:WebRTC 就像"可视电话"——浏览器原生支持,不需要装插件就能打电话。
WebRTC 核心组件
1. getUserMedia ── 获取摄像头/麦克风
2. RTCPeerConnection ── P2P 连接
3. RTCDataChannel ── 数据通道
WebRTC 连接流程
1. 信令交换(SDP Offer/Answer)
A → 服务器 → B:SDP Offer(我的媒体能力)
B → 服务器 → A:SDP Answer(同意,我的媒体能力)
2. ICE 候选收集
A 收集自己的网络地址(公网/内网/中继)
B 收集自己的网络地址
互相交换
3. P2P 连接建立
尝试直连(UDP)
直连失败 → STUN 获取公网 IP
还失败 → TURN 中继服务器转发
4. 音视频传输
连接建立后,音视频数据 P2P 传输
WebRTC 代码示例
// 获取本地媒体流
const localStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false // 游戏语音不需要视频
});
// 创建 PeerConnection
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' }, // STUN 服务器
{ urls: 'turn:turn.example.com', username: 'user', credential: 'pass' } // TURN 服务器
]
});
// 添加本地流
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));
// 接收远程流
pc.ontrack = (event) => {
const remoteAudio = document.getElementById('remoteAudio');
remoteAudio.srcObject = event.streams[0];
};
// ICE 候选
pc.onicecandidate = (event) => {
if (event.candidate) {
// 通过信令服务器发送给对方
signalingServer.send({ type: 'ice-candidate', candidate: event.candidate });
}
};
二、实时语音架构
生活类比:语音架构就像"会议系统"——2 人通话直接连,10 人开会需要主持人转发。
三种架构
| 架构 | 原理 | 适合人数 | 延迟 | 服务器压力 |
|---|---|---|---|---|
| Mesh | 每个人直连所有人 | 2~4 人 | 最低 | 无 |
| SFU | 服务器转发,不解码 | 5~20 人 | 低 | 中 |
| MCU | 服务器解码混合再编码 | 20+ 人 | 较高 | 高 |
Mesh 架构
A ←→ B
↕ ↕
D ←→ C
每个人和其他所有人建立 P2P 连接
N 人需要 N×(N-1)/2 个连接
4 人 = 6 个连接 ✅
10 人 = 45 个连接 ❌(太多)
SFU 架构(推荐)
A → ┐
B → SFU → A/B/C/D
C → ┘
D → ┘
每人发一路流给 SFU
SFU 转发给其他人(不解码,只转发)
服务器压力小,延迟低
游戏推荐:5~20 人的房间语音用 SFU
MCU 架构
A → ┐
B → MCU → 混合流 → A/B/C/D
C → ┘
D → ┘
服务器解码所有人的音频 → 混合 → 重新编码 → 发给每人
每人只收一路流(带宽最省)
缺点:服务器 CPU 开销大,延迟高
适合:大型会议/直播
三、音视频编解码
音频编解码
| 编解码器 | 比特率 | 延迟 | 适用场景 |
|---|---|---|---|
| Opus | 6~510 kbps | 5~66ms | 游戏语音首选 ✅ |
| AAC | 64~256 kbps | ~100ms | 音乐/直播 |
| G.711 | 64 kbps | 低 | 传统电话 |
| Speex | 2.4~24.6 kbps | ~30ms | Opus 之前的方案 |
视频编解码
| 编解码器 | 压缩率 | 延迟 | 适用场景 |
|---|---|---|---|
| H.264/AVC | 中 | 低 | 通用,兼容性最好 |
| H.265/HEVC | 高(比H.264省50%) | 中 | 4K/高画质 |
| VP8/VP9 | 中/高 | 低 | WebRTC 默认 |
| AV1 | 最高 | 较高 | 未来标准 |
游戏语音的特殊处理
1. 降噪(Noise Suppression)
- 过滤背景噪音
- WebRTC 内置降噪模块
2. 回声消除(AEC)
- 消除扬声器播放的声音被麦克风采集
- 游戏必须开启(不戴耳机时)
3. 自动增益(AGC)
- 自动调整音量
- 远近说话声音一样大
4. 静音检测(VAD)
- 不说话时不发送音频
- 节省带宽 50%+
四、第三方服务选型
生活类比:自己搭建音视频就像"自己建电话网",用第三方就像"用移动/联通"——后者更稳定更省事。
主流音视频 SDK 对比
| 声网 Agora | 腾讯 TRTC | 即构 ZEGO | |
|---|---|---|---|
| 延迟 | < 200ms | < 200ms | < 200ms |
| 音质 | 高 | 高 | 高 |
| 游戏适配 | ✅ 有游戏方案 | ✅ 有游戏方案 | ✅ 有游戏方案 |
| 价格 | 中 | 中 | 中 |
| 文档 | 优秀 | 优秀 | 优秀 |
| 免费额度 | 每月1万分钟 | 每月1万分钟 | 每月1万分钟 |
选型建议
游戏语音方案选择:
1. 小团队/MVP → 第三方 SDK(声网/腾讯TRTC)
优势:开发快、稳定、有免费额度
劣势:有依赖、长期成本高
2. 大团队/自研需求 → 自建 SFU(MediaSoup/LiveKit)
优势:自主可控、无依赖
劣势:开发维护成本高
3. 不推荐:纯 WebRTC 自研
原因:信令服务器、TURN/STUN、NAT 穿透等太复杂
推荐路径:先用第三方 SDK → 量大后自建 SFU
自问自答
Q1:游戏一定要有语音聊天吗?
不一定。休闲游戏不需要。竞技游戏(MOBA/FPS/吃鸡)必须。社交游戏推荐。语音能显著提升团队配合和游戏体验。
Q2:WebRTC 在微信小游戏中能用吗?
微信小游戏支持
wx.createLivePlayer和wx.createLivePusher,但不完全支持标准 WebRTC API。需要用微信的实时音视频组件或第三方 SDK 的小游戏版。
Q3:语音聊天会不会影响游戏性能?
影响很小。Opus 编码比特率约 32kbps,现代网络完全无压力。CPU 开销约 2~5%。建议语音和游戏逻辑在不同线程处理。
Q4:自己搭建 SFU 服务器需要什么?
MediaSoup(Node.js)或 LiveKit(Go)是开源 SFU。需要:1. 高带宽服务器(100Mbps+);2. TURN 服务器(NAT 穿透失败时中继);3. 信令服务器(WebSocket)。
Q5:云游戏的视频流和语音有什么区别?
云游戏是"远程桌面"——服务器渲染画面 → 编码视频流 → 传到客户端。延迟要求更低(< 50ms),带宽更大(5~20Mbps)。技术栈不同,但底层都依赖 WebRTC/QUIC。
实践任务
- WebRTC 语音 Demo:2 人浏览器语音通话
- 接入第三方 SDK:用声网 Agora 实现游戏内语音
- 音频处理:实现降噪 + 静音检测 + 音量可视化
- 架构设计:为 5 人小队设计语音架构方案
- 性能测试:测试语音对游戏 FPS 和网络延迟的影响
与其他章节的关联
| 本节内容 | 关联章节 | 关联点 |
|---|---|---|
| WebSocket | 3_1 第14章 游戏实时通信优化 | WebRTC 信令用 WebSocket |
| 网络优化 | 3_1 第14章 游戏实时通信优化 | 弱网下的音视频处理 |
| 云游戏 | 5_2 第02章 云游戏与边缘计算 | 云游戏基于视频流传输 |
| 微信小游戏 | 5_2 第05章 微信小游戏开发 | 小游戏的音视频 API |
| 容器化 | 第03章 Kubernetes 编排 | SFU 服务器的 K8s 部署 |
⬅️ 上一章:版本管理与灰度发布 | ➡️ 返回学习路线图