437 lines
18 KiB
Markdown
437 lines
18 KiB
Markdown
|
|
# 一对一通信示例
|
|||
|
|
|
|||
|
|
<cite>
|
|||
|
|
**本文引用的文件**
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [index.html](file://client/public/onebyone/index.html)
|
|||
|
|
- [connect.html](file://client/public/onebyone/connect/connect.html)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|
|||
|
|
</cite>
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
1. [简介](#简介)
|
|||
|
|
2. [项目结构](#项目结构)
|
|||
|
|
3. [核心组件](#核心组件)
|
|||
|
|
4. [架构总览](#架构总览)
|
|||
|
|
5. [详细组件分析](#详细组件分析)
|
|||
|
|
6. [依赖关系分析](#依赖关系分析)
|
|||
|
|
7. [性能考量](#性能考量)
|
|||
|
|
8. [故障排查指南](#故障排查指南)
|
|||
|
|
9. [结论](#结论)
|
|||
|
|
10. [附录](#附录)
|
|||
|
|
|
|||
|
|
## 简介
|
|||
|
|
本项目是一对一视频通话示例,基于浏览器 WebRTC 技术实现点对点(P2P)视频通话,包含连接建立、媒体协商、通话管理、聊天消息与用户界面等完整功能。本文档将深入解析代码架构,涵盖数据模型、状态管理、视图渲染、连接流程与通话结束处理,并提供扩展、定制与集成建议。
|
|||
|
|
|
|||
|
|
## 项目结构
|
|||
|
|
客户端采用模块化组织,核心目录与文件如下:
|
|||
|
|
- onebyone 目录:一对一通话主界面与相关模块
|
|||
|
|
- models.js:数据模型定义
|
|||
|
|
- store.js:状态管理与 WebRTC 会话控制
|
|||
|
|
- renderer.js:视图渲染器,负责将状态映射到 DOM
|
|||
|
|
- main.js:应用入口,绑定事件与初始化
|
|||
|
|
- index.html:主界面 HTML 模板
|
|||
|
|
- connect/:连接界面
|
|||
|
|
- connect.html:初始连接界面
|
|||
|
|
- connect.js:连接界面逻辑
|
|||
|
|
- endcall/:通话结束界面
|
|||
|
|
- endcall.html:结束界面
|
|||
|
|
- endcall.js:结束逻辑
|
|||
|
|
- chatmessage.js:聊天消息模块
|
|||
|
|
- utils.js:工具函数
|
|||
|
|
- public/js:通用配置与 ICE 设置
|
|||
|
|
- config.js:获取服务器配置与 RTC 配置
|
|||
|
|
- icesettings.js:ICE 服务器配置持久化与读取
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
subgraph "客户端(onebyone)"
|
|||
|
|
A["index.html<br/>主界面"]
|
|||
|
|
B["main.js<br/>入口与事件绑定"]
|
|||
|
|
C["store.js<br/>状态管理/WebRTC"]
|
|||
|
|
D["renderer.js<br/>视图渲染"]
|
|||
|
|
E["models.js<br/>数据模型"]
|
|||
|
|
F["chatmessage.js<br/>聊天消息"]
|
|||
|
|
G["utils.js<br/>工具函数"]
|
|||
|
|
H["connect/connect.html<br/>连接界面"]
|
|||
|
|
I["connect/connect.js<br/>连接逻辑"]
|
|||
|
|
J["endcall/endcall.js<br/>结束逻辑"]
|
|||
|
|
end
|
|||
|
|
subgraph "公共配置"
|
|||
|
|
K["config.js<br/>服务器/RTC配置"]
|
|||
|
|
L["icesettings.js<br/>ICE服务器持久化"]
|
|||
|
|
end
|
|||
|
|
A --> B
|
|||
|
|
B --> C
|
|||
|
|
B --> D
|
|||
|
|
B --> F
|
|||
|
|
C --> D
|
|||
|
|
C --> F
|
|||
|
|
C --> E
|
|||
|
|
C --> K
|
|||
|
|
K --> L
|
|||
|
|
H --> I
|
|||
|
|
A --> J
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [index.html](file://client/public/onebyone/index.html)
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [connect/connect.html](file://client/public/onebyone/connect/connect.html)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [index.html](file://client/public/onebyone/index.html)
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [connect/connect.html](file://client/public/onebyone/connect/connect.html)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|
|||
|
|
|
|||
|
|
## 核心组件
|
|||
|
|
- 数据模型(models.js)
|
|||
|
|
- 定义通话会话、本地/远端用户、媒体状态、聊天消息等类型与模拟数据
|
|||
|
|
- 状态管理(store.js)
|
|||
|
|
- 使用简单观察者模式管理应用状态,封装 WebRTC 连接、媒体轨道、编解码器偏好、编码参数、网络质量检测、音频活动检测、消息广播等
|
|||
|
|
- 视图渲染(renderer.js)
|
|||
|
|
- 将状态映射到 DOM,支持多参与者网格、占位符、占位符切换、分辨率自适应、网络质量指示等
|
|||
|
|
- 连接界面(connect/connect.js)
|
|||
|
|
- 提供创建/加入通话、连接 ID 列表浏览、用户设置(头像、昵称、ID)、头像上传等功能
|
|||
|
|
- 通话结束界面(endcall/endcall.js)
|
|||
|
|
- 提供重新连接与离开选项
|
|||
|
|
- 聊天消息(chatmessage.js)
|
|||
|
|
- 负责消息的发送、接收、显示、未读计数与侧边栏切换
|
|||
|
|
- 工具函数(utils.js)
|
|||
|
|
- 时间格式化、通知、元素显示/隐藏、按钮状态切换等
|
|||
|
|
- 应用入口(main.js)
|
|||
|
|
- 初始化渲染器、绑定 DOM 事件、键盘快捷键、挂断确认对话框等
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
|
|||
|
|
## 架构总览
|
|||
|
|
整体采用“状态驱动”的架构:store.js 维护核心状态,renderer.js 响应状态变化更新 UI;WebRTC 通过 RenderStreaming 实例进行媒体协商与传输;聊天消息通过 WebSocket 或信令通道传递;配置通过 config.js 与 icesettings.js 提供 STUN/TURN 与媒体约束。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant U as "用户"
|
|||
|
|
participant M as "main.js"
|
|||
|
|
participant S as "store.js"
|
|||
|
|
participant R as "renderer.js"
|
|||
|
|
participant RS as "RenderStreaming(WebRTC)"
|
|||
|
|
participant WS as "WebSocket/信令"
|
|||
|
|
U->>M : 打开主界面
|
|||
|
|
M->>S : 初始化并加入通话
|
|||
|
|
S->>RS : 创建连接并启动
|
|||
|
|
RS-->>S : 连接建立回调
|
|||
|
|
S->>R : 通知 CALL_STATUS_CHANGE/ONGOING
|
|||
|
|
S->>WS : 发送 user-info / media-state-changed
|
|||
|
|
WS-->>S : 接收 chat-message / media-state-changed / user-info
|
|||
|
|
S->>R : 通知 REMOTE_STREAM_OBTAINED / USER_LIST_UPDATE
|
|||
|
|
R-->>U : 渲染远端视频/用户列表/网络质量
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
|
|||
|
|
## 详细组件分析
|
|||
|
|
|
|||
|
|
### 数据模型(models.js)
|
|||
|
|
- 类型定义
|
|||
|
|
- CallSession:通话会话,包含通话类型、状态、起始时间、时长、加密标志、本地/远端用户信息
|
|||
|
|
- LocalUser/RemoteUser:用户信息,含媒体状态与网络质量
|
|||
|
|
- MediaState:音频/视频/屏幕共享/录屏/说话检测状态
|
|||
|
|
- ChatMessage:消息结构,含发送者信息、内容、类型、时间戳与是否自已发送
|
|||
|
|
- 模拟数据
|
|||
|
|
- 提供 mockCallSession 与 mockMessages,便于开发调试与演示
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
|
|||
|
|
### 状态管理(store.js)
|
|||
|
|
- 核心职责
|
|||
|
|
- 初始化与本地媒体流获取、媒体状态变更、WebRTC 连接建立与回调注册
|
|||
|
|
- 编解码器偏好设置、视频编码参数动态调整、分辨率切换
|
|||
|
|
- 网络质量检测、音频活动检测、统计信息输出
|
|||
|
|
- 聊天消息广播、用户信息同步、成员列表广播
|
|||
|
|
- 通话结束处理(挂断、清理、通知)
|
|||
|
|
- 关键流程
|
|||
|
|
- 连接建立:_createSignalingAndRTC -> setUp -> _registerCallbacks -> _startConnection
|
|||
|
|
- 媒体协商:onNewPeer/addTransceiver/setCodecPreferences/setVideoEncodingParameters
|
|||
|
|
- 状态通知:notify -> renderer 渲染
|
|||
|
|
- 媒体状态变化:emitMediaStateChange -> WebSocket 广播
|
|||
|
|
- 网络质量:detectNetworkQuality -> 综合丢包率/抖动/RTT 评估
|
|||
|
|
- 音频活动:startActivityDetection -> VAD 检测
|
|||
|
|
- 设计要点
|
|||
|
|
- 观察者模式:subscribe/notify 解耦状态与 UI
|
|||
|
|
- 可扩展性:编解码器与编码参数策略可按平台能力扩展
|
|||
|
|
- 容错性:轨道替换、占位符延迟通知、分辨率回退
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
classDiagram
|
|||
|
|
class CallStateManager {
|
|||
|
|
+state
|
|||
|
|
+listeners
|
|||
|
|
+init()
|
|||
|
|
+setUp(connectionId)
|
|||
|
|
+updateLocalMedia(type, value)
|
|||
|
|
+hangUp()
|
|||
|
|
+broadcastParticipantsList()
|
|||
|
|
+setCodecPreferences(participantId)
|
|||
|
|
+setVideoEncodingParameters(participantId)
|
|||
|
|
+changeResolution(width, height)
|
|||
|
|
+emitMediaStateChange()
|
|||
|
|
+detectNetworkQuality()
|
|||
|
|
+startActivityDetection(stream, options)
|
|||
|
|
+showStatsMessage()
|
|||
|
|
}
|
|||
|
|
class UIRenderer {
|
|||
|
|
+render(state, changes)
|
|||
|
|
+renderRemoteStream(stream, connectionId, isHost)
|
|||
|
|
+renderUserList(localUser, remoteUser, participants)
|
|||
|
|
}
|
|||
|
|
CallStateManager --> UIRenderer : "通知状态变化"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
|
|||
|
|
### 视图渲染(renderer.js)
|
|||
|
|
- 渲染策略
|
|||
|
|
- 基于变化类型分派渲染:INIT、DURATION_UPDATE、LOCAL_MEDIA_CHANGE、REMOTE_STREAM_OBTAINED、REMOTE_MEDIA_CHANGE、USER_LIST_UPDATE、NETWORK_CHANGE、CALL_STATUS_CHANGE、CALL_ENDED、PARTICIPANT_LEFT、RESOLUTION_CHANGED
|
|||
|
|
- 支持多参与者网格(Host 端)与单路远端视频(Participant 端)
|
|||
|
|
- 占位符与占位符切换:音频先到、视频后到时延迟通知,避免黑屏
|
|||
|
|
- 网络质量指示:根据远端网络质量更新头部与侧边栏
|
|||
|
|
- 分辨率自适应:监听视频轨道 resize 事件调整显示尺寸
|
|||
|
|
- 交互与事件
|
|||
|
|
- 绑定事件监听器(由 main.js 绑定),响应按钮与快捷键
|
|||
|
|
- 侧边栏开关与未读计数联动
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [index.html](file://client/public/onebyone/index.html)
|
|||
|
|
|
|||
|
|
### 连接建立(connect/connect.js)
|
|||
|
|
- 功能
|
|||
|
|
- 加入通话:校验连接 ID,保存到本地存储,跳转主界面
|
|||
|
|
- 创建通话:生成随机连接 ID,保存并跳转主界面
|
|||
|
|
- 浏览连接 ID:调用 /signaling/connection-ids 获取列表并展示
|
|||
|
|
- 用户设置:昵称、头像、用户 ID,支持头像上传(/api/upload/avatar)
|
|||
|
|
- 交互
|
|||
|
|
- 输入框回车触发加入
|
|||
|
|
- 选择连接 ID 自动填充
|
|||
|
|
- 设置菜单外点击关闭
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [connect/connect.html](file://client/public/onebyone/connect/connect.html)
|
|||
|
|
|
|||
|
|
### 通话结束处理(endcall/endcall.js)
|
|||
|
|
- 功能
|
|||
|
|
- 重新连接:跳转主界面
|
|||
|
|
- 离开:清除本地连接 ID,回到连接界面
|
|||
|
|
- 交互
|
|||
|
|
- 页面加载时显示断开连接信息(连接 ID 与时间)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
|
|||
|
|
### 聊天消息(chatmessage.js)
|
|||
|
|
- 功能
|
|||
|
|
- 消息状态管理:消息列表、未读计数、侧边栏开关
|
|||
|
|
- 发送消息:构造消息对象,通过 store 发送到远端
|
|||
|
|
- 接收消息:handleChatMessage -> addMessage -> 通知 UI
|
|||
|
|
- 图片消息:限制大小、读取为 DataURL、发送文件消息
|
|||
|
|
- 未读通知:侧边栏关闭时累加未读,打开时清零
|
|||
|
|
- 事件绑定
|
|||
|
|
- sendMessage/handleChatSubmit/openImagePicker/handleImageUpload
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
|
|||
|
|
### 工具函数(utils.js)
|
|||
|
|
- 功能
|
|||
|
|
- formatTime/formatTimestamp:时间格式化
|
|||
|
|
- generateId:生成唯一 ID
|
|||
|
|
- showNotification:通知组件显示与隐藏
|
|||
|
|
- toggleElement/toggleButtonState:元素与按钮状态切换
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
|
|||
|
|
### 应用入口(main.js)
|
|||
|
|
- 功能
|
|||
|
|
- 初始化渲染器与聊天模块
|
|||
|
|
- 绑定 DOM 事件:静音/视频切换、录屏、更多选项、分辨率切换、结束通话确认
|
|||
|
|
- 键盘快捷键:Space 静音、Ctrl+V 切换视频
|
|||
|
|
- 接收通话请求弹窗:接受/拒绝
|
|||
|
|
- 页面加载后检查连接 ID,初始化并启动 WebRTC 连接
|
|||
|
|
- 交互
|
|||
|
|
- 对话框事件绑定、更多选项菜单外点击关闭
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [index.html](file://client/public/onebyone/index.html)
|
|||
|
|
|
|||
|
|
## 依赖关系分析
|
|||
|
|
- 模块依赖
|
|||
|
|
- main.js 依赖 store、renderer、chatmessage、utils
|
|||
|
|
- store.js 依赖 models、config、icesettings、chatmessage、utils
|
|||
|
|
- renderer.js 依赖 models、chatmessage、utils、store
|
|||
|
|
- connect/connect.js 依赖 utils
|
|||
|
|
- endcall/endcall.js 依赖 utils
|
|||
|
|
- config.js 依赖 icesettings.js
|
|||
|
|
- 外部依赖
|
|||
|
|
- WebRTC API(getUserMedia、RTCPeerConnection、RTCRtpTransceiver)
|
|||
|
|
- WebSocket/信令通道(用于媒体状态、用户信息、聊天消息、参与者列表同步)
|
|||
|
|
- 服务器接口:/config、/api/upload/avatar、/signaling/connection-ids
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
main_js["main.js"] --> store_js["store.js"]
|
|||
|
|
main_js --> renderer_js["renderer.js"]
|
|||
|
|
main_js --> chat_js["chatmessage.js"]
|
|||
|
|
store_js --> models_js["models.js"]
|
|||
|
|
store_js --> config_js["config.js"]
|
|||
|
|
store_js --> chat_js
|
|||
|
|
renderer_js --> models_js
|
|||
|
|
renderer_js --> chat_js
|
|||
|
|
renderer_js --> utils_js["utils.js"]
|
|||
|
|
store_js --> utils_js
|
|||
|
|
connect_js["connect/connect.js"] --> utils_js
|
|||
|
|
endcall_js["endcall/endcall.js"] --> utils_js
|
|||
|
|
config_js --> icesettings_js["icesettings.js"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [main.js](file://client/public/onebyone/main.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [utils.js](file://client/public/onebyone/utils.js)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
- [endcall/endcall.js](file://client/public/onebyone/endcall/endcall.js)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|
|||
|
|
|
|||
|
|
## 性能考量
|
|||
|
|
- 媒体轨道管理
|
|||
|
|
- 音频先到、视频后到时延迟通知,避免黑屏与频繁 UI 刷新
|
|||
|
|
- 替换视频轨道时保留音频轨道,减少资源开销
|
|||
|
|
- 编解码器与编码参数
|
|||
|
|
- 优先选择 AV1/VP9,回退 H264,提升压缩效率
|
|||
|
|
- 根据采集分辨率动态设置最大比特率,平衡画质与带宽
|
|||
|
|
- 网络质量检测
|
|||
|
|
- 丢包率、抖动、RTT 综合评估,定期更新网络质量指示
|
|||
|
|
- 统计信息
|
|||
|
|
- 定时输出视频/音频统计,便于诊断与优化
|
|||
|
|
- 分辨率切换
|
|||
|
|
- 使用 applyConstraints 实时调整,避免重新获取流
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
|
|||
|
|
## 故障排查指南
|
|||
|
|
- 无法获取本地媒体流
|
|||
|
|
- 检查 getUserMedia 权限与约束;若失败,保持媒体状态关闭并通知 UI
|
|||
|
|
- 远端视频黑屏
|
|||
|
|
- 确认音频轨道先到时的延迟通知逻辑;检查轨道是否正确添加到 MediaStream
|
|||
|
|
- 连接状态异常
|
|||
|
|
- 检查 onConnect/onDisconnect 回调;确认信令通道正常
|
|||
|
|
- 媒体状态不同步
|
|||
|
|
- 确认 emitMediaStateChange 是否被调用;检查 onMessage 中 media-state-changed 分发
|
|||
|
|
- 网络质量指示不更新
|
|||
|
|
- 确认 startNetworkQualityDetection 是否启动;检查 detectNetworkQuality 统计字段
|
|||
|
|
- 头像上传失败
|
|||
|
|
- 检查文件类型与大小限制;确认 /api/upload/avatar 接口可用
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [connect/connect.js](file://client/public/onebyone/connect/connect.js)
|
|||
|
|
|
|||
|
|
## 结论
|
|||
|
|
本示例通过清晰的模块划分与状态驱动架构,实现了稳定的一对一视频通话体验。其关键优势在于:
|
|||
|
|
- 状态与 UI 解耦,易于扩展与维护
|
|||
|
|
- 完整的媒体协商与网络质量处理
|
|||
|
|
- 丰富的聊天与用户信息同步机制
|
|||
|
|
- 友好的用户界面与交互体验
|
|||
|
|
|
|||
|
|
建议在生产环境中进一步完善:
|
|||
|
|
- 使用成熟的状态管理库(如 Redux/Pinia)替代简易观察者模式
|
|||
|
|
- 增强错误处理与重连机制
|
|||
|
|
- 集成更多媒体能力检测与自适应策略
|
|||
|
|
- 优化统计信息展示与告警机制
|
|||
|
|
|
|||
|
|
## 附录
|
|||
|
|
|
|||
|
|
### 开发指南:扩展与定制
|
|||
|
|
- 扩展聊天功能
|
|||
|
|
- 新增消息类型:在 ChatMessage 类型中扩展 type 字段,更新 chatmessage.js 的发送/接收逻辑
|
|||
|
|
- 文件上传:参考 handleImageUpload 的流程,扩展更多文件类型与大小限制
|
|||
|
|
- 自定义界面
|
|||
|
|
- 修改 index.html 的布局与样式,注意与 renderer.js 的 DOM 选择器保持一致
|
|||
|
|
- 新增控制按钮:在 main.js 绑定事件并在 store 中实现对应逻辑
|
|||
|
|
- 集成其他服务
|
|||
|
|
- 服务器配置:通过 /config 接口返回 useWebSocket 等配置,store.js 中据此选择 WebSocketSignaling 或 Signaling
|
|||
|
|
- ICE 服务器:通过 icesettings.js 的持久化配置,支持多 STUN/TURN 服务器
|
|||
|
|
- WebRTC 优化
|
|||
|
|
- 编解码器与编码参数:根据设备能力动态调整,提升兼容性与画质
|
|||
|
|
- 分辨率与帧率:结合网络状况动态调整,保证流畅度
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [models.js](file://client/public/onebyone/models.js)
|
|||
|
|
- [store.js](file://client/public/onebyone/store.js)
|
|||
|
|
- [renderer.js](file://client/public/onebyone/renderer.js)
|
|||
|
|
- [chatmessage.js](file://client/public/onebyone/chatmessage.js)
|
|||
|
|
- [config.js](file://client/public/js/config.js)
|
|||
|
|
- [icesettings.js](file://client/public/js/icesettings.js)
|