Files
video_socket-server/.qoder/repowiki/zh/content/客户端示例/一对一通信示例.md
2026-05-16 13:24:02 +08:00

18 KiB
Raw Blame History

一对一通信示例

**本文引用的文件** - [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)

目录

  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.jsICE 服务器配置持久化与读取
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

图表来源

章节来源

核心组件

  • 数据模型models.js
    • 定义通话会话、本地/远端用户、媒体状态、聊天消息等类型与模拟数据
  • 状态管理store.js
    • 使用简单观察者模式管理应用状态,封装 WebRTC 连接、媒体轨道、编解码器偏好、编码参数、网络质量检测、音频活动检测、消息广播等
  • 视图渲染renderer.js
    • 将状态映射到 DOM支持多参与者网格、占位符、占位符切换、分辨率自适应、网络质量指示等
  • 连接界面connect/connect.js
    • 提供创建/加入通话、连接 ID 列表浏览、用户设置头像、昵称、ID、头像上传等功能
  • 通话结束界面endcall/endcall.js
    • 提供重新连接与离开选项
  • 聊天消息chatmessage.js
    • 负责消息的发送、接收、显示、未读计数与侧边栏切换
  • 工具函数utils.js
    • 时间格式化、通知、元素显示/隐藏、按钮状态切换等
  • 应用入口main.js
    • 初始化渲染器、绑定 DOM 事件、键盘快捷键、挂断确认对话框等

章节来源

架构总览

整体采用“状态驱动”的架构store.js 维护核心状态renderer.js 响应状态变化更新 UIWebRTC 通过 RenderStreaming 实例进行媒体协商与传输;聊天消息通过 WebSocket 或信令通道传递;配置通过 config.js 与 icesettings.js 提供 STUN/TURN 与媒体约束。

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 : 渲染远端视频/用户列表/网络质量

图表来源

详细组件分析

数据模型models.js

  • 类型定义
    • CallSession通话会话包含通话类型、状态、起始时间、时长、加密标志、本地/远端用户信息
    • LocalUser/RemoteUser用户信息含媒体状态与网络质量
    • MediaState音频/视频/屏幕共享/录屏/说话检测状态
    • ChatMessage消息结构含发送者信息、内容、类型、时间戳与是否自已发送
  • 模拟数据
    • 提供 mockCallSession 与 mockMessages便于开发调试与演示

章节来源

状态管理store.js

  • 核心职责
    • 初始化与本地媒体流获取、媒体状态变更、WebRTC 连接建立与回调注册
    • 编解码器偏好设置、视频编码参数动态调整、分辨率切换
    • 网络质量检测、音频活动检测、统计信息输出
    • 聊天消息广播、用户信息同步、成员列表广播
    • 通话结束处理(挂断、清理、通知)
  • 关键流程
    • 连接建立_createSignalingAndRTC -> setUp -> _registerCallbacks -> _startConnection
    • 媒体协商onNewPeer/addTransceiver/setCodecPreferences/setVideoEncodingParameters
    • 状态通知notify -> renderer 渲染
    • 媒体状态变化emitMediaStateChange -> WebSocket 广播
    • 网络质量detectNetworkQuality -> 综合丢包率/抖动/RTT 评估
    • 音频活动startActivityDetection -> VAD 检测
  • 设计要点
    • 观察者模式subscribe/notify 解耦状态与 UI
    • 可扩展性:编解码器与编码参数策略可按平台能力扩展
    • 容错性:轨道替换、占位符延迟通知、分辨率回退
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 : "通知状态变化"

图表来源

章节来源

视图渲染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 绑定),响应按钮与快捷键
    • 侧边栏开关与未读计数联动

章节来源

连接建立connect/connect.js

  • 功能
    • 加入通话:校验连接 ID保存到本地存储跳转主界面
    • 创建通话:生成随机连接 ID保存并跳转主界面
    • 浏览连接 ID调用 /signaling/connection-ids 获取列表并展示
    • 用户设置:昵称、头像、用户 ID支持头像上传/api/upload/avatar
  • 交互
    • 输入框回车触发加入
    • 选择连接 ID 自动填充
    • 设置菜单外点击关闭

章节来源

通话结束处理endcall/endcall.js

  • 功能
    • 重新连接:跳转主界面
    • 离开:清除本地连接 ID回到连接界面
  • 交互
    • 页面加载时显示断开连接信息(连接 ID 与时间)

章节来源

聊天消息chatmessage.js

  • 功能
    • 消息状态管理:消息列表、未读计数、侧边栏开关
    • 发送消息:构造消息对象,通过 store 发送到远端
    • 接收消息handleChatMessage -> addMessage -> 通知 UI
    • 图片消息:限制大小、读取为 DataURL、发送文件消息
    • 未读通知:侧边栏关闭时累加未读,打开时清零
  • 事件绑定
    • sendMessage/handleChatSubmit/openImagePicker/handleImageUpload

章节来源

工具函数utils.js

  • 功能
    • formatTime/formatTimestamp时间格式化
    • generateId生成唯一 ID
    • showNotification通知组件显示与隐藏
    • toggleElement/toggleButtonState元素与按钮状态切换

章节来源

应用入口main.js

  • 功能
    • 初始化渲染器与聊天模块
    • 绑定 DOM 事件:静音/视频切换、录屏、更多选项、分辨率切换、结束通话确认
    • 键盘快捷键Space 静音、Ctrl+V 切换视频
    • 接收通话请求弹窗:接受/拒绝
    • 页面加载后检查连接 ID初始化并启动 WebRTC 连接
  • 交互
    • 对话框事件绑定、更多选项菜单外点击关闭

章节来源

依赖关系分析

  • 模块依赖
    • 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 APIgetUserMedia、RTCPeerConnection、RTCRtpTransceiver
    • WebSocket/信令通道(用于媒体状态、用户信息、聊天消息、参与者列表同步)
    • 服务器接口:/config、/api/upload/avatar、/signaling/connection-ids
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"]

图表来源

章节来源

性能考量

  • 媒体轨道管理
    • 音频先到、视频后到时延迟通知,避免黑屏与频繁 UI 刷新
    • 替换视频轨道时保留音频轨道,减少资源开销
  • 编解码器与编码参数
    • 优先选择 AV1/VP9回退 H264提升压缩效率
    • 根据采集分辨率动态设置最大比特率,平衡画质与带宽
  • 网络质量检测
    • 丢包率、抖动、RTT 综合评估,定期更新网络质量指示
  • 统计信息
    • 定时输出视频/音频统计,便于诊断与优化
  • 分辨率切换
    • 使用 applyConstraints 实时调整,避免重新获取流

章节来源

故障排查指南

  • 无法获取本地媒体流
    • 检查 getUserMedia 权限与约束;若失败,保持媒体状态关闭并通知 UI
  • 远端视频黑屏
    • 确认音频轨道先到时的延迟通知逻辑;检查轨道是否正确添加到 MediaStream
  • 连接状态异常
    • 检查 onConnect/onDisconnect 回调;确认信令通道正常
  • 媒体状态不同步
    • 确认 emitMediaStateChange 是否被调用;检查 onMessage 中 media-state-changed 分发
  • 网络质量指示不更新
    • 确认 startNetworkQualityDetection 是否启动;检查 detectNetworkQuality 统计字段
  • 头像上传失败
    • 检查文件类型与大小限制;确认 /api/upload/avatar 接口可用

章节来源

结论

本示例通过清晰的模块划分与状态驱动架构,实现了稳定的一对一视频通话体验。其关键优势在于:

  • 状态与 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 优化
    • 编解码器与编码参数:根据设备能力动态调整,提升兼容性与画质
    • 分辨率与帧率:结合网络状况动态调整,保证流畅度

章节来源