标签

WebRTC

WebRTC(Web Real-Time Communication)是一个允许在网页浏览器之间直接进行实时通讯的技术。这个开放标准的目标是使网页应用程序能够进行实时音频、视频和数据传输,而无需安装插件或下载本地应用。

WebRTC
服务端5月30日 00:37
什么是 WebRTC?它的核心组成部分有哪些?WebRTC 是浏览器里的实时音视频和数据通信能力,核心价值是不用插件就能让两个端建立低延迟连接。它主要由三块组成:媒体采集用 `getUserMedia` 拿摄像头、麦克风;连接与协商用 `RTCPeerConnection` 处理 SDP、ICE、加密和媒体传输;任意数据传输用 `RTCDataChannel`。另外要记住:WebRTC 不自带信令服务,房间、呼叫、offer/answer 和 candidate 交换通常由业务用 WebSocket 或 HTTP 自己实现。 ## 追问 ### WebRTC 是完全点对点吗? 不一定。能直连时媒体可以 P2P;直连失败会走 TURN 中继;多人会议通常还会用 SFU 转发媒体流,所以“WebRTC 等于 P2P”这个说法不准确。 ### RTCPeerConnection 具体负责什么? 它负责创建 offer/answer、管理 ICE 候选、建立 DTLS/SRTP 安全传输,并把本地媒体轨道发送给对端。简单说,它是 WebRTC 连接的核心对象。 ### 信令为什么不算 WebRTC 标准的一部分? 因为不同业务的房间模型、鉴权、重连和消息格式差异很大。标准只规定浏览器如何生成 SDP 和 candidate,至于怎么传给对端,由业务决定。 ### getUserMedia 和 RTCDataChannel 有什么区别? `getUserMedia` 采集音视频流,适合通话、录制、屏幕共享。`RTCDataChannel` 传任意数据,适合聊天、白板同步、文件分片或游戏状态同步。 ## 写段代码 ```js const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true }) const pc = new RTCPeerConnection({ iceServers }) stream.getTracks().forEach(track => pc.addTrack(track, stream)) const channel = pc.createDataChannel('chat') ```
服务端5月30日 00:37
WebRTC 如何实现 NAT 穿透?STUN、TURN 和 ICE 分别做什么?WebRTC 的 NAT 穿透不是靠某一个协议硬打洞,而是由 ICE 统一调度:先收集本地地址,再用 STUN 拿到公网映射地址,最后在直连失败时走 TURN 中继。面试里可以这样答:STUN 负责“我在公网看起来是谁”,TURN 负责“直连不通时替我转发”,ICE 负责“把所有候选路径试一遍,选能通且质量最好的”。生产环境只配 STUN 不够,遇到对称 NAT、企业防火墙或 UDP 被限制时,必须有 TURN 兜底。 ## 追问 ### STUN 和 TURN 有什么区别? STUN 只参与建连阶段,帮助发现公网 IP 和端口,媒体流通常仍然点对点传输。TURN 会一直在媒体路径上转发数据,成功率高,但延迟、带宽成本和服务器压力都更大。 ### ICE 候选者有哪些? 常见有 host、srflx、relay 三类。host 是本机局域网地址,srflx 是 STUN 得到的公网映射地址,relay 是 TURN 分配的中继地址。 ### 为什么有 STUN 还需要 TURN? 因为 STUN 依赖 NAT 映射可预测。对称 NAT 或严格防火墙下,对端无法直接打到这个映射端口,TURN 中继就成了最后的可用路径。 ### 实际项目里怎么配置? 至少配置一个 STUN 和一个带鉴权的 TURN,TURN 建议靠近用户部署。监控里要看 relay 占比、ICE 失败率、连接耗时和 RTT,relay 占比突然升高通常说明网络或 STUN 可用性出问题。 ## 写段代码 ```js const pc = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, { urls: 'turn:turn.example.com:3478', username: 'u', credential: 'p' } ] }) pc.onicecandidate = e => sendToPeer(e.candidate) ```
服务端5月29日 22:54
WebRTC 如何控制音视频质量?码率/分辨率/帧率的动态调节策略是什么?## WebRTC 如何控制音视频质量?码率/分辨率/帧率的动态调节策略是什么? WebRTC 通过 **GCC(Google Congest Control)** 算法自动估算带宽,动态调节编码参数,核心机制: **自动调节**: - **带宽探测**:发送端逐步增加码率,检测丢包率上升则回退(AIMD 策略) - **编码器适配**:VP8/VP9/H264 编码器根据目标码率自动调整量化参数 - **帧率调节**:带宽不足时降低帧率优先保分辨率,极低带宽才降分辨率 **手动控制 API**: ```javascript const sender = pc.getSenders()[0]; const params = sender.getParameters(); params.encodings[0].maxBitrate = 500000; // 500kbps params.encodings[0].maxFramerate = 15; params.encodings[0].scaleResolutionDownBy = 2; // 分辨率减半 sender.setParameters(params); ``` **音频处理**: - **NetEQ**:抖动缓冲 + PLC(丢包隐藏),平滑播放 - **AEC**:回声消除,防止扬声器声音被麦克风拾取 - **NS/ANR**:噪声抑制,过滤背景噪声 - **AGC**:自动增益控制,稳定音量 **视频处理**:关键帧请求(PLI/FIR)应对丢包,Simulcast 发多路流供 SFU 选择。 ### 追问 1. **Simulcast 是什么?如何工作?** — 同时发送多分辨率/码率流,SFU 按接收端带宽转发对应路 2. **如何检测网络质量变差?** — 监听 getStats 的 packetsLost、jitterBufferDelay、availableOutgoingBitrate 3. **AEC 在什么场景下效果差?** — 延迟超过 200ms、非线性失真严重、多声源场景 4. **setParameters 和 replaceTrack 有什么区别?** — setParameters 调编码参数不变轨道,replaceTrack 换整个轨道(如切换摄像头)
服务端5月29日 22:54
WebRTC 安全吗?DTLS/SRTP 加密原理和常见风险有哪些?## WebRTC 安全吗?DTLS/SRTP 加密原理和常见风险有哪些? WebRTC **强制加密**:所有媒体流走 SRTP,数据通道走 DTLS,密钥通过 DTLS 握手在 ICE 连接建立后协商,默认端到端加密。 **加密链路**: - **信令**:HTTPS/WSS 传输 SDP,信令服务器可看明文(所以选可信信令服务) - **媒体**:DTLS 握手协商密钥 → SRTP 加密音视频包 → 中间人无法解密 - **数据通道**:DTLS 直接加密,SCTP 传输 **潜在安全风险**: 1. **信令劫持**:SDP 明文经信令服务器,恶意服务器可篡改 SDP 注入攻击者 ICE Candidate(MITM) 2. **IP 泄露**:ICE Candidate 包含本地/公网 IP,即使经过 VPN 也会泄露真实 IP 3. **TURN 中继窃听**:TURN 服务器可解密中继流量,需选择可信 TURN 提供商 4. **屏幕共享滥用**:getDisplayMedia 无限制可能泄露敏感信息,应约束分享区域 5. **DDoS 利用**:WebRTC 可被用来发起 UDP 泛洪攻击 **防护措施**:验证远端指纹(remoteDescription.fingerprint)、限制 ICE Candidate 类型隐藏 IP、信令用 Token 鉴权。 ### 追问 1. **DTLS 和 TLS 有什么区别?** — DTLS 基于 UDP,增加重传和乱序处理,握手流程类似但容忍丢包 2. **如何防止 IP 通过 ICE 泄露?** — 设置 iceTransportPolicy 为 relay 仅用 TURN,或 filter 掉 host Candidate 3. **WebRTC 能做到零信任吗?** — 需要 Insertable Streams 在应用层再做一层端到端加密 4. **TURN 服务器如何选择才安全?** — 自建优于第三方,审计日志,限制中继流量配额
服务端5月29日 22:54
WebRTC 如何与 Socket.io 和 Node.js 后端集成?信令服务怎么设计?## WebRTC 如何与 Socket.io 和 Node.js 后端集成?信令服务怎么设计? WebRTC 本身只解决 P2P 媒体传输,**信令交换**(SDP Offer/Answer、ICE Candidate)必须通过独立信令通道完成,Socket.io + Node.js 是最常见组合。 **架构**:浏览器 A 通过 Socket.io 将 SDP Offer 发给 Node.js 信令服务器 → 服务器转发给浏览器 B → B 回传 Answer → 双方交换 ICE Candidate → P2P 连接建立。 **核心集成点**: 1. **Socket.io 信令**:事件驱动,房间模型天然适合多方通话。emit/offer、on/answer、ice-candidate 三组事件即可完成信令 2. **Node.js TURN 服务**:P2P 穿透失败时需中继,Node.js 可管理 TURN 服务器分配 3. **录制集成**:Node.js + FFmpeg 接收 WebRTC 流转码存储,或用 MediaRecorder API 浏览器端录制 4. **权限控制**:Node.js 中间件校验房间 Token,防止未授权加入 **典型信令流程**: ``` join room → emit('offer') → broadcast → emit('answer') → exchange ICE → RTCPeerConnection connected ``` 注意事项:Socket.io 不保证消息顺序,ICE Candidate 可能乱序到达,但 WebRTC 内部会缓存排序;大规模房间需改用 SFU(如 mediasoup)代替 Mesh。 ### 追问 1. **信令服务器能用 HTTP 代替 WebSocket 吗?** — 可以但延迟高,HTTP 轮询不适合实时 ICE 交换 2. **多人通话信令如何设计?** — 每对用户建立 PeerConnection,新用户加入时向房间内所有人发 Offer 3. **如何集成 mediasoup 做 SFU?** — Node.js worker 管理 Router/Transport,WebRTC 端通过 produce/consume 订阅流 4. **Socket.io 和原生 WebSocket 怎么选?** — Socket.io 自带房间/重连/命名空间,开发效率高;原生 WebSocket 更轻量性能更好
服务端5月28日 02:13
WebRTC的数据通道有什么作用?如何使用它传输非媒体数据?WebRTC 数据通道(Data Channel)是 WebRTC 中与媒体通道并列的传输机制,基于 SCTP over DTLS 协议栈,在浏览器之间建立加密的点对点连接来传输任意二进制或文本数据。 ## 数据通道的核心作用 **与媒体通道的区别**:媒体通道使用 SRTP 传输音视频,而数据通道使用 SCTP over DTLS 传输非媒体数据。两者共享同一个 ICE 传输层,但走不同的协议栈,互不干扰。 **相比 WebSocket 的优势**:WebSocket 需要服务器中继,数据经由服务端转发;数据通道建立后直接在两端之间传输,省去服务器中转的延迟和带宽开销。API 设计上与 WebSocket 高度相似,降低了学习成本。 **关键特性**: - **DTLS 加密**:所有数据自动经过 DTLS 加密,无需应用层额外处理 - **全双工通信**:双方可同时收发,不存在方向限制 - **可靠性可配置**:通过 `ordered`、`maxRetransmits`、`maxPacketLifeTime` 三个参数,可在可靠有序(类 TCP)和不可靠无序(类 UDP)之间自由选择 - **NAT 穿透**:复用 ICE 框架的 NAT 穿透能力,无需额外处理 ## 数据通道的协议栈 理解协议栈有助于在面试中讲清"为什么数据通道既能可靠传输又能低延迟": ``` 应用层数据 ↓ SCTP(流控传输协议,提供多流、可靠/部分可靠传输) ↓ DTLS(加密层,提供安全性) ↓ UDP(ICE 协商后的 P2P 通道) ``` SCTP 支持在同一关联上建立多个流(Stream),每个数据通道对应一个 SCTP 流,通道间互不阻塞。SCTP 的"部分可靠"扩展(PR-SCTP)使得配置 `maxRetransmits` 和 `maxPacketLifeTime` 成为可能,这是数据通道灵活性的根源。 ## 创建数据通道 ```javascript const pc = new RTCPeerConnection(config); // 创建方(Offerer)主动创建 const channel = pc.createDataChannel('chat', { ordered: true, // 保证消息有序到达 maxRetransmits: 3, // 最多重传3次,超出则丢弃 // maxPacketLifeTime: 3000, // 与maxRetransmits二选一,消息最大存活时间(ms) protocol: 'text', // 子协议标识 negotiated: false, // false=自动协商,true=手动指定id }); ``` **参数说明**: - `ordered: true` + `maxRetransmits: null` + `maxPacketLifeTime: null` = TCP 模式(可靠有序) - `ordered: false` + `maxRetransmits: 0` = UDP 模式(不可靠无序) - `maxRetransmits` 和 `maxPacketLifeTime` 互斥,只能设一个 ## 监听事件与收发数据 ```javascript // 发送方 channel.onopen = () => { // 通道就绪后才能发送 channel.send('Hello!'); }; channel.onmessage = (e) => { console.log('收到:', e.data); }; channel.onclose = () => { console.log('通道关闭'); }; // 接收方(被动方通过 ondatachannel 获取) pc.ondatachannel = (e) => { const rc = e.channel; rc.onmessage = (ev) => { console.log('收到:', ev.data); }; rc.onopen = () => { rc.send('收到你的消息'); }; }; ``` **发送数据的三种格式**: ```javascript channel.send('字符串'); // string → PPID 51 channel.send(new ArrayBuffer(8)); // binary → PPID 53 channel.send(new Blob(['data'])); // binary → PPID 53 ``` SCTP 内部通过 PPID(Payload Protocol Identifier)区分 UTF-8 文本(51)和二进制数据(53),接收方 `onmessage` 的 `event.data` 会自动还原为 `string` 或 `ArrayBuffer`。 ## 缓冲区管理与背压 数据通道有发送缓冲区,持续发送大量数据而不检查缓冲区会导致内存暴涨甚至通道崩溃: ```javascript // 检查缓冲区是否快满 if (channel.bufferedAmount > channel.bufferedAmountLowThreshold) { // 暂停发送,等待缓冲区排空 channel.onbufferedamountlow = () => { // 恢复发送 sendNextChunk(); }; return; } channel.send(chunk); ``` `bufferedAmountLowThreshold` 默认为 0,建议设为缓冲区容量的 1/4 左右。这是面试中常被追问的实战细节。 ## 常见应用场景 | 场景 | 配置建议 | 原因 | |------|---------|------| | 实时游戏状态同步 | `ordered: false, maxRetransmits: 0` | 旧状态无需重传,只要最新帧 | | 协作白板 | `ordered: true, maxRetransmits: 3` | 操作顺序不能乱,但偶尔丢帧可接受 | | 文件传输 | `ordered: true`(默认可靠模式) | 文件必须完整到达 | | 聊天消息 | `ordered: true`(默认可靠模式) | 消息不能丢、不能乱序 | | IoT 传感器数据 | `ordered: false, maxPacketLifeTime: 1000` | 传感器数据实时性优先 | ## 面试追问方向 - **数据通道能传多大消息?** 理论上 SCTP 支持最大 1 GiB 的消息(通过分片重组),但实际受浏览器实现限制,建议单条消息不超过 64 KiB,大文件应分块传输。 - **数据通道和 WebSocket 怎么选?** 需要服务器中转或一对多广播用 WebSocket;需要点对点低延迟且能接受 ICE 协商开销用数据通道。两者也可以混合使用。 - **`negotiated: true` 是什么?** 跳过 DCEP 协商,双方通过约定相同的 `id` 手动创建通道,减少一次 RTT 的协商开销。
服务端5月28日 02:07
WebRTC的信令过程是怎样的?为什么需要信令服务器?## WebRTC的信令过程是怎样的?为什么需要信令服务器? WebRTC 本身只负责音视频采集、编解码和点对点传输,但在两个浏览器建立直连之前,它们需要先交换一些关键信息——这个过程就叫信令(Signaling)。信令是 WebRTC 连接建立的前置环节,没有它,两个隔离在各自网络里的浏览器根本找不到对方。 ### 信令过程的核心步骤 信令过程可以拆成两个并行的子流程:SDP 协商和 ICE 候选交换。它们不是串行的,而是几乎同时进行。 #### SDP 协商:双方就"用什么格式通话"达成一致 1. 呼叫方创建 `RTCPeerConnection`,调用 `createOffer()` 生成 SDP Offer 2. 呼叫方调用 `setLocalDescription()` 保存本地描述,然后通过信令服务器将 Offer 转发给应答方 3. 应答方收到 Offer 后调用 `setRemoteDescription()` 设置远端描述 4. 应答方调用 `createAnswer()` 生成 SDP Answer,再通过信令服务器回传 5. 呼叫方收到 Answer 后调用 `setRemoteDescription()` 完成协商 SDP 里包含了什么?媒体格式(编解码器、payload type)、带宽限制、ICE 账号密码、DTLS 指纹等。双方通过 Offer/Answer 交换这些信息,选出共同支持的编码方案。 #### ICE 候选交换:双方就"通过哪条网络路径连接"达成一致 1. 双方创建 `RTCPeerConnection` 后,ICE Agent 开始收集候选地址 2. 每发现一个候选,触发 `onicecandidate` 事件,通过信令服务器发送给对方 3. 对方收到后调用 `addIceCandidate()` 添加候选 ICE 候选有三种类型: - **Host 候选**:本机网卡地址,优先级最高 - **Server Reflexive 候选(srflx)**:通过 STUN 服务器获取的公网映射地址 - **Relay 候选(relay)**:TURN 服务器分配的中继地址,优先级最低但穿透能力最强 实际项目中常用 Trickle ICE 策略:不等所有候选收集完毕,而是找到一个就发一个,加快连接速度。 #### 连接建立 SDP 协商和 ICE 候选交换完成后,ICE 会对候选对进行连通性检查。一旦找到可用的路径,DTLS 握手随即完成,SRTP 通道建立,双方开始传输音视频数据。 ### 为什么需要信令服务器? WebRTC 规范故意不定义信令协议,但信令服务器在连接建立中不可或缺,原因如下: **NAT 穿透的必要条件** 大多数设备在 NAT 或防火墙后面,无法直接被外部访问。信令服务器是双方交换 ICE 候选的唯一通道——没有它,两个浏览器根本不知道对方的公网地址和端口,也无法协调 STUN/TURN 的使用。 **媒体协商的桥梁** 两个浏览器支持的编解码器可能不同(比如 Chrome 支持 VP8/VP9/AV1,Safari 可能只支持 H.264)。SDP 协商让双方在连接建立前就确定好共同支持的编码方案,避免连接成功却发现无法解码的尴尬。 **会话状态管理** 实际应用中还需要处理房间创建、用户加入/离开、通话挂断等业务逻辑。这些都不在 WebRTC 规范内,需要信令服务器配合业务层实现。 **安全认证的起点** DTLS 证书指纹通过 SDP 传递,确保连接建立后双方可以验证对方身份。如果指纹不匹配,连接会被拒绝。信令服务器是这个信任链的传输通道。 ### 信令协议怎么选? WebRTC 不限制信令协议,常见的选型: - **WebSocket**:最主流的方案,全双工、低延迟,适合实时通信场景 - **Socket.io**:在 WebSocket 基础上加了房间、广播等语义,开发效率高 - **HTTP 轮询**:实时性差,仅作为降级方案 生产环境建议使用 WSS(加密的 WebSocket),防止信令数据被截获或篡改。 ### 常见踩坑 - 忘记在 `setRemoteDescription` 之前设置好 `ontrack` 等事件监听,导致远端流丢失 - ICE 候选在 SDP 协商完成前到达,调用 `addIceCandidate()` 会报错,需要做缓冲处理 - 信令服务器只存在单进程内存中,服务器重启所有房间丢失,建议用 Redis 共享会话状态
服务端5月28日 00:58
WebRTC应用性能优化的常见问题有哪些?如何从延迟、带宽、编解码三个维度逐项解决?WebRTC实时通信的性能直接影响用户体验,卡顿、延迟、画质下降等问题在生产环境中频繁出现。下面从延迟、带宽、编解码、音视频处理和监控五个维度,逐项分析常见问题并给出可落地的解决方案。 ## 网络延迟:高延迟导致音视频不同步 高延迟是WebRTC应用最常见也最影响体验的问题,通常表现为视频卡顿、音频不同步或对话出现明显滞后。 **核心原因**:ICE候选路径选择不当、STUN/TURN服务器距离远、DTLS握手耗时过长。 **解决方案**: - 就近部署STUN/TURN服务器,减少物理链路距离。通过`iceServers`配置多个候选服务器: ```javascript const config = { iceServers: [ { urls: 'stun:stun-cn.example.com:3478' }, { urls: 'turn:turn-cn.example.com:3478', username: 'user', credential: 'pass' } ] }; const pc = new RTCPeerConnection(config); ``` - 优化ICE候选排序,优先选择srflx(服务器反射)和relay(中继)类型中RTT最低的路径。监听`onicecandidate`事件收集全部候选后再创建Offer,避免Trickle ICE带来的次优路径选择。 - DTLS-SRTP握手从3-RTT缩减为0-RTT。在重复连接场景中复用之前协商的会话密钥,WebRTC M120+版本已支持`dtlsRestart`配置。 ## 带宽不足:自适应码率策略与降级方案 带宽受限时视频画质骤降甚至连接断开,这在移动网络和弱网环境下尤为突出。 **核心原因**:固定码率无法适应网络波动、同时传输多路视频流抢占带宽。 **解决方案**: - 实现自适应码率(ABR),根据`RTCPeerConnection.getStats()`返回的可用带宽动态调整发送参数: ```javascript async function adjustBitrate(pc) { const stats = await pc.getStats(); stats.forEach(report => { if (report.type === 'outbound-rtp' && report.kind === 'video') { const availableBitrate = report.bitrate || 0; const sender = pc.getSenders().find(s => s.track.kind === 'video'); if (sender) { const params = sender.getParameters(); if (!params.encodings[0]) params.encodings = [{}]; params.encodings[0].maxBitrate = Math.min(availableBitrate * 0.8, 2500000); sender.setParameters(params); } } }); } ``` - 弱网降级策略:音频优先于视频,先降低帧率再降低分辨率。设置媒体约束时预留降级空间: ```javascript const constraints = { video: { width: { ideal: 1280, max: 1920 }, height: { ideal: 720, max: 1080 }, frameRate: { ideal: 30, max: 30 } }, audio: true }; ``` - 多路通话场景使用Simulcast(联播),发送高低两种分辨率的视频流,SFU服务器根据接收端带宽选择转发哪一路。 ## 编解码与CPU开销:硬件加速与编码参数调优 CPU占用过高会导致编解码延迟增大、设备发热和帧率下降。 **核心原因**:软编解码占用CPU、分辨率和帧率设置过高、编码参数未针对实时场景优化。 **解决方案**: - 强制使用硬件编解码。检查浏览器是否支持硬件加速,优先选择H.264(硬件加速支持最广)或VP9(压缩率高但编码慢): ```javascript const preferredCodecs = [ { mimeType: 'video/H264', clockRate: 90000 }, { mimeType: 'video/VP8', clockRate: 90000 } ]; const transceiver = pc.addTransceiver('video', { direction: 'sendrecv', sendEncodings: [{ maxBitrate: 2000000 }] }); transceiver.setCodecPreferences(preferredCodecs); ``` - 关键参数调优:设置`maxFramerate`为24-30fps(视频会议不需要60fps),开启`scalabilityMode: 'L1T3'`实现时域可伸缩编码,弱网时自动丢弃非关键帧。 - 减少不必要的处理步骤:关闭不用的`MediaStreamTrack`,避免空轨道占用编码资源。 ## 音视频处理:卡顿、回声与噪声 视频卡顿来自Jitter Buffer配置不当,音频回声和噪声来自信号处理不充分。 **视频卡顿解决方案**: - 调整Jitter Buffer大小,在延迟和流畅度之间取平衡。WebRTC默认自适应,极端场景下可通过SDP协商调整`maxptime`参数。 - 使用NACK+FEC组合抗丢包:NACK请求重传关键帧,FEC对每组包添加冗余数据实现前向纠错。在5%以下丢包率靠NACK,5%-20%丢包率需要FEC配合。 - 平滑码率调整:避免瞬间大幅改变编码参数,使用指数移动平均平滑带宽估计值。 **音频回声与噪声解决方案**: - 启用WebRTC内置三大音频处理模块:AEC(回声消除)、NS(噪声抑制)、AGC(自动增益控制)。这些在Chrome中默认开启,但需要确认音频约束正确: ```javascript const audioConstraints = { audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true, sampleRate: { ideal: 48000 } } }; ``` - 回声问题严重时优先使用耳机。扬声器场景下增大AEC滤波器长度,适配大房间混响。 ## 监控与运维:从数据中发现性能瓶颈 性能优化不能靠猜测,需要建立系统化的监控体系。 **关键监控指标**: - 通过`getStats()`采集核心指标:RTT(往返延迟)、packetsLost(丢包数)、jitter(抖动)、bytesSent/bytesReceived(吞吐量)、framesPerSecond(帧率)。 ```javascript setInterval(async () => { const stats = await pc.getStats(); stats.forEach(report => { if (report.type === 'candidate-pair' && report.state === 'succeeded') { console.log('RTT:', report.currentRoundTripTime * 1000, 'ms'); } if (report.type === 'inbound-rtp') { console.log(report.kind, 'packetsLost:', report.packetsLost); console.log(report.kind, 'jitter:', report.jitter, 's'); } }); }, 5000); ``` - Chrome DevTools中访问`chrome://webrtc-internals/`查看连接级别的详细图表。 - 生产环境搭建端到端监控:客户端采集指标上报到服务端,按房间、用户、时段聚合分析,设置RTT>200ms或丢包率>5%的告警阈值。 **资源管理**: - 及时关闭不用的`RTCPeerConnection`和`MediaStreamTrack`,调用`close()`释放资源,避免内存泄漏。 - 多路通话中合理管理发送/接收流数量,1对多场景使用SFU架构代替Mesh架构,降低客户端上行带宽和CPU压力。 **服务器端优化**: - TURN服务器选择Coturn,开启`fingerprint`和`lt-cred-mech`,配置合理的会话超时和端口范围。 - 负载均衡:多台TURN服务器前挂负载均衡器,基于地理IP路由到最近节点。 - CDN分发非实时媒体资源(如录制回放),减少源站压力。 以上五个维度的优化措施需要根据实际业务场景选择优先级。对于实时音视频应用,延迟和带宽是首要解决的问题;对于大规模会议场景,编解码效率和服务器架构是关键瓶颈。持续监控、数据驱动的调优比一次性优化更有价值。