1. WebRTC 层级定位与核心功能
WebRTC 为应用层提供了四个核心 API,这些 API 是构建实时通信应用的基础:
| API | 功能 | 关键作用 | 浏览器兼容性 |
|---|---|---|---|
getUserMedia | 获取本地音视频流 | 访问摄像头、麦克风等硬件设备 | Chrome, Firefox, Edge, Safari |
RTCPeerConnection | 建立点对点连接 | 管理连接、交换媒体数据、处理 ICE 候选 | Chrome, Firefox, Edge, Safari |
RTCDataChannel | 传输任意数据 | 实现文本、文件等非媒体数据传输 | Chrome, Firefox, Edge |
getDisplayMedia | 获取屏幕共享流 | 实现屏幕共享功能 | Chrome, Firefox |
1.1 WebRTC API 的层级定位
WebRTC API 位于API 层,是应用层与核心引擎层之间的桥梁。应用层通过调用这些 API,无需了解底层实现细节,即可实现复杂的实时通信功能。
1.2 WebRTC API 的工作原理
WebRTC API 本质上是 JavaScript 接口,它封装了底层 WebRTC 核心引擎的功能。当应用层调用这些 API 时,WebRTC 引擎会执行以下操作:
- 通过系统接口层访问硬件设备
- 与核心引擎层交互,处理媒体流和网络连接
- 通过信令机制与其他端点交换连接信息
1.3 API 层的核心功能与作用
核心功能定位
| 功能 | 说明 | 重要性 |
|---|---|---|
| 标准化接口 | 提供统一的 WebRTC API,使开发者无需关心底层实现 | ⭐⭐⭐⭐⭐ |
| 复杂性封装 | 将 ICE 候选收集、SDP 协商、媒体处理等复杂逻辑封装 | ⭐⭐⭐⭐ |
| 生命周期管理 | 管理 RTCPeerConnection 等对象的创建、使用和销毁 | ⭐⭐⭐⭐ |
| 跨平台支持 | 确保不同浏览器提供一致的 API 体验 | ⭐⭐⭐ |
| 错误处理 | 提供标准化的错误处理机制 | ⭐⭐⭐ |
2. API 层关键源码应用层开发的基本流程
WebRTC 应用开发的完整流程可以概括为'获取媒体→建立连接→交换信令→处理媒体→数据传输'五个核心步骤:
应用层 │ ├── 1. 获取本地媒体流 (getUserMedia) │ ├── 2. 创建 RTCPeerConnection 实例 (RTCPeerConnection) │ ├── 3. 信令交换 (SDP 与 ICE 候选) │ ├── 3.1 创建 Offer │ ├── 3.2 发送 Offer 给对方 │ ├── 3.3 接收 Answer │ └── 3.4 交换 ICE 候选 │ ├── 4. 处理媒体流 (ontrack 事件) │ └── 5. 数据传输 (RTCDataChannel)
2.1 源码结构与目录组织
WebRTC 源码中 API 层主要位于 api/ 目录下:
api/
├── peerconnectioninterface.h
├── peerconnectionfactoryinterface.h
├── mediastreaminterface.h
├── datachannelinterface.h
├── sdp.h
├── ...
pc/
├── peerconnectioninterface.cc
├── peerconnectionfactory.cc
├── ...
2.2 关键源码文件解析
2.2.1 peerconnectioninterface.h - 核心接口
// api/peerconnectioninterface.h
// RTCPeerConnection 的核心接口定义
class RTCPeerConnectionInterface {
public:
// 创建 offer
virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) = 0;
// 创建 answer
virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) = 0;
// 设置远程描述
virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) = 0;
// 设置本地描述
virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) = 0;
// 添加媒体轨道
virtual void AddTrack(const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) = 0;
// 添加 ICE 候选
virtual void AddIceCandidate(const IceCandidateInterface* candidate) = 0;
// 监听事件
virtual void OnTrack(const rtc::scoped_refptr<TrackEvent>& event) = 0;
// 获取连接状态
virtual std::string iceConnectionState() const = 0;
virtual std::string connectionState() const = 0;
// ... 其他方法
};
- 该接口定义了 WebRTC 的核心功能,是 API 层的'心脏'
- 使用纯虚函数定义,由实现类具体实现
CreateSessionDescriptionObserver等接口用于处理异步操作- 所有方法都设计为异步,避免阻塞 UI 线程
2.2.2 peerconnectionfactoryinterface.h - 工厂接口
// api/peerconnectionfactoryinterface.h
// PeerConnectionFactory 的接口定义
class PeerConnectionFactoryInterface {
public:
// 创建 PeerConnection 对象
virtual rtc::scoped_refptr<RTCPeerConnectionInterface> CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) = 0;
// 创建 DataChannel
virtual rtc::scoped_refptr<RTCDataChannelInterface> CreateDataChannel(
const std::string& label, const DataChannelInterface::Init& config) = 0;
// 创建 MediaStream
virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
const std::string& label) = 0;
// 创建 MediaStreamTrack
virtual rtc::scoped_refptr<MediaStreamTrackInterface> CreateVideoTrack(
const std::string& id, VideoTrackSourceInterface* source) = 0;
// ... 其他方法
};
- 工厂接口负责创建 WebRTC 核心对象
CreatePeerConnection是创建 RTCPeerConnection 的入口- 使用
scoped_refptr管理对象生命周期,避免内存泄漏 RTCConfiguration用于配置 ICE 服务器等连接参数
2.2.3 mediastreaminterface.h - 媒体流接口
// api/mediastreaminterface.h
// MediaStream API 的核心接口
class MediaStreamInterface {
public:
// 获取媒体流 ID
virtual std::string id() const = 0;
// 获取媒体轨道列表
virtual const std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>>& GetAudioTracks() const = 0;
virtual const std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>>& GetVideoTracks() const = 0;
// 添加媒体轨道
virtual void AddTrack(const rtc::scoped_refptr<MediaStreamTrackInterface>& track) = 0;
// 移除媒体轨道
virtual void RemoveTrack(const rtc::scoped_refptr<MediaStreamTrackInterface>& track) = 0;
};
// MediaStreamTrack 的核心接口
class MediaStreamTrackInterface {
public:
// 获取轨道 ID
virtual std::string id() const = 0;
// 获取轨道类型
virtual std::string kind() const = 0;
// 获取轨道状态
virtual std::string state() const = 0;
// 获取轨道的媒体源
virtual MediaStreamSourceInterface* GetSource() const = 0;
};
- 提供了媒体流和媒体轨道的标准接口
getUserMedia()API 最终会调用这些接口MediaStreamTrack是媒体流的基本单元,可以是音频或视频
2.2.4 sdp.h - SDP 处理接口
// api/sdp.h
// SDP 处理核心接口
class SessionDescriptionInterface {
public:
// 获取 SDP 类型
virtual SdpType type() const = 0;
// 获取 SDP 内容
virtual std::string ToString() const = 0;
// 获取 SDP 的媒体描述
virtual const std::vector<MediaDescriptionInterface*>& GetMediaDescriptions() const = 0;
};
// SDP 解析器接口
class SdpParseError {
public:
// 错误类型
enum Type { kNoError, kInvalidFormat, kInvalidMLine, kInvalidAttribute /*...*/ };
};
// SDP 解析器
class SdpParse {
public:
// 解析 SDP 字符串
static rtc::scoped_refptr<SessionDescriptionInterface> ParseSdp(
const std::string& sdp, SdpParseError* error);
// 生成 SDP 字符串
static std::string GenerateSdp(const SessionDescriptionInterface* desc);
};
- SDP(Session Description Protocol)是 WebRTC 信令交换的核心
SdpParse类负责 SDP 的解析和生成SessionDescriptionInterface是 SDP 的抽象表示
2.2.5 peerconnectioninterface.cc - 实现层
// pc/peerconnectioninterface.cc
// RTCPeerConnection 的实现
class PeerConnection : public RTCPeerConnectionInterface {
public:
PeerConnection(const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<IceServer>>& ice_servers) {
Initialize(options, config, ice_servers);
}
// 创建 offer
void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) override {
// 1. 创建 SDP Offer
SessionDescriptionInterface* offer = CreateOfferInternal(options);
// 2. 设置本地描述
if (offer) SetLocalDescriptionInternal(offer);
// 3. 通过 Observer 返回结果
if (observer) observer->OnSuccess(offer);
}
// 设置本地描述
void SetLocalDescription(SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) override {
// 1. 更新本地描述状态
local_desc_ = desc;
// 2. 生成 ICE 候选
GenerateIceCandidates();
// 3. 通知核心引擎
core_engine_->SetLocalDescription(desc);
// 4. 通过 Observer 通知应用层
if (observer) observer->OnSuccess();
}
// 添加 ICE 候选
void AddIceCandidate(const IceCandidateInterface* candidate) override {
// 1. 添加候选到内部列表
ice_candidates_.push_back(candidate);
// 2. 通知核心引擎
core_engine_->AddIceCandidate(candidate);
}
private:
SessionDescriptionInterface* local_desc_ = nullptr;
SessionDescriptionInterface* remote_desc_ = nullptr;
std::vector<rtc::scoped_refptr<IceCandidateInterface>> ice_candidates_;
std::unique_ptr<CoreEngine> core_engine_;
void Initialize(const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<IceServer>>& ice_servers) {
// 1. 创建核心引擎
core_engine_ = std::make_unique<CoreEngine>(config, ice_servers);
// 2. 设置内部状态
}
};
PeerConnection类实现了RTCPeerConnectionInterface接口- 所有 API 方法都调用内部
core_engine_进行实际操作 - 使用
scoped_refptr管理对象生命周期 - 通过
Observer模式处理异步操作
2.2.6 peerconnectionfactory.cc - 工厂实现
// pc/peerconnectionfactory.cc
// PeerConnectionFactory 的实现
class PeerConnectionFactory : public PeerConnectionFactoryInterface {
public:
// 创建 PeerConnection
rtc::scoped_refptr<RTCPeerConnectionInterface> CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) override {
// 1. 创建 PeerConnection 对象
PeerConnection* pc = new PeerConnection(options, config, ice_servers);
// 2. 初始化内部状态
pc->Initialize();
// 3. 返回封装对象
return rtc::scoped_refptr<RTCPeerConnectionInterface>(pc);
}
// 创建 DataChannel
rtc::scoped_refptr<RTCDataChannelInterface> CreateDataChannel(
const std::string& label, const DataChannelInterface::Init& config) override {
// 实现 DataChannel 创建逻辑
// ...
}
};
- 工厂方法负责创建和初始化 PeerConnection 对象
- 使用
scoped_refptr确保对象生命周期安全 - 实现了
PeerConnectionFactoryInterface接口
3. API 层工作流程详解
3.1 API 层交互流程
应用层 (JavaScript) -> API 层 (WebRTC API) -> 核心引擎层 (C++)
1. new RTCPeerConnection()
2. 调用 PeerConnectionFactory::CreatePeerConnection()
3. 创建 PeerConnection 对象
4. 返回 PeerConnection 实例
5. 返回 RTCPeerConnection 实例
6. getUserMedia()
7. 调用 MediaStreamInterface 实现
8. 获取媒体设备
9. 返回媒体流
10. 返回 MediaStream 对象
11. createOffer()
12. 调用 PeerConnection::CreateOffer()
13. 生成 SDP Offer
14. 返回 SDP Offer
15. 返回 Offer SDP
16. setLocalDescription()
17. 调用 PeerConnection::SetLocalDescription()
18. 更新连接状态
19. 确认设置
20. 确认设置
21. addTrack()
22. 调用 PeerConnection::AddTrack()
23. 添加媒体轨道
24. 确认添加
25. 确认添加
26. onicecandidate 事件处理
27. 监听 ICE 候选
28. 收集 ICE 候选
29. 触发 onicecandidate 事件
3.2 详细工作流程
3.2.1 创建 RTCPeerConnection
JavaScript 应用层代码:
const pc = new RTCPeerConnection({
iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
});
API 层工作流程:
- 应用层调用
new RTCPeerConnection() - API 层调用
PeerConnectionFactory::CreatePeerConnection() - 工厂创建
PeerConnection对象 - 初始化内部状态(包括 ICE 服务器配置)
- 返回封装的
RTCPeerConnectionInterface对象
关键源码:
// pc/peerconnectionfactory.cc
rtc::scoped_refptr<RTCPeerConnectionInterface>
PeerConnectionFactory::CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) {
// 创建 PeerConnection 对象
PeerConnection* pc = new PeerConnection(options, config, ice_servers);
// 初始化内部状态
pc->Initialize();
// 返回封装对象
return rtc::scoped_refptr<RTCPeerConnectionInterface>(pc);
}
3.2.2 获取媒体流
JavaScript 应用层代码:
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
API 层工作流程:
- 应用层调用
getUserMedia() - API 层调用
MediaStreamInterface实现 - 调用底层 C++ API 获取媒体设备
- 返回媒体流对象
关键源码:
// api/mediastreaminterface.h
class MediaStreamInterface {
public:
static rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(const std::string& label);
};
// 实现部分
rtc::scoped_refptr<MediaStreamInterface>
MediaStreamInterface::CreateLocalMediaStream(const std::string& label) {
return CreateLocalMediaStreamInternal(label);
}
3.2.3 SDP 协商过程
JavaScript 应用层代码:
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signalingServer.send({ type: "offer", sdp: offer.sdp });
API 层工作流程:
- 应用层调用
createOffer() - API 层调用
PeerConnection::CreateOffer() - 内部调用
CreateOfferInternal()生成 SDP Offer - 调用
SetLocalDescriptionInternal()设置本地描述 - 通过 Observer 返回结果
关键源码:
// pc/peerconnectioninterface.cc
void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) {
SessionDescriptionInterface* offer = CreateOfferInternal(options);
if (offer) SetLocalDescriptionInternal(offer);
if (observer) observer->OnSuccess(offer);
}
SessionDescriptionInterface* PeerConnection::CreateOfferInternal(const RTCOfferOptions* options) {
// 实际 SDP 生成逻辑
return new SessionDescription(offer_sdp);
}
void PeerConnection::SetLocalDescriptionInternal(SessionDescriptionInterface* desc) {
local_desc_ = desc;
GenerateIceCandidates();
core_engine_->SetLocalDescription(desc);
}
3.2.4 ICE 候选交换
JavaScript 应用层代码:
pc.onicecandidate = event => {
if (event.candidate) {
signalingServer.send({ type: "candidate", candidate: event.candidate });
}
};
API 层工作流程:
- 应用层监听
onicecandidate事件 - API 层在内部收集 ICE 候选
- 通过
onicecandidate事件通知应用层 - 应用层将候选发送到信令服务器
关键源码:
// pc/peerconnectioninterface.cc
void PeerConnection::GenerateIceCandidates() {
std::vector<IceCandidateInterface*> candidates;
core_engine_->GetIceCandidates(&candidates);
for (auto& candidate : candidates) {
OnIceCandidate(candidate);
}
}
void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
if (ice_candidate_observer_) {
ice_candidate_observer_->OnIceCandidate(candidate);
}
}
4. 信令机制
4.1 信令机制的核心作用与原理
信令模块是 WebRTC 核心引擎层的关键组成部分,负责处理 WebRTC 会话的建立、协商和管理。信令模块的主要作用是交换 SDP(Session Description Protocol)描述和 ICE 候选地址,以建立 P2P 连接。
WebRTC 本身不提供信令机制,需要开发者实现自己的信令服务器。虽然 WebRTC核心源码本身不包含完整的信令服务器实现,但这是设计层面的刻意选择:
- 核心原因:WebRTC 标准只定义了「实时媒体传输」的核心逻辑,但信令协议是完全开放的(可以用 WebSocket/HTTP/GRPC 等任意协议),因此 Google 没有在核心库中固化某一种信令实现。
- 源码中的相关部分:WebRTC 源码提供了信令交互所需的「数据结构和接口」(如 SDP 解析、ICE 候选者交换的结构体),但不会实现信令的收发、转发逻辑。
实际开发:信令服务器需要开发者自行实现(或使用开源方案如 Janus/Mediasoup/OpenVidu),核心职责是转发 SDP、ICE 候选者、房间控制指令等。
信令服务器用于交换以下关键信息:
- SDP (Session Description Protocol):会话描述信息,包含媒体格式、编解码器等
- ICE Candidates:网络地址信息,用于建立 P2P 连接
信令机制的核心原理
WebRTC 的信令机制是'桥梁',连接两个对等端。它不负责媒体传输,只负责交换建立连接所需的信息。信令机制包括以下关键步骤:
- 初始化:双方建立连接
- Offer/Answer:协商媒体能力
- ICE 候选交换:确定网络路径
- 连接建立:P2P 连接成功
信令模块的作用:
- 会话协商:通过 SDP 交换,协商双方支持的媒体类型、编解码器、分辨率等参数
- 网络信息交换:交换 ICE 候选地址,用于 NAT 穿透和建立 P2P 连接
- 连接管理:管理连接状态,处理连接断开和重连
- 媒体流控制:控制媒体流的添加、删除和修改
- 错误处理:处理连接过程中的错误和异常情况
4.2 关键源码文件及作用
信令模块的核心代码位于 webrtc/pc 和 webrtc/api 目录下,以下是关键文件及其作用:
4.2.1 peer_connection.h 和 peer_connection_impl.h
// webrtc/pc/peer_connection.h
class RTCPeerConnection {
public:
static std::unique_ptr<RTCPeerConnection> Create(const PeerConnectionInterface::Options& options);
virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options = nullptr) = 0;
virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options = nullptr) = 0;
virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) = 0;
virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) = 0;
virtual void AddIceCandidate(const IceCandidateInterface* candidate) = 0;
virtual void GetIceCandidates(std::vector<IceCandidateInterface*>* candidates) = 0;
virtual void OnIceConnectionStateChange(IceConnectionState state) = 0;
};
作用:定义 RTCPeerConnection 接口,实现信令交互的核心功能,包括创建 offer/answer、设置本地/远程描述、添加 ICE 候选等。
4.2.2 session_description.h 和 session_description_impl.h
// webrtc/pc/session_description.h
class SessionDescriptionInterface {
public:
virtual SessionDescriptionType type() const = 0;
virtual const std::string& ToString() const = 0;
virtual const std::vector<MediaContentDescriptionInterface*>& contents() const = 0;
};
作用:定义 SDP 会话描述的接口,用于表示 offer 和 answer 的媒体信息,包括编解码器、分辨率、带宽等参数。
4.2.3 ice_candidate.h 和 ice_candidate_impl.h
// webrtc/pc/ice_candidate.h
class IceCandidateInterface {
public:
virtual const std::string& candidate() const = 0;
virtual const std::string& sdp_mid() const = 0;
virtual int sdp_mline_index() const = 0;
};
作用:定义 ICE 候选的接口,用于表示 NAT 穿透过程中收集的候选地址,包括 Host 候选、Server Reflexive 候选和 Relay 候选。
4.2.4 signaling_channel.h 和 signaling_channel_impl.h
// webrtc/pc/signaling_channel.h
class SignalingChannel {
public:
virtual ~SignalingChannel() {}
virtual void SendOffer(const SessionDescriptionInterface* offer) = 0;
virtual void SendAnswer(const SessionDescriptionInterface* answer) = 0;
virtual void SendLocalDescription(const SessionDescriptionInterface* desc) = 0;
virtual void SendIceCandidate(const IceCandidateInterface* candidate) = 0;
virtual void SetMessageHandler(std::function<void(const SignalingMessage&)> handler) = 0;
};
作用:定义信令通道的接口,用于实现具体的信令传输方式(如 WebSocket、MQTT 等),将 SDP 和 ICE 候选通过信令服务器发送给对端。
4.3 与其他模块的交互
4.3.1 与传输模块的交互
- 信令模块创建 RTCPeerConnection 实例
- 传输模块初始化 RTP/RTCP 和 ICE
- 传输模块收集 ICE 候选并返回给信令模块
- 信令模块将 ICE 候选通过信令服务器交换给对方
- 信令模块设置对方的 ICE 候选给传输模块
- 传输模块建立 P2P 连接
4.3.2 与媒体引擎的交互
- 信令模块创建 RTCPeerConnection 实例
- 媒体引擎初始化并采集媒体流
- 信令模块生成 SDP offer 并交换
- 信令模块设置远程描述
- 媒体引擎根据远程描述配置媒体处理
4.4 源码示例
4.4.1 RTCPeerConnection 实现
// webrtc/pc/peer_connection_impl.cc
class RTCPeerConnectionImpl : public RTCPeerConnection {
public:
RTCPeerConnectionImpl(const PeerConnectionInterface::Options& options)
: options_(options), signaling_thread_(nullptr), transport_(nullptr), media_engine_(nullptr) {
signaling_thread_ = new rtc::Thread("SignalingThread");
signaling_thread_->Start();
transport_ = new Transport();
transport_->Init();
media_engine_ = new MediaEngine();
media_engine_->Init();
}
void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options) override {
SessionDescriptionInterface* offer = media_engine_->CreateOffer(options);
local_description_ = offer;
if (signaling_channel_) signaling_channel_->SendOffer(offer);
observer->OnSuccess(offer);
}
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options) override {
SessionDescriptionInterface* answer = media_engine_->CreateAnswer(options);
local_description_ = answer;
if (signaling_channel_) signaling_channel_->SendAnswer(answer);
observer->OnSuccess(answer);
}
void SetLocalDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {
local_description_ = desc;
if (signaling_channel_) signaling_channel_->SendLocalDescription(desc);
observer->OnSuccess();
}
void SetRemoteDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {
remote_description_ = desc;
media_engine_->SetRemoteDescription(desc);
transport_->SetRemoteDescription(desc);
observer->OnSuccess();
}
void AddIceCandidate(const IceCandidateInterface* candidate) override {
ice_candidates_.push_back(candidate);
if (signaling_channel_) signaling_channel_->SendIceCandidate(candidate);
}
void OnIceConnectionStateChange(IceConnectionState state) override {
ice_connection_state_ = state;
if (ice_connection_state_observer_) {
ice_connection_state_observer_->OnIceConnectionStateChange(state);
}
}
private:
PeerConnectionInterface::Options options_;
rtc::Thread* signaling_thread_;
Transport* transport_;
MediaEngine* media_engine_;
SessionDescriptionInterface* local_description_;
SessionDescriptionInterface* remote_description_;
std::vector<IceCandidateInterface*> ice_candidates_;
IceConnectionState ice_connection_state_;
IceConnectionStateObserver* ice_connection_state_observer_;
SignalingChannel* signaling_channel_;
};
RTCPeerConnectionImpl是 RTCPeerConnection 的实现类- 通过组合模式管理传输模块、媒体引擎和信令通道
CreateOffer()和CreateAnswer()生成 SDP 描述SetLocalDescription()和SetRemoteDescription()设置本地和远程描述AddIceCandidate()添加 ICE 候选OnIceConnectionStateChange()处理 ICE 连接状态变化
4.4.2 信令通道实现
// webrtc/pc/signaling_channel_impl.h
class WebSocketSignalingChannel : public SignalingChannel {
public:
WebSocketSignalingChannel(const std::string& url) : url_(url), socket_(nullptr) {
Connect();
}
void SendOffer(const SessionDescriptionInterface* offer) override {
SignalingMessage message;
message.type = "sdp_offer";
message.data = offer->ToString();
Send(message);
}
void SendAnswer(const SessionDescriptionInterface* answer) override {
SignalingMessage message;
message.type = "sdp_answer";
message.data = answer->ToString();
Send(message);
}
void SendLocalDescription(const SessionDescriptionInterface* desc) override {
SignalingMessage message;
message.type = "sdp_local";
message.data = desc->ToString();
Send(message);
}
void SendIceCandidate(const IceCandidateInterface* candidate) override {
SignalingMessage message;
message.type = "ice_candidate";
message.data = candidate->candidate();
message.sdp_mid = candidate->sdp_mid();
message.sdp_mline_index = candidate->sdp_mline_index();
Send(message);
}
void SetMessageHandler(std::function<void(const SignalingMessage&)> handler) override {
message_handler_ = handler;
}
private:
void Connect() {
socket_ = new WebSocket(url_);
socket_->SetMessageHandler([this](const std::string& message) {
SignalingMessage msg;
ParseMessage(message, &msg);
if (message_handler_) message_handler_(msg);
});
}
void Send(const SignalingMessage& message) {
std::string json = SerializeMessage(message);
socket_->Send(json);
}
std::string url_;
WebSocket* socket_;
std::function<void(const SignalingMessage&)> message_handler_;
};
SignalingChannel是信令通道的接口类WebSocketSignalingChannel是 WebSocket 信令通道的实现类SendOffer()和SendAnswer()发送 SDP offer 和 answerSendIceCandidate()发送 ICE 候选SetMessageHandler()设置消息处理回调- 信令通道负责将 SDP 和 ICE 候选通过 WebSocket 发送给对端
4.5 信令模块工作时序
参与者 A -> 信令模块 -> 信令服务器 -> 信令模块 -> 参与者 B
1. 创建 RTCPeerConnection
2. 采集媒体流
3. CreateOffer -> 生成 SDP offer
4. 发送 SDP offer -> 转发 SDP offer
5. 创建 RTCPeerConnection
6. 采集媒体流
7. CreateAnswer -> 生成 SDP answer
8. 发送 SDP answer -> 转发 SDP answer
9. SetRemoteDescription -> 配置媒体引擎
10. AddIceCandidate -> 收集 ICE 候选
11. 通过 STUN 获取公网 IP -> 返回 ICE 候选
12. 发送 ICE 候选 -> 转发 ICE 候选
13. AddIceCandidate -> 设置 ICE 候选
14. 尝试建立 P2P 连接 -> 连接成功
15. 通知连接状态 -> 通知连接状态
16. 接收媒体流 -> 接收媒体流
4.6 信令模块核心流程
- 参与者 A:创建 RTCPeerConnection,采集媒体流,生成 SDP offer,通过信令服务器发送 offer
- 参与者 B:接收 offer,生成 SDP answer,通过信令服务器发送 answer
- 参与者 A:接收 answer,设置远程描述,配置媒体引擎,收集 ICE 候选,通过 STUN 获取公网 IP,发送 ICE 候选
- 参与者 B:接收 ICE 候选,设置 ICE 候选,尝试建立 P2P 连接,连接成功,传输媒体流
4.7 信令模块的关键技术
4.7.1 SDP(Session Description Protocol)
SDP 是 WebRTC 信令的核心,用于描述媒体会话的参数,包括:
- 会话名称
- 会话时间
- 媒体类型(音频、视频)
- 编解码器
- 分辨率
- 带宽
- ICE 候选地址
SDP 格式示例:
v=0 o=- 123456 1 IN IP4 127.0.0.1 s=- t=0 0 m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 c=IN IP4 192.168.1.100 a=rtcp:9 IN IP4 192.168.1.100 a=rtpmap:111 opus/48000/2 a=fmtp:111 minptime=10;useinbandfec=1 a=sendrecv
4.7.2 ICE 候选交换
ICE 候选是 NAT 穿透的关键,包括:
- Host Candidate:本地网络地址
- Server Reflexive Candidate:NAT 反射地址
- Relay Candidate:TURN 中继地址
ICE 候选格式示例:
candidate:1 1 udp 2130706431 192.168.1.100 54321 typ host
candidate:2 1 udp 1686052607 203.0.113.1 54321 typ srflx raddr 192.168.1.100 rport 54321
candidate:3 1 udp 1500000000 198.51.100.1 54321 typ relay raddr 192.168.1.100 rport 54321
4.7.3 信令协议
WebRTC 没有定义具体的信令协议,开发者可以使用各种方式,如:
- WebSocket
- XMPP
- SIP
- HTTP
- MQTT
信令消息格式示例:
{"type":"sdp_offer","data":"v=0\r\no=- 123456 1 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104\r\nc=IN IP4 192.168.1.100\r\na=rtcp:9 IN IP4 192.168.1.100\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=sendrecv\r\n"}
4.8 信令模块的异常处理
4.8.1 连接失败处理
pc.oniceconnectionstatechange = () => {
if (pc.iceconnectionstate() == "disconnected") {
restartIce();
}
};
function restartIce() {
const offer = pc.createoffer();
pc.setlocaldescription(offer);
signaling_channel_->sendoffer(offer);
}
关键点:
- 监听 ICE 连接状态变化
- 当连接断开时,重新发起 ICE 协商
- 创建新的 offer 并发送给对端
4.8.2 媒体流中断处理
pc.addeventlistener("negotiationneeded", () => {
const transceiver = pc.gettransceivers()[0];
transceiver.setcodecpreferences(filtercodecs("vp9"));
});
关键点:
- 监听 negotiationneeded 事件
- 当媒体流中断时,切换编解码器
- 优先使用高效的编解码器如 VP9
4.9 信令模块的未来发展方向
更高效的信令协议
WebRTC 信令模块将采用更高效的信令协议:
- MQTT:轻量级消息传输协议,适合低带宽环境
- QUIC:基于 UDP 的多路复用传输协议,减少连接建立时间
- WebTransport:基于 Web 标准的传输协议,支持更丰富的信令功能
AI 增强的信令处理
WebRTC 信令模块将集成 AI 技术,实现更智能的信令处理:
- AI 信令优化:使用 AI 算法优化信令消息的发送和处理
- AI 连接预测:使用 AI 算法预测连接状态,提前进行优化
- AI 异常检测:使用 AI 算法检测连接异常,自动进行处理
信令与边缘计算结合
WebRTC 信令模块将与边缘计算结合,实现更高效的信令处理:
- 边缘信令服务器:在边缘节点部署信令服务器,减少延迟
- 本地信令处理:在设备端进行部分信令处理,减少对中心服务器的依赖
- 分布式信令网络:构建分布式信令网络,提高信令处理的可靠性和效率


