WebRTC - 架构
WebRTC - 架构
Section titled “WebRTC - 架构”WebRTC(Web Real-Time Communication,Web实时通信)的架构是多层次的,旨在无需插件即可在浏览器之间直接实现实时通信。理解其组成部分是有效利用其功能的关键。
原文教程包含一张图表,说明了WebRTC的层次。概念上,这可以分解如下:
- Web开发者API层(Web Developer API Layer): 这是最顶层,向JavaScript开发者开放。它包括核心API,例如
RTCPeerConnection(对等连接)、RTCDataChannel(数据通道)和MediaStream(媒体流,通过navigator.mediaDevices.getUserMedia获取)。 - WebRTC C++ API层(浏览器内部实现 - Browser Internals): 在JavaScript API之下,浏览器实现了一个标准化的C++ API,用于将JavaScript调用桥接到下层的引擎。这一层主要供浏览器厂商使用。
- 底层引擎和传输组件(Underlying Engines & Transport Components): 这一层包含几个关键组件:
-
* **语音引擎(Voice Engine)**: 处理音频,包括采集、编码/解码(Opus, G.711等)、回声消除、降噪和播放。
-
* **视频引擎(Video Engine)**: 管理视频处理,包括摄像头捕获、编码/解码(VP8, VP9, H.264, AV1等)、图像增强和渲染。
-
* **传输组件(Transport Components)**: 负责数据传输。这包括用于数据通道的SCTP(Stream Control Transmission Protocol,流控制传输协议)、用于媒体的SRTP(Secure Real-time Transport Protocol,安全实时传输协议)、用于保护数据通道和密钥交换的DTLS(Datagram Transport Layer Security,数据报传输层安全),以及用于NAT(Network Address Translation,网络地址转换)穿越和建立对等(peer-to-peer)连接的ICE(Interactive Connectivity Establishment,交互式连接建立)、STUN(Session Traversal Utilities for NAT,NAT会话穿越工具)和TURN(Traversal Using Relays around NAT,使用中继穿越NAT)。
-
* **会话管理(Session Management)**: 处理信令解释和连接的状态管理。
对于Web开发者而言,主要交互是与JavaScript API层进行。浏览器抽象了底层复杂性。
信令的客户端-服务器交互模型
Section titled “信令的客户端-服务器交互模型”虽然WebRTC实现了对等(peer-to-peer)的媒体和数据交换,但要发起和管理连接,需要一个信令机制(通常涉及一个服务器)。两种常见的概念模型是:
1. SIP梯形模型(SIP Trapezoid Model,简单WebRTC中较少见)
Section titled “1. SIP梯形模型(SIP Trapezoid Model,简单WebRTC中较少见)”原文教程展示了这种模型的图表。在这种模型中,两个对等方(用户A和用户B)可能使用由不同Web服务器(Web服务器A和Web服务器B)提供的Web应用。他们可能与一个中心信令服务器通信(或者甚至是可以互操作的独立信令服务器,例如使用SIP)。信令服务器帮助他们交换SDP(Session Description Protocol,会话描述协议)和ICE候选者(ICE candidates),以建立直接的 RTCPeerConnection。
这种模型更类似于传统的VoIP系统,但在基本的基于Web的WebRTC应用中较少见,因为用户通常连接到同一个应用服务器。
2. 三角模型(Triangle Model,WebRTC应用中常见)
Section titled “2. 三角模型(Triangle Model,WebRTC应用中常见)”原文教程也描述了这种模型。在这里,两个对等方(用户A和用户B)连接到同一个Web应用服务器。该服务器也承载信令逻辑(例如,一个WebSocket服务器)。用户通过这个中心服务器互相发现并交换信令消息,然后服务器协助建立媒体/数据的直接对等 RTCPeerConnection。由于其简单性以及对用户管理和信令的集中控制,这在基于Web的WebRTC应用中是一种非常普遍的模式。
核心WebRTC JavaScript API
Section titled “核心WebRTC JavaScript API”WebRTC JavaScript API由几个主要对象组成:
RTCPeerConnection: 用于建立和管理与对等方连接的核心组件。MediaStream(和MediaStreamTrack): 表示音频或视频数据流,通常通过navigator.mediaDevices.getUserMedia()从本地设备获取。RTCDataChannel: 启用对等方之间任意数据的双向传输。
RTCPeerConnection对象
Section titled “RTCPeerConnection对象”这个对象是WebRTC的主要入口点。它处理连接到对等方的复杂过程,包括NAT穿越、安全性、编解码器协商和媒体传输。它触发各种事件,通知应用程序连接的状态和生命周期(lifecycle)。
原文教程展示了一张图表,说明了关键的 RTCPeerConnection 事件,如 onicecandidate、ontrack(以前是 onaddstream),以及方法,如 createOffer、createAnswer、setLocalDescription、setRemoteDescription 和 addTrack(以前是 addStream)。
创建 RTCPeerConnection 非常直接:
const configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };const peerConnection = new RTCPeerConnection(configuration);
// Example event handler for incoming trackspeerConnection.ontrack = (event) => { // const remoteVideo = document.getElementById('remoteVideo'); // remoteVideo.srcObject = event.streams[0]; console.log('Remote track received:', event.track);};
// Example event handler for ICE candidatespeerConnection.onicecandidate = (event) => { if (event.candidate) { // Send the candidate to the remote peer via signaling server // signalingChannel.send({ candidate: event.candidate }); }};configuration 参数对于指定STUN/TURN服务器至关重要。
MediaStream API(navigator.mediaDevices.getUserMedia)
Section titled “MediaStream API(navigator.mediaDevices.getUserMedia)”现代浏览器通过 navigator.mediaDevices.getUserMedia() 方法提供对本地摄像头和麦克风的访问。关键方面:
- 它返回一个Promise(承诺),成功时解析为
MediaStream对象。 - 它需要用户权限才能访问设备。
- 可以指定约束(constraints)以请求特定的分辨率、帧率或特定设备。
获取本地媒体流的示例:
async function getLocalMedia() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); // const localVideo = document.getElementById('localVideo'); // localVideo.srcObject = stream; console.log('Local media stream obtained:', stream); return stream; } catch (error) { console.error('Error accessing media devices.', error); alert('Could not access camera/microphone: ' + error.message); }}
// To use it:// getLocalMedia().then(localStream => {// if (localStream) {// // Add tracks to peerConnection, etc.// localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));// }// });原文教程提供了类似的代码,但使用了较旧的、基于回调(callback)的 navigator.getUserMedia 和 video.src = window.URL.createObjectURL(stream)。现代方法使用Promise和 video.srcObject = stream。
请记住,getUserMedia(以及其他需要安全上下文的WebRTC API)通常仅适用于通过HTTPS或 localhost 提供的页面。
RTCDataChannel对象
Section titled “RTCDataChannel对象”除了媒体,WebRTC还允许使用 RTCDataChannel 发送任意数据。这对于文本聊天、文件共享、游戏状态同步等非常有用。
数据通道是从现有的 RTCPeerConnection 创建的:
// Assuming 'peerConnection' is an existing RTCPeerConnection instance
// Initiator side:const dataChannelOptions = { reliable: true, ordered: true };const dataChannel = peerConnection.createDataChannel("myChannelLabel", dataChannelOptions);
dataChannel.onopen = () => console.log('Data channel open');dataChannel.onmessage = (event) => console.log('Message received:', event.data);dataChannel.onclose = () => console.log('Data channel closed');dataChannel.onerror = (error) => console.error('Data channel error:', error);
// To send a message:// if (dataChannel.readyState === 'open') {// dataChannel.send('Hello from initiator!');// }
// Receiver side (setup within peerConnection.ondatachannel event):// peerConnection.ondatachannel = (event) => {// const receiveChannel = event.channel;// receiveChannel.onopen = () => console.log('Receive channel open');// receiveChannel.onmessage = (event) => console.log('Message from peer:', event.data);// // ... other handlers// };数据通道可以配置为可靠的(reliable)和有序的(ordered),模拟TCP的行为;或不可靠的(unreliable)和无序的(unordered),模拟UDP的行为。
本概述提供了对WebRTC架构及其核心JavaScript API的基础理解。这些组件在信令机制的协助下协同工作,使得在浏览器中直接构建强大的实时通信应用程序成为可能。随着WebRTC标准的不断发展,请始终参考最新的规范和浏览器文档,以获取最当前的信息。