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

348 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 接收端示例
<cite>
**本文引用的文件**
- [client/public/receiver/js/main.js](file://client/public/receiver/js/main.js)
- [client/public/receiver/index.html](file://client/public/receiver/index.html)
- [client/public/receiver/css/style.css](file://client/public/receiver/css/style.css)
- [client/src/renderstreaming.js](file://client/src/renderstreaming.js)
- [client/src/peer.js](file://client/src/peer.js)
- [client/src/signaling.js](file://client/src/signaling.js)
- [client/public/js/config.js](file://client/public/js/config.js)
- [client/public/js/videoplayer.js](file://client/public/js/videoplayer.js)
- [client/public/js/stats.js](file://client/public/js/stats.js)
- [client/public/js/icesettings.js](file://client/public/js/icesettings.js)
- [package.json](file://package.json)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本指南面向使用 Unity Render Streaming 的接收端示例,帮助您在浏览器中完成以下目标:
- 连接到服务器,建立 WebRTC 媒体会话
- 接收并解码视频/音频流
- 将媒体轨道渲染到页面中的视频元素
- 处理输入通道(鼠标/键盘/触摸/手柄)以实现远程输入遥测
- 实时查看统计信息,辅助调试与性能评估
- 提供性能优化建议与兼容性注意事项
- 给出典型使用场景与配置示例
## 项目结构
接收端示例位于 client/public/receiver 目录,前端采用模块化 JavaScript配合自定义的 RenderStreaming、Peer、Signaling 模块实现 WebRTC 信令与媒体处理。
```mermaid
graph TB
subgraph "接收端页面"
HTML["index.html"]
CSS["css/style.css"]
JSMain["receiver/js/main.js"]
JSConfig["public/js/config.js"]
JSStats["public/js/stats.js"]
JSVideo["public/js/videoplayer.js"]
end
subgraph "核心模块"
RRS["src/renderstreaming.js"]
PEER["src/peer.js"]
SIG["src/signaling.js"]
end
HTML --> JSMain
HTML --> CSS
JSMain --> JSConfig
JSMain --> JSStats
JSMain --> JSVideo
JSMain --> RRS
RRS --> PEER
RRS --> SIG
```
图表来源
- [client/public/receiver/index.html:1-54](file://client/public/receiver/index.html#L1-L54)
- [client/public/receiver/js/main.js:1-186](file://client/public/receiver/js/main.js#L1-L186)
- [client/public/receiver/css/style.css:1-43](file://client/public/receiver/css/style.css#L1-L43)
- [client/src/renderstreaming.js:1-317](file://client/src/renderstreaming.js#L1-L317)
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
章节来源
- [client/public/receiver/index.html:1-54](file://client/public/receiver/index.html#L1-L54)
- [client/public/receiver/js/main.js:1-186](file://client/public/receiver/js/main.js#L1-L186)
- [client/public/receiver/css/style.css:1-43](file://client/public/receiver/css/style.css#L1-L43)
- [client/src/renderstreaming.js:1-317](file://client/src/renderstreaming.js#L1-L317)
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
## 核心组件
- 页面与入口
- index.html页面骨架、样式与脚本加载入口
- receiver/js/main.js应用主流程负责初始化、信令选择、RTCPeerConnection 配置、媒体轨道接入与统计展示
- 媒体播放器
- public/js/videoplayer.js封装视频元素创建、全屏切换、输入通道绑定与媒体轨道追加
- 信令层
- src/signaling.jsHTTP 与 WebSocket 两种信令实现负责连接生命周期、offer/answer/candidate 转发
- 会话与媒体
- src/renderstreaming.js高层封装管理连接、多 peer、事件路由、统计查询、数据通道创建
- src/peer.js底层 RTCPeerConnection 管理包含协商、ICE、统计查询、轨道与数据通道操作
- 配置与工具
- public/js/config.js读取服务器配置、生成 RTC 配置(含 STUN/TURN、音频增强
- public/js/stats.js从 RTCStatsReport 生成可读字符串数组
- public/js/icesettings.jsSTUN/TURN 配置持久化与读取
章节来源
- [client/public/receiver/index.html:1-54](file://client/public/receiver/index.html#L1-L54)
- [client/public/receiver/js/main.js:1-186](file://client/public/receiver/js/main.js#L1-L186)
- [client/public/js/videoplayer.js:1-213](file://client/public/js/videoplayer.js#L1-L213)
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
- [client/src/renderstreaming.js:1-317](file://client/src/renderstreaming.js#L1-L317)
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
- [client/public/js/config.js:1-39](file://client/public/js/config.js#L1-L39)
- [client/public/js/stats.js:1-91](file://client/public/js/stats.js#L1-L91)
- [client/public/js/icesettings.js:1-104](file://client/public/js/icesettings.js#L1-L104)
## 架构总览
下图展示了从用户点击“开始”到媒体渲染的关键交互路径,以及输入通道的建立流程。
```mermaid
sequenceDiagram
participant U as "用户"
participant Page as "页面(main.js)"
participant RS as "RenderStreaming"
participant Sig as "Signaling(HTTP/WebSocket)"
participant P as "Peer(RTCPeerConnection)"
participant VP as "VideoPlayer"
U->>Page : 点击“开始”
Page->>VP : 创建视频容器与播放器
Page->>Sig : 选择信令类型并创建连接
Page->>RS : 初始化并启动
RS->>P : 创建/准备 Peer
P-->>RS : 触发 onnegotiationneeded
RS->>Sig : 发送 offer
Sig-->>RS : 下行 offer
RS->>P : 设置远端 offer 并生成 answer
RS->>Sig : 发送 answer
Sig-->>RS : 下行 answer
P-->>RS : 触发 ontrack
RS-->>Page : 分发 track 事件
Page->>VP : 追加轨道到视频元素
Page->>VP : 建立输入数据通道并绑定
Page->>Page : 定时获取统计并展示
```
图表来源
- [client/public/receiver/js/main.js:67-108](file://client/public/receiver/js/main.js#L67-L108)
- [client/src/renderstreaming.js:182-250](file://client/src/renderstreaming.js#L182-L250)
- [client/src/peer.js:57-173](file://client/src/peer.js#L57-L173)
- [client/src/signaling.js:30-149](file://client/src/signaling.js#L30-L149)
- [client/public/js/videoplayer.js:19-41](file://client/public/js/videoplayer.js#L19-L41)
## 详细组件分析
### 页面与入口main.js
- 初始化与页面控制
- 读取服务器配置,决定是否使用 WebSocket 信令
- 显示警告(如私有模式限制)、编解码器选择下拉框、播放按钮
- 点击播放后创建视频播放器并初始化 RenderStreaming
- RTCPeerConnection 配置
- 通过 config.js 获取 RTC 配置,包含 sdpSemantics、iceServers、媒体约束与音频增强参数
- 事件与生命周期
- onConnect创建输入数据通道绑定 VideoPlayer 输入遥测
- onDisconnect清理统计、重置 UI、重建播放器与编解码器选择
- onTrackEvent将轨道追加到视频元素
- onGotOffer根据浏览器能力设置编解码器偏好
- 统计展示
- 定时调用 RenderStreaming.getStats使用 stats.js 生成可读字符串并显示
章节来源
- [client/public/receiver/js/main.js:1-186](file://client/public/receiver/js/main.js#L1-L186)
- [client/public/js/config.js:1-39](file://client/public/js/config.js#L1-L39)
- [client/public/js/stats.js:1-91](file://client/public/js/stats.js#L1-L91)
### 媒体播放器VideoPlayer
- 视频元素与布局
- 创建 video 元素,设置 playsInline、空 MediaStream监听元数据加载完成自动播放
- 提供全屏按钮与全屏状态切换逻辑,支持指针锁定(可选)
- 轨道与尺寸
- addTrack向 video.srcObject 追加媒体轨道
- resizeVideo计算缩放与偏移适配容器尺寸
- 输入遥测
- setupInput创建 Sender/InputRemoting订阅 RTCDataChannel打开后开始发送输入事件
- 支持鼠标、键盘、触摸屏、手柄输入的转发
章节来源
- [client/public/js/videoplayer.js:1-213](file://client/public/js/videoplayer.js#L1-L213)
### 信令层SignalingHTTP 与 WebSocket
- HTTP 信令
- start轮询获取消息队列分发 connect/disconnect/offer/answer/candidate/on-message
- createConnection/deleteConnection创建/删除连接
- sendOffer/sendAnswer/sendCandidate/sendMessage发送 SDP 与消息
- WebSocket 信令
- onopen/onmessage/onclose解析消息类型并分发事件
- createConnection/deleteConnection/sendOffer/sendAnswer/sendCandidate/sendMessage与 HTTP 版本对应
章节来源
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
### 会话与媒体RenderStreaming
- 生命周期与角色
- 支持 Host/Participant 双端模式Participant 端默认单 peerHost 端按参与者维护多 peer
- 事件路由
- 将 Peer 的 track/adddatachannel/offer/answer/candidate 等事件上抛,并携带 participantId
- 关键方法
- createConnection/start/stop连接生命周期管理
- getStats/createDataChannel/addTrack/addTransceiver/getTransceivers媒体与统计接口
- 与 Signaling 事件绑定,完成 offer/answer/candidate 的收发
章节来源
- [client/src/renderstreaming.js:1-317](file://client/src/renderstreaming.js#L1-L317)
### 底层会话PeerRTCPeerConnection
- 协商与 ICE
- onnegotiationneeded生成本地 offer 并通过事件上报
- onGotDescription设置远端描述若为 offer 则生成 answer 并上报
- onIceCandidate上报候选
- 状态与错误
- iceConnectionState=failed 时触发 disconnect 事件
- 工具方法
- getTransceivers/addTrack/addTransceiver/createDataChannel/getStats/close媒体与统计操作
章节来源
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
### 配置与工具
- config.js
- getServerConfig读取服务器配置含 useWebSocket
- getRTCConfiguration统一计划 SDP、ICE 服务器、媒体约束与音频增强参数
- icesettings.js
- STUN/TURN 服务器的增删改查与本地存储
- stats.js
- 从 inbound/outbound RTP 统计生成可读字符串,包含编解码器、分辨率、帧率、比特率等
章节来源
- [client/public/js/config.js:1-39](file://client/public/js/config.js#L1-L39)
- [client/public/js/icesettings.js:1-104](file://client/public/js/icesettings.js#L1-L104)
- [client/public/js/stats.js:1-91](file://client/public/js/stats.js#L1-L91)
## 依赖关系分析
- 模块耦合
- main.js 依赖 renderstreaming.js、videoplayer.js、config.js、stats.js
- renderstreaming.js 依赖 peer.js 与 signaling.js
- peer.js 仅依赖 logger.js内部日志
- 外部依赖
- 浏览器原生 WebRTC APIRTCPeerConnection、MediaStream、RTCIceServer 等)
- 第三方 polyfill/适配库(页面引入了 webrtc-adapter
```mermaid
graph LR
MAIN["main.js"] --> CFG["config.js"]
MAIN --> STATS["stats.js"]
MAIN --> VP["videoplayer.js"]
MAIN --> RRS["renderstreaming.js"]
RRS --> PEER["peer.js"]
RRS --> SIG["signaling.js"]
VP --> INPUT["inputremoting.js(sender.js)"]
```
图表来源
- [client/public/receiver/js/main.js:1-10](file://client/public/receiver/js/main.js#L1-L10)
- [client/src/renderstreaming.js:1-30](file://client/src/renderstreaming.js#L1-L30)
- [client/src/peer.js:1-10](file://client/src/peer.js#L1-L10)
- [client/src/signaling.js:1-10](file://client/src/signaling.js#L1-L10)
- [client/public/js/videoplayer.js:1-3](file://client/public/js/videoplayer.js#L1-L3)
章节来源
- [client/public/receiver/js/main.js:1-10](file://client/public/receiver/js/main.js#L1-L10)
- [client/src/renderstreaming.js:1-30](file://client/src/renderstreaming.js#L1-L30)
- [client/src/peer.js:1-10](file://client/src/peer.js#L1-L10)
- [client/src/signaling.js:1-10](file://client/src/signaling.js#L1-L10)
- [client/public/js/videoplayer.js:1-3](file://client/public/js/videoplayer.js#L1-L3)
## 性能考虑
- 编解码器选择
- 若浏览器支持 setCodecPreferences可在 offer 生成前设置偏好,减少不必要解码开销
- 统计监控
- 使用 stats.js 输出的比特率、分辨率、帧率等指标,结合网络状况动态调整
- 媒体约束与音频增强
- 合理配置音频回声消除、降噪、自动增益等参数,降低 CPU 占用与提升音质
- 渲染与布局
- 使用 videoplayer.js 的 resizeVideo 计算缩放,避免不必要的重排
- 信令选择
- WebSocket 信令延迟更低适合低延迟场景HTTP 轮询更通用,兼容性更好
[本节为通用指导,无需列出具体文件来源]
## 故障排查指南
- 私有模式限制
- 页面会在私有模式下提示警告,导致部分功能不可用
- 无法播放或黑屏
- 检查 onConnect 是否触发、track 事件是否到达、VideoPlayer 是否成功追加轨道
- 确认浏览器是否支持所选编解码器,必要时切换默认或手动选择
- 无声音
- 确认音频媒体轨道已加入,检查音频增强参数与浏览器静音策略
- 输入无响应
- 确认数据通道已创建并打开VideoPlayer.setupInput 是否被调用
- 连接失败或频繁断开
- 查看 ICE 候选是否正常收发STUN/TURN 配置是否正确
- 关注 Peer 的 iceConnectionState 与 signalingState 变化
章节来源
- [client/public/receiver/js/main.js:48-54](file://client/public/receiver/js/main.js#L48-L54)
- [client/public/js/videoplayer.js:194-212](file://client/public/js/videoplayer.js#L194-L212)
- [client/src/peer.js:43-48](file://client/src/peer.js#L43-L48)
- [client/public/js/icesettings.js:94-104](file://client/public/js/icesettings.js#L94-L104)
## 结论
该接收端示例通过清晰的模块划分与事件驱动设计,实现了从信令、协商、媒体轨道接入到播放器渲染与输入遥测的完整链路。借助统计模块与编解码器偏好设置,开发者可以快速定位问题并优化体验。建议在生产环境中优先使用 WebSocket 信令、合理配置 ICE 服务器与音频增强,并持续监控统计指标以保障质量。
[本节为总结性内容,无需列出具体文件来源]
## 附录
### 使用步骤(从零到运行)
- 启动服务端
- 使用 package.json 中的脚本启动服务端,默认端口与证书参数可参考脚本配置
- 打开接收端页面
- 在浏览器中访问接收端页面,点击“开始”
- 选择信令方式
- 若服务器返回 useWebSocket=true则使用 WebSocket 信令;否则使用 HTTP 信令
- 选择编解码器(可选)
- 若浏览器支持 setCodecPreferences可在下拉框中选择偏好编解码器
- 观察统计与播放
- 页面会定时显示统计信息;视频元素加载完成后自动播放
- 输入遥测(可选)
- 勾选“锁定光标到播放器”,进入全屏后可进行指针锁定与输入转发
章节来源
- [package.json:9-10](file://package.json#L9-L10)
- [client/public/receiver/js/main.js:40-88](file://client/public/receiver/js/main.js#L40-L88)
- [client/public/js/config.js:3-7](file://client/public/js/config.js#L3-L7)
- [client/public/js/stats.js:7-91](file://client/public/js/stats.js#L7-L91)
### 关键流程图:编解码器偏好设置
```mermaid
flowchart TD
Start(["收到 Offer"]) --> CheckSupport{"浏览器支持<br/>setCodecPreferences?"}
CheckSupport --> |否| Skip["跳过设置偏好"]
CheckSupport --> |是| ReadOptions["读取下拉框选中项"]
ReadOptions --> Parse["解析 mimeType 与 sdpFmtpLine"]
Parse --> Find["在 RTCRtpSender.getCapabilities 中查找匹配编解码器"]
Find --> Found{"找到匹配项?"}
Found --> |否| Skip
Found --> |是| GetTransceivers["获取视频接收端点列表"]
GetTransceivers --> Apply["对每个视频接收端点调用 setCodecPreferences"]
Apply --> End(["完成"])
Skip --> End
```
图表来源
- [client/public/receiver/js/main.js:110-131](file://client/public/receiver/js/main.js#L110-L131)
- [client/src/renderstreaming.js:284-290](file://client/src/renderstreaming.js#L284-L290)