# WebRTC 直播组件说明 ## 概述 `WebRTCVideo` 是一个基于 WebRTC 的实时视频直播 Vue 3 组件,用于从远端摄像头设备接收音视频流并在浏览器中播放。组件通过 WebSocket 信令服务器与设备建立 P2P 连接,支持自动重连、画面冻结检测、截图、扬声器/麦克风控制等功能。 技术栈:Vue 3 Composition API + TypeScript + Element Plus。 ## 连接流程 整个直播连接分为三个阶段:**信令协商 → ICE 连接 → 媒体播放**。 ``` 组件挂载 │ ├─ 1. 建立 WebSocket 信令连接 │ ws://{host}:{port}/wswebclient/{meid} │ ├─ 2. WebSocket 打开后发送 __connectto(告诉服务器要连哪个设备) │ ├─ 3. 服务器返回 _create(设备在线状态 + ICE 服务器配置) │ ├─ 4. 发送 __call(发起呼叫,携带音视频方向、认证信息) │ ├─ 5. 服务器返回 _call 或 _offer(SDP 协商开始) │ ├─ 收到 _call → 创建 PeerConnection → createOffer → 发送 __offer │ └─ 收到 _offer → 创建 PeerConnection → createAnswer → 发送 __answer │ ├─ 6. 收到 _answer → setRemoteDescription(SDP 协商完成) │ ├─ 7. ICE Candidate 交换(__ice_candidate / _ice_candidate) │ ├─ 8. ICE 连接建立(checking → connected) │ ├─ 9. 远端 Track 到达 → video.srcObject 赋值 → video.play() │ └─ 10. 画面显示,进入稳定播放状态 ``` 正常情况下,从 WebSocket 打开到画面显示约 100-500ms。 ## 信令消息说明 | 方向 | 消息 | 说明 | |------|------|------| | → 发送 | `__connectto` | 请求连接指定设备 | | ← 接收 | `_create` | 设备状态(online/offline)及 ICE 配置 | | → 发送 | `__call` | 发起呼叫,携带音视频方向和认证信息 | | ← 接收 | `_call` / `_offer` | 服务器要求创建 Offer 或直接下发 Offer | | → 发送 | `__offer` / `__answer` | SDP 协商 | | ← 接收 | `_answer` | 远端 SDP 应答 | | ↔ 双向 | `__ice_candidate` / `_ice_candidate` | ICE 候选地址交换 | | → 发送 | `__ping` | 心跳保活(每 30 秒) | | → 发送 | `__disconnected` | 主动断开通知 | | ← 接收 | `_session_failed` | 会话失败,需要重新连接 | | ← 接收 | `_session_disconnected` | 远端断开通知 | | ← 接收 | `_connectinfo` | 连接信息(调试用) | ## 重要功能 ### 自动重连机制 - **心跳保活**:每 2 秒检测 WebSocket 状态,断开后自动重建连接 - **WebSocket 握手超时**:超过设定时间未连接成功则关闭并重试 - **Session 失败重试**:收到 `_session_failed` 后立即用新 sessionId 重新发起连接 - **ICE 断连恢复**:ICE 状态变为 disconnected/failed 时,如果 WebSocket 还活着则立即重新发起信令协商 - **组件卸载通知**:离开页面或切换路由时主动发送 `__disconnected`,让服务器立即清理旧 session ### 画面冻结检测(Watchdog) 每 3 秒通过 `RTCPeerConnection.getStats()` 检查视频流的 `bytesReceived`: - 如果连续 3 次(约 9 秒)没有新数据到达,判定为画面冻结 - 先尝试 ICE Restart(`createOffer({ iceRestart: true })`)恢复连接 - ICE Restart 失败则完全重连 - 同时检测 `