# 项目概述 **本文档引用的文件** - [src/index.ts](file://src/index.ts) - [src/server.ts](file://src/server.ts) - [src/websocket.ts](file://src/websocket.ts) - [src/class/websockethandler.ts](file://src/class/websockethandler.ts) - [src/class/httphandler.ts](file://src/class/httphandler.ts) - [src/signaling.ts](file://src/signaling.ts) - [client/public/bidirectional/js/main.js](file://client/public/bidirectional/js/main.js) - [client/public/onebyone/main.js](file://client/public/onebyone/main.js) - [client/src/peer.js](file://client/src/peer.js) - [client/src/sender.js](file://client/src/sender.js) - [package.json](file://package.json) - [client/package.json](file://client/package.json) - [src/log.ts](file://src/log.ts) - [src/class/options.ts](file://src/class/options.ts) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 Video Socket Server 是一个基于 WebRTC 的实时双向视频通信服务端与前端示例项目,支持两种信令模式(WebSocket 与 HTTP 轮询)与两种通信模式(公共模式与私有模式)。项目旨在为 Unity Render Streaming、远程视频监控、在线教育等场景提供低延迟、高可靠性的视频传输基础设施。 - 核心目标 - 提供稳定可靠的 WebRTC 信令与媒体转发能力 - 支持公共模式(广播式)与私有模式(点对点/一对多) - 提供 WebSocket 与 HTTP 两种信令通道,适配不同网络环境 - 提供丰富的前端示例,覆盖双向视频通话、一对一通话、输入遥测等 - 技术定位 - 后端:Node.js + TypeScript + Express.js - 前端:原生 JavaScript(ES Modules),结合 WebRTC API - 协议:WebSocket(ws:// 或 wss://)与 HTTP RESTful 接口 - 数据结构:Offer/Answer 与 ICE Candidate 的信令封装 - 主要应用场景 - Unity Render Streaming:通过 WebRTC 实现远端渲染画面的低延迟传输 - 远程视频监控:支持多路摄像头与回放控制 - 在线教育:支持课堂互动、屏幕共享与聊天 **章节来源** - [src/index.ts:13-109](file://src/index.ts#L13-L109) - [src/server.ts:14-90](file://src/server.ts#L14-L90) ## 项目结构 项目采用前后端分离的组织方式: - 后端(src):服务启动、HTTP 路由、WebSocket 信令、日志与配置 - 前端(client):静态资源与示例页面,包含多个演示场景(双向视频、一对一通话、输入遥测等) ```mermaid graph TB subgraph "后端(src)" IDX["入口: index.ts"] SRV["HTTP服务: server.ts"] WS["WebSocket信令: websocket.ts"] WSH["WS处理器: class/websockethandler.ts"] HTH["HTTP处理器: class/httphandler.ts"] SIG["信令路由: signaling.ts"] LOG["日志: log.ts"] OPT["配置: class/options.ts"] end subgraph "前端(client)" PUB["静态资源: public/*"] SRC["模块: src/*"] end IDX --> SRV SRV --> SIG SRV --> PUB SRV --> SRC SRV --> WS WS --> WSH SIG --> HTH IDX --> LOG IDX --> OPT ``` **图表来源** - [src/index.ts:13-109](file://src/index.ts#L13-L109) - [src/server.ts:14-90](file://src/server.ts#L14-L90) - [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118) - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) - [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800) - [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25) **章节来源** - [package.json:1-60](file://package.json#L1-L60) - [client/package.json:1-19](file://client/package.json#L1-L19) ## 核心组件 - 服务入口与启动 - 解析命令行参数,创建 HTTP/HTTPS 服务器,根据配置选择信令模式 - 启动 WebSocket 信令或 HTTP 轮询信令 - HTTP 服务与静态资源 - 提供 /config 接口返回运行配置(是否使用 WebSocket、启动模式、日志级别) - 提供 /signaling 路由,挂载 HTTP 信令处理器 - 提供静态页面与模块资源,首页自动指向 client/public/index.html - WebSocket 信令 - 监听连接、消息、关闭事件,解析多种信令类型(connect/disconnect/offer/answer/candidate/broadcast/ping/pong/call-request/on-message) - 将消息分派至 WS 处理器进行业务逻辑处理 - WS 处理器(1对多/私有模式) - 维护连接组(host 与 participants),支持广播与定向转发 - 处理 offer/answer/candidate 的路由与转发,支持 participantId 标识 - HTTP 信令处理器(HTTP 轮询) - 提供会话管理与连接管理接口,支持轮询获取信令消息 - 支持超时会话清理与断开连接记录 - 日志与配置 - 可配置日志级别,统一输出格式 - Options 接口定义运行参数(端口、证书、信令类型、通信模式、日志级别) **章节来源** - [src/index.ts:13-109](file://src/index.ts#L13-L109) - [src/server.ts:14-90](file://src/server.ts#L14-L90) - [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118) - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) - [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800) - [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25) - [src/log.ts:1-51](file://src/log.ts#L1-L51) - [src/class/options.ts:1-10](file://src/class/options.ts#L1-L10) ## 架构总览 系统采用“HTTP 服务 + WebSocket/HTTP 信令”的双信令架构,支持公共模式与私有模式两种通信策略。 ```mermaid graph TB subgraph "客户端" FE1["双向视频示例
bidirectional/main.js"] FE2["一对一通话示例
onebyone/main.js"] PEER["Peer类
peer.js"] SEND["输入遥测Sender
sender.js"] end subgraph "服务端" HTTP["HTTP服务
server.ts"] WS["WebSocket信令
websocket.ts"] WSH["WS处理器
websockethandler.ts"] HTH["HTTP处理器
httphandler.ts"] SIG["信令路由
signaling.ts"] end FE1 --> |WebSocket/HTTP| HTTP FE2 --> |WebSocket/HTTP| HTTP HTTP --> SIG HTTP --> WS WS --> WSH SIG --> HTH FE1 --> PEER FE2 --> PEER FE1 --> SEND ``` **图表来源** - [src/server.ts:14-90](file://src/server.ts#L14-L90) - [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118) - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) - [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800) - [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25) - [client/public/bidirectional/js/main.js:1-383](file://client/public/bidirectional/js/main.js#L1-L383) - [client/public/onebyone/main.js:1-216](file://client/public/onebyone/main.js#L1-L216) - [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188) - [client/src/sender.js:1-209](file://client/src/sender.js#L1-L209) ## 详细组件分析 ### WebSocket 信令流程(序列图) 展示客户端通过 WebSocket 发送/接收信令的典型流程。 ```mermaid sequenceDiagram participant C as "客户端" participant WS as "WebSocket服务器" participant H as "WS处理器" C->>WS : "connect" 连接建立 WS->>H : "onConnect(connectionId)" H-->>C : "connect" {connectionId, role, participantId} C->>WS : "offer" {connectionId, sdp} WS->>H : "onOffer(ws, message)" H-->>C : "offer" 转发/广播 C->>WS : "answer" {connectionId, sdp} WS->>H : "onAnswer(ws, message)" H-->>C : "answer" 转发/广播 C->>WS : "candidate" {connectionId, candidate, sdpMLineIndex, sdpMid} WS->>H : "onCandidate(ws, message)" H-->>C : "candidate" 转发/广播 C->>WS : "disconnect" {connectionId} WS->>H : "onDisconnect(ws, connectionId)" H-->>C : "disconnect" 通知 ``` **图表来源** - [src/websocket.ts:65-114](file://src/websocket.ts#L65-L114) - [src/class/websockethandler.ts:145-206](file://src/class/websockethandler.ts#L145-L206) - [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338) - [src/class/websockethandler.ts:309-338](file://src/class/websockethandler.ts#L309-L338) **章节来源** - [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118) - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) ### HTTP 信令轮询流程(序列图) 展示客户端通过 HTTP 轮询获取信令消息的流程。 ```mermaid sequenceDiagram participant C as "客户端" participant S as "HTTP服务" participant R as "信令路由" participant H as "HTTP处理器" C->>S : "PUT /signaling" 创建会话 S->>R : "路由到 httphandler" R->>H : "createSession()" H-->>C : "{sessionId}" C->>S : "PUT /signaling/connection" {connectionId} S->>R : "路由到 httphandler" R->>H : "createConnection()" H-->>C : "{connectionId, polite}" loop 轮询 C->>S : "GET /signaling/offer?fromtime=..." S->>R : "路由到 httphandler" R->>H : "getOffer(fromtime)" H-->>C : "{offers}" end C->>S : "POST /signaling/offer" {sdp} S->>R : "路由到 httphandler" R->>H : "postOffer()" H-->>C : "OK" C->>S : "DELETE /signaling" 删除会话 S->>R : "路由到 httphandler" R->>H : "deleteSession()" H-->>C : "200" ``` **图表来源** - [src/server.ts:25-89](file://src/server.ts#L25-L89) - [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24) - [src/class/httphandler.ts:661-696](file://src/class/httphandler.ts#L661-L696) - [src/class/httphandler.ts:268-318](file://src/class/httphandler.ts#L268-L318) - [src/class/httphandler.ts:492-501](file://src/class/httphandler.ts#L492-L501) - [src/class/httphandler.ts:549-558](file://src/class/httphandler.ts#L549-L558) **章节来源** - [src/server.ts:14-90](file://src/server.ts#L14-L90) - [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25) - [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800) ### 前端组件与 WebRTC 集成 - 双向视频示例(bidirectional) - 通过 RenderStreaming 管理连接,动态选择 WebSocket 或 HTTP 信令 - 使用 Peer 类封装 RTCPeerConnection 生命周期与事件 - 使用 Sender 类实现鼠标/键盘/手柄/触摸的输入遥测与数据通道发送 - 一对一通话示例(onebyone) - 基于 store/UIRenderer 的状态管理与 UI 渲染 - 支持通话请求、接听/拒接、媒体切换、录制控制等 ```mermaid classDiagram class Peer { +connectionId +polite +pc +ontrack() +ondatachannel() +onicecandidate() +onnegotiationneeded() +getTransceivers() +addTrack() +addTransceiver() +createDataChannel() +getStats() +onGotDescription() +onGotCandidate() } class Sender { +devices +addMouse() +addKeyboard() +addGamepad() +addTouchscreen() +_queueStateEvent() +_queueTextEvent() } class Observer { +channel +onNext(message) } Sender --> Observer : "通过数据通道发送" Peer --> Sender : "配合输入遥测" ``` **图表来源** - [client/src/peer.js:3-188](file://client/src/peer.js#L3-L188) - [client/src/sender.js:14-209](file://client/src/sender.js#L14-L209) **章节来源** - [client/public/bidirectional/js/main.js:1-383](file://client/public/bidirectional/js/main.js#L1-L383) - [client/public/onebyone/main.js:1-216](file://client/public/onebyone/main.js#L1-L216) - [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188) - [client/src/sender.js:1-209](file://client/src/sender.js#L1-L209) ### 通信模式与连接组(流程图) 展示私有模式下的连接组管理与消息转发逻辑。 ```mermaid flowchart TD Start(["进入 onConnect"]) --> CheckPrivate{"是否私有模式?"} CheckPrivate --> |否| Public["公共模式: 创建连接组(若无)"] CheckPrivate --> |是| Private["私有模式: host/参与者管理"] Public --> BroadcastOffer["广播 offer 给其他客户端"] Private --> HostCheck{"是否已有 host?"} HostCheck --> |否| CreateHost["创建 host 并标记为 polite=false"] HostCheck --> |是| AddParticipant["添加为 participant 并通知 host"] OfferRoute{"消息来源角色"} --> |host| ToParticipants["转发给所有 participants"] OfferRoute --> |participant| ToHost["转发给 host"] AnswerRoute{"消息来源角色"} --> |host| ToTarget["转发给指定 participant"] AnswerRoute --> |participant| ToHost2["转发给 host"] CandidateRoute{"消息来源角色"} --> |host| ToParticipants2["转发给所有 participants"] CandidateRoute --> |participant| ToHost3["转发给 host"] ``` **图表来源** - [src/class/websockethandler.ts:145-206](file://src/class/websockethandler.ts#L145-L206) - [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338) - [src/class/websockethandler.ts:309-338](file://src/class/websockethandler.ts#L309-L338) **章节来源** - [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479) ## 依赖分析 - 后端依赖 - express:HTTP 服务框架 - ws:WebSocket 服务器 - morgan:HTTP 访问日志 - cors/multer:跨域与文件上传 - uuid:会话 ID 生成 - commander:命令行参数解析 - 前端依赖 - Jest(开发):单元测试 - ESLint(开发):代码规范 - 浏览器原生 WebRTC API ```mermaid graph LR P["package.json"] --> E["express"] P --> W["ws"] P --> M["morgan"] P --> C["cors"] P --> U["uuid"] P --> CMD["commander"] CP["client/package.json"] --> J["jest"] CP --> ESL["eslint"] ``` **图表来源** - [package.json:14-46](file://package.json#L14-L46) - [client/package.json:9-18](file://client/package.json#L9-L18) **章节来源** - [package.json:1-60](file://package.json#L1-L60) - [client/package.json:1-19](file://client/package.json#L1-L19) ## 性能考虑 - 信令模式选择 - WebSocket:低延迟、高吞吐,适合实时交互 - HTTP 轮询:兼容性更好,适合受限网络或代理环境 - 通信模式选择 - 私有模式:host 与 participants 明确分离,便于控制与扩展 - 公共模式:广播式转发,适合简单场景但需注意带宽与 CPU 开销 - 日志与监控 - 可配置日志级别,避免生产环境过度输出 - 建议结合浏览器 WebRTC 统计 API 与服务端日志进行性能分析 - 媒体参数 - 合理设置分辨率、帧率与编解码器偏好,平衡画质与延迟 [本节为通用指导,无需具体文件分析] ## 故障排查指南 - 启动与证书 - HTTPS 启用需提供 server.key 与 server.cert;可通过命令行参数指定路径 - 若证书缺失,服务将以 HTTP 方式启动 - 信令类型校验 - 仅支持 websocket 与 http 两种类型;非法值会被重置为 websocket - WebSocket 心跳与断开 - 服务器内置心跳检测(ping/pong),长时间无活动将触发断开 - 客户端需正确处理断开事件并清理资源 - HTTP 会话超时 - 会话在指定时间内无请求将被清理,避免内存泄漏 - 客户端应定期轮询或及时释放会话 **章节来源** - [src/index.ts:75-82](file://src/index.ts#L75-L82) - [src/websocket.ts:95-113](file://src/websocket.ts#L95-L113) - [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232) - [src/log.ts:1-51](file://src/log.ts#L1-L51) ## 结论 Video Socket Server 提供了完整的 WebRTC 信令与媒体传输方案,具备灵活的信令与通信模式选择、清晰的前后端分离架构,以及丰富的前端示例。通过合理配置与优化,可在多种实际场景中实现高质量的实时视频通信。 [本节为总结性内容,无需具体文件分析] ## 附录 - 快速启动 - 开发模式:执行脚本 dev,启动 HTTPS 服务,监听指定端口 - 生产模式:构建后运行 build/index.js,或使用打包工具 - 常用接口 - GET /config:获取运行配置 - GET /signaling/connection-ids:获取所有连接 ID - PUT /signaling:创建会话 - PUT /signaling/connection:创建连接 - GET /signaling/offer|answer|candidate:轮询获取信令 - POST /signaling/offer|answer|candidate:推送信令 - DELETE /signaling:删除会话 **章节来源** - [src/server.ts:25-89](file://src/server.ts#L25-L89) - [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24) - [package.json:5-12](file://package.json#L5-L12)