Electron 会议系统架构设计与 WebRTC 本地编解码学习笔记
适合目标:系统掌握基于 Electron 的会议系统架构设计,重点理解 WebRTC、音视频采集、本地编解码、信令、传输、SFU 架构、原生层接入与工程落地。
学习重点:会议系统整体分层、WebRTC 核心链路、音视频本地处理与编解码、Electron 中的设备接入、Native Addon 扩展、性能优化、稳定性治理与高频面试题。
学习原则:先理解会议系统全局架构,再拆到信令、媒体、传输和客户端内部模块;先理解 WebRTC 标准链路,再理解 Electron 实战中的工程细节。
目录
- 学习总览
- 会议系统到底在解决什么问题
- 为什么 Electron 适合做会议系统客户端
- 会议系统总体架构
- 会议系统核心模块拆解
- WebRTC 核心原理
- 会议系统中的典型媒体链路
- 本地编解码到底是什么
- Electron 中本地编解码架构怎么做
- 信令系统设计
- 媒体服务器架构:P2P、MCU、SFU 对比
- 房间、成员、流管理设计
- 音频链路设计
- 视频链路设计
- 屏幕共享设计
- 网络传输与弱网对抗
- Electron + Native Addon 的落地位置
- 线程模型与性能优化
- 安全、稳定性与可观测性
- 实战项目架构建议
- 高频面试题
- 学习路线建议
- 一页速记总结
- 背诵口诀
1. 学习总览
1.1 这类系统真正要学什么
很多人一提会议系统,会先想到:
- 音视频通话
- 房间
- 屏幕共享
- 麦克风和摄像头
但如果你真的做 Electron 会议系统,核心问题远比 UI 复杂得多。
你真正要学的是:
如何让采集、编解码、网络传输、实时同步、设备控制和桌面端 UI 在复杂网络与复杂设备环境下长期稳定运行。
这套系统通常同时涉及:
- Electron 桌面客户端架构
- WebRTC 实时音视频
- 信令系统
- 媒体服务器
- 本地音视频设备与编解码能力
- Native Addon 或底层 SDK 扩展
- 监控、容灾、弱网优化
1.2 这篇笔记的视角
这篇不是只讲 WebRTC API,而是站在“做一个真实会议系统”的视角来讲:
- 系统为什么这么分层
- 客户端内部怎么设计
- 本地编解码为什么重要
- Electron 在其中扮演什么角色
- 工程上有哪些坑
2. 会议系统到底在解决什么问题
一个会议系统表面上是“多人连麦开会”,本质上是在解决下面这些问题:
- 如何把本地音视频采集出来
- 如何在本地做处理和编码
- 如何在网络中低延迟传输
- 如何让多人在房间内同步状态
- 如何在弱网情况下尽量保证可用
- 如何让客户端在不同设备、不同平台稳定工作
2.1 会议系统的核心指标
- 首次入会时延
- 端到端音视频延迟
- 丢包恢复能力
- 卡顿率
- 音视频同步
- CPU / 内存占用
- 崩溃率
2.2 会议系统和普通直播的差别
会议系统比直播更难,因为它更强调:
- 双向实时互动
- 低延迟
- 多人协作
- 设备控制
- 屏幕共享
- 房间与成员状态一致性
3. 为什么 Electron 适合做会议系统客户端
3.1 Electron 的优势
- 跨平台
- UI 开发效率高
- 可以复用 React / Vue / TS 工程体系
- 可以访问桌面能力
- 可以和 Native Addon、C++ SDK 结合
3.2 会议系统为什么常常需要 Electron + 原生
因为纯 Web 版本虽然也能做会议,但桌面客户端常常还需要:
- 更强的设备控制能力
- 更好的屏幕共享体验
- 更稳定的本地文件、录制、日志和系统集成
- 更细的音视频底层优化
- 接硬件加速、厂商编解码 SDK 或音视频前处理库
3.3 Electron 的代价
- 进程模型更复杂
- CPU / 内存管理更要小心
- 原生模块与打包发布更复杂
- 安全边界必须自己做好
4. 会议系统总体架构
先给出一个推荐的总体架构图。
4.1 总体架构图
+----------------------------------------------------------------------------------+
| Electron Meeting App |
| |
| +----------------------+ +----------------------+ +-------------------+ |
| | Renderer(UI Layer) | --> | Preload / Bridge | --> | Main Process | |
| | React/Vue 页面层 | | 白名单能力暴露 | | 应用调度/IPC/设备管控 | |
| +----------------------+ +----------------------+ +-------------------+ |
| | | | |
| | | | |
| v v v |
| +----------------------+ +----------------------+ +-------------------+ |
| | Meeting Domain Layer | --> | RTC Client Layer | --> | Native Service | |
| | 房间/成员/状态管理 | | PeerConnection/Track | | Addon/SDK/系统能力 | |
| +----------------------+ +----------------------+ +-------------------+ |
| | | | |
| v v v |
| +----------------------+ +----------------------+ +-------------------+ |
| | Signaling Client | | Media Engine | | C++ / Codec / SDK | |
| | WebSocket/状态同步 | | Capture/Encode/Decode| | 音频前处理/硬编解码 | |
| +----------------------+ +----------------------+ +-------------------+ |
+----------------------------------------------------------------------------------+
| |
| |
v v
+-------------------+ +----------------------+
| Signaling Server | | SFU / Media Server |
| 房间/成员/协商 | | 转发音视频 RTP 流 |
+-------------------+ +----------------------+
4.2 分层理解
UI 层
- 参会页面
- 成员列表
- 麦克风、摄像头、共享按钮
- 网络状态和设备状态展示
会议领域层
- 房间状态
- 成员状态
- Track 与流的绑定
- 主持人控制逻辑
RTC 客户端层
- WebRTC 连接管理
- 本地流发布
- 远端流订阅
- ICE / SDP 交换配合
Native / Media 层
- 设备枚举
- 音视频前处理
- 硬件编解码
- 特殊平台能力
5. 会议系统核心模块拆解
一个可落地的会议系统客户端,至少要有这些模块:
- 房间管理模块
- 成员管理模块
- 设备管理模块
- 音频管理模块
- 视频管理模块
- 屏幕共享模块
- 信令模块
- RTC 连接模块
- 网络质量检测模块
- 日志与监控模块
5.1 房间管理模块
负责:
- 入会
- 离会
- 房间配置同步
- 主持人和角色控制
5.2 成员管理模块
负责:
- 在线成员列表
- 用户上下线事件
- 麦克风 / 摄像头状态
- 流订阅状态
5.3 设备管理模块
负责:
- 枚举设备
- 切换麦克风 / 摄像头
- 检测设备插拔
- 回声消除、噪声抑制参数管理
6. WebRTC 核心原理
WebRTC 是会议系统里最核心的技术之一。
6.1 WebRTC 在做什么
可以把 WebRTC 理解成:
一个让浏览器或客户端之间低延迟传输音视频和数据的实时通信框架。
它主要提供:
- 音视频采集
- 编解码
- 网络协商
- RTP / RTCP 传输
- 抖动缓冲、带宽估计、重传、拥塞控制
6.2 WebRTC 的关键对象
MediaStreamMediaStreamTrackRTCPeerConnectionRTCDataChannelSDPICE
6.3 WebRTC 建链流程图
客户端 A 客户端 B
| |
|---- 获取本地音视频轨道 -------------------------->|
| |
|---- createOffer --------------------------------|
|---- 本地 setLocalDescription -------------------|
| |
|---- 通过信令发送 SDP offer --------------------->|
| |
|<--- 通过信令返回 SDP answer ---------------------|
|---- setRemoteDescription ------------------------|
| |
|<--- 交换 ICE candidate ------------------------->|
| |
|---- 建立媒体通道 --------------------------------|
| |
|<--- 音视频 RTP / RTCP 双向传输 ------------------>|
6.4 WebRTC 在 Electron 里怎么用
如果 Electron 渲染层基于 Chromium 能力,很多 WebRTC 能力可以直接复用。
但当你需要更深的本地能力时,常常还要额外接入:
- Native Addon
- 本地设备 SDK
- 本地编解码优化能力
7. 会议系统中的典型媒体链路
7.1 发送链路
摄像头/麦克风采集
-> 音视频前处理
-> 编码
-> RTP 打包
-> 网络传输
-> SFU 转发
7.2 接收链路
网络接收 RTP
-> 抖动缓冲/Jitter Buffer
-> 丢包恢复/NACK/FEC/PLI
-> 解码
-> 音频播放 / 视频渲染
7.3 一个更完整的链路图
本地采集
-> Track 生成
-> Audio Processing / Video Preprocess
-> Codec Encode
-> RTP Sender
-> ICE/DTLS/SRTP
-> 网络
-> SFU
-> 网络
-> SRTP 解密
-> RTP Receiver
-> Jitter Buffer
-> Codec Decode
-> Render / Speaker
8. 本地编解码到底是什么
这部分是你重点要求的内容。
8.1 编码是什么
编码是指把原始音视频数据压缩成更适合网络传输的数据格式。
例如:
- 原始视频帧非常大
- 原始 PCM 音频数据也很大
- 如果不压缩,网络几乎扛不住
所以需要编码成:
- 视频:H.264、VP8、VP9、AV1 等
- 音频:Opus、AAC 等
8.2 解码是什么
解码就是把收到的压缩数据恢复成可以播放和渲染的音视频数据。
8.3 为什么说“本地编解码”
因为这个过程通常发生在客户端本地设备上,而不是一定在服务器。
客户端本地会做:
- 摄像头原始帧采集
- 编码
- 网络发送
接收端本地会做:
- 收包
- 解码
- 渲染
8.4 为什么本地编解码很重要
因为它直接影响:
- CPU 占用
- 发热
- 功耗
- 分辨率和码率
- 端到端延迟
- 画质和流畅度
8.5 软件编解码和硬件编解码
软件编解码
- 用 CPU 做编码和解码
- 灵活
- 兼容广
- CPU 开销更大
硬件编解码
- 用 GPU / 专用硬件单元处理
- 功耗更低
- 性能更高
- 平台差异更大
- 接入复杂度更高
8.6 在会议系统里的现实选择
很多会议系统会采用:
- 默认优先硬编解码
- 不支持时降级到软编解码
- 在弱网下动态调整分辨率、帧率、码率
9. Electron 中本地编解码架构怎么做
这一节讲实际架构。
9.1 推荐分层
UI 层
-> Meeting Domain
-> RTC Client
-> Native Media Service
-> Codec Adapter
-> Platform Codec / SDK
9.2 为什么要单独抽 Native Media Service
因为本地编解码相关能力通常涉及:
- 摄像头设备访问
- 音频前处理
- 硬件编解码调用
- 原始帧缓存
- 性能监控
这些能力不适合散落在页面和 WebRTC 逻辑里。
9.3 一个推荐的客户端内部架构图
+------------------------------------------------------------------------+
| Electron Meeting Client |
| |
| Renderer(UI) |
| |- Room View |
| |- Member Grid |
| |- Device Panel |
| |
| Meeting Domain |
| |- roomStore |
| |- memberStore |
| |- trackStore |
| |
| RTC Client |
| |- PeerConnection Manager |
| |- Publish Manager |
| |- Subscribe Manager |
| |- Stats Collector |
| |
| Native Media Service |
| |- Audio Device Manager |
| |- Video Device Manager |
| |- Screen Capture Adapter |
| |- Audio Process Adapter(AEC/ANS/AGC) |
| |- Codec Adapter(H264/VP8/VP9/AV1/Opus) |
| |
| Native Addon / C++ Layer |
| |- OS Device APIs |
| |- Vendor SDK |
| |- Hardware Encode/Decode |
| |- Frame Convert / PCM Process |
+------------------------------------------------------------------------+
9.4 哪些场景需要原生层接管编解码
- Chromium 自带编解码能力不满足需求
- 需要厂商硬件编解码 SDK
- 需要低延迟自定义前处理
- 需要特殊视频源或特殊音频链路
- 需要对原始帧做 AI 处理、美颜、降噪、背景替换
9.5 哪些场景不一定需要自己写原生编解码
- 常规会议应用
- 只使用 Chromium / WebRTC 默认编解码
- 对平台适配和控制要求不极端
一句话:
能用 WebRTC 默认媒体栈解决的先用默认栈,只有当性能、能力或设备控制不足时,再接管本地编解码相关链路。
10. 信令系统设计
信令系统不传音视频帧,它主要负责“协商和状态同步”。
10.1 信令系统负责什么
- 入会
- 离会
- SDP offer / answer 交换
- ICE candidate 交换
- 房间成员状态同步
- 设备状态同步
- 主持人控制消息
10.2 信令系统不负责什么
- 不直接承载大规模音视频媒体流
- 不负责视频帧编解码
- 不负责 RTP 转发
10.3 信令消息分类建议
- 房间类消息
- 协商类消息
- 控制类消息
- 成员状态类消息
- 共享类消息
10.4 信令流程图
用户点击加入会议
-> 客户端向信令服务发 join
-> 服务端校验房间、权限、令牌
-> 返回房间信息、成员列表、媒体策略
-> 客户端创建 PeerConnection
-> 与 SFU 进行 SDP/ICE 协商
-> 建立媒体收发链路
-> 信令持续同步成员状态和控制指令
11. 媒体服务器架构:P2P、MCU、SFU 对比
这是会议系统架构设计面试高频题。
11.1 P2P
每个客户端直接和其他客户端互连。
优点:
- 架构简单
- 服务端成本低
缺点:
- 人数一多连接数爆炸
- 上行带宽压力极大
- 不适合多人会议
11.2 MCU
服务端把多路流解码、混流、再编码后发给客户端。
优点:
- 客户端压力小
- 带宽模型简单
缺点:
- 服务端编解码成本极高
- 延迟更高
- 扩展性差
11.3 SFU
服务端主要做选择性转发,不做或尽量少做重编码。
优点:
- 延迟低
- 扩展性好
- 是现代会议系统主流方案
缺点:
- 客户端要处理多路流
- 订阅和布局逻辑更复杂
11.4 现代会议系统为什么大多选 SFU
因为它在:
- 延迟
- 质量
- 成本
- 可扩展性
之间取得了相对更平衡的结果。
11.5 三者对比表
| 方案 | 优势 | 短板 | 适合场景 |
|---|---|---|---|
| P2P | 简单、服务端轻 | 多人不可扩展 | 1v1、小规模场景 |
| MCU | 客户端轻、统一混流 | 服务端成本高、延迟高 | 特殊混流场景 |
| SFU | 低延迟、可扩展、主流 | 客户端订阅复杂 | 多人会议主流架构 |
12. 房间、成员、流管理设计
12.1 房间模型
通常需要:
- 房间 ID
- 房间配置
- 角色信息
- 当前成员列表
- 当前流列表
12.2 成员模型
建议至少有:
- 用户 ID
- 昵称
- 角色
- 麦克风状态
- 摄像头状态
- 共享状态
- 网络状态
12.3 流模型
建议区分:
- 摄像头流
- 麦克风流
- 屏幕流
- 系统音频流
12.4 为什么“人”和“流”不能混为一谈
因为一个人可能同时拥有:
- 音频流
- 摄像头流
- 屏幕共享流
所以会议系统里通常是:
用户实体
和
媒体流实体
分开管理。
13. 音频链路设计
音频通常比视频更重要,因为会议里“能听清”优先级更高。
13.1 音频采集后会经历什么
麦克风采集
-> AEC 回声消除
-> ANS 噪声抑制
-> AGC 自动增益控制
-> 编码(Opus)
-> RTP 发送
13.2 音频常见前处理
- AEC:回声消除
- ANS:噪声抑制
- AGC:自动增益
- VAD:语音活动检测
13.3 为什么音频常常更依赖本地处理
因为:
- 音频问题非常影响主观体验
- 回声、底噪、爆音需要本地尽早处理
- 这些能力和设备环境强相关
13.4 Electron + 原生层的音频机会点
- 接更强的本地音频前处理库
- 接厂商音频算法 SDK
- 做设备级调优
14. 视频链路设计
14.1 视频发送链路
Camera Capture
-> Frame Convert
-> 预处理(美颜/背景替换/裁剪)
-> 编码(H264/VP8/VP9/AV1)
-> 网络发送
14.2 视频接收链路
网络接收
-> 丢包恢复
-> 解码
-> 渲染
-> 缩略图 / 主画面布局
14.3 视频设计里最重要的几个点
- 分辨率
- 帧率
- 码率
- 编码复杂度
- 关键帧请求
- 多路视频订阅策略
14.4 多人会议为什么客户端会更复杂
因为客户端可能同时收到多路远端视频:
- 主讲人高清
- 其他人缩略流
- 屏幕共享流
所以客户端必须有:
- 订阅策略
- 渲染策略
- 资源调度策略
15. 屏幕共享设计
屏幕共享通常是会议系统的另一条特殊媒体链路。
15.1 屏幕共享和摄像头流的区别
- 内容特征不同
- 对清晰度要求更高
- 帧率需求可能更低或变化更大
- 对文字清晰度和颜色保真更敏感
15.2 屏幕共享链路图
屏幕捕获
-> 可选捕获系统音频
-> 视频帧采集
-> 屏幕场景编码参数
-> 发布到 SFU
-> 远端订阅并渲染
15.3 屏幕共享的工程难点
- 多显示器选择
- 窗口共享还是全屏共享
- 鼠标指针是否采集
- 系统音频捕获
- 权限问题
- 不同平台差异
15.4 为什么 Electron 在这里更有优势
因为桌面环境下:
- 系统能力访问更自然
- 多窗口、多显示器管理更方便
- 可以更细地处理共享体验
16. 网络传输与弱网对抗
会议系统不是只要本地编解码强就够了,网络侧同样关键。
16.1 弱网问题通常表现为
- 卡顿
- 马赛克
- 音频断断续续
- 延迟升高
- 音画不同步
16.2 常见弱网对抗手段
- 自适应码率
- 自适应分辨率
- 降帧
- 重传 NACK
- 前向纠错 FEC
- 关键帧请求 PLI/FIR
- 抖动缓冲
16.3 会议系统中的动态策略
客户端通常要根据:
- RTT
- 丢包率
- 接收带宽估计
- 发送带宽估计
动态调整:
- 分辨率
- 帧率
- 码率
- 订阅层级
16.4 一个弱网自适应流程图
定时采集 RTC stats
-> 计算 RTT / 丢包 / 抖动 / 实际码率
-> 判断网络等级
-> 调整编码参数或订阅层级
-> 观察恢复效果
-> 持续反馈闭环
17. Electron + Native Addon 的落地位置
如果你要做“本地编解码增强”,Native Addon 很可能会出现在这里。
17.1 适合放在原生层的能力
- 硬编解码适配
- 图像前处理
- 音频算法
- 设备控制
- 厂商 SDK 对接
17.2 不适合放在原生层的能力
- 房间业务状态
- UI 布局逻辑
- 大量会议业务编排
- 页面交互逻辑
17.3 推荐调用链
Renderer
-> Preload
-> Main / Native Media Service
-> Node-API Addon
-> C++ / SDK / 编解码器
17.4 为什么不要让 Renderer 直接碰底层编解码
因为这样会带来:
- 安全问题
- 架构耦合
- 调试困难
- 替换底层实现困难
18. 线程模型与性能优化
这是 Electron 会议系统的生死线。
18.1 线程模型建议
建议至少区分:
- UI 线程
- RTC 工作线程
- 音频处理线程
- 视频处理线程
- Native 后台任务线程
18.2 为什么不能在 UI 线程做重活
因为这会直接导致:
- 页面卡顿
- 鼠标点击迟钝
- 会议控制面板无响应
18.3 重点优化方向
- 本地预览和远端渲染分离
- 降低不必要的 React / Vue 重渲染
- 多路视频渲染时做虚拟化或优先级渲染
- 编解码优先硬件加速
- 统计信息采集不要过高频
18.4 CPU 过高的常见原因
- 多路高清视频同时解码
- 多路视频 DOM / Canvas 渲染
- 美颜、背景替换等前处理太重
- 软件编解码占用过高
- 重复状态更新导致 UI 抖动
19. 安全、稳定性与可观测性
会议系统不只是“功能能跑”,还必须能长期稳定。
19.1 安全点
- Token 鉴权
- 信令鉴权
- 会议房间权限控制
- Electron Bridge 白名单能力
- 不要随意暴露 Node 能力到页面
19.2 稳定性点
- 重连机制
- 设备切换时状态恢复
- 屏幕共享异常恢复
- 媒体链路重协商
- 崩溃日志和核心事件埋点
19.3 可观测性点
建议至少采集:
- 加入会议成功率
- 首次出声时间
- 首帧渲染时间
- 丢包率
- RTT
- 编码和解码耗时
- CPU / 内存
- 设备异常次数
20. 实战项目架构建议
20.1 推荐目录结构
electron-meeting/
src/
main/
ipc/
app/
preload/
renderer/
pages/
components/
stores/
meeting/
room/
member/
rtc/
device/
screen-share/
stats/
native/
addon/
media-service/
codec-adapter/
20.2 推荐模块职责
meeting/room
- 房间生命周期
- 入会离会
- 会控状态
meeting/rtc
- PeerConnection 管理
- 发布和订阅
- Track 管理
meeting/device
- 摄像头
- 麦克风
- 扬声器
- 设备检测和切换
meeting/stats
- RTC stats 收集
- 网络质量判断
- 弱网策略触发
native/media-service
- 本地音视频增强
- 编解码适配
- 设备底层接入
20.3 为什么这样划分
因为会议系统本身已经很复杂,如果:
- UI
- 房间状态
- RTC 逻辑
- 本地编解码
全部糊在一起,后期会非常难维护。
21. 高频面试题
21.1 Electron 会议系统为什么常用 WebRTC
答题模板:
因为 WebRTC 提供了实时音视频通信所需的核心能力,包括采集、编解码、网络协商、RTP 传输、拥塞控制和弱网适配,非常适合低延迟互动会议场景。
21.2 会议系统里信令服务器和媒体服务器的区别
信令服务器负责房间状态同步、SDP/ICE 交换和控制消息;媒体服务器负责音视频 RTP 流的转发或处理。信令不直接承载主媒体数据。
21.3 P2P、MCU、SFU 怎么选
推荐回答:
- 小规模可用 P2P
- 需要服务端混流可考虑 MCU
- 多人会议主流是 SFU,因为延迟、扩展性和成本更平衡
21.4 本地编解码为什么重要
因为它直接影响会议客户端的 CPU 占用、功耗、画质、流畅度、发热和延迟。尤其在多人会议、屏幕共享和弱网环境下,本地编解码策略会显著影响体验。
21.5 什么时候需要 Electron + Native Addon
当默认 WebRTC 媒体能力不够时,比如要接硬件编解码、厂商音视频 SDK、特殊设备、音频前处理或本地视频特效,通常需要 Native Addon。
21.6 会议系统里最难的工程问题是什么
- 弱网对抗
- 本地编解码与性能
- 多平台设备兼容
- 屏幕共享差异
- 复杂状态同步
- 可观测性建设
21.7 如何优化多人会议客户端性能
- 优化订阅策略
- 优化渲染数量
- 使用硬件编解码
- 降低 UI 重渲染
- 动态调整分辨率、码率和帧率
22. 学习路线建议
22.1 第一阶段
先学:
- Electron 架构
- WebRTC 基础
- 信令流程
22.2 第二阶段
补:
- SFU 架构
- 房间与成员模型
- RTC stats
22.3 第三阶段
深入:
- 音频前处理
- 本地编解码
- 屏幕共享
- Native Addon
22.4 第四阶段
工程化:
- 监控埋点
- 弱网策略
- 崩溃恢复
- 跨平台发布
23. 一页速记总结
23.1 会议系统核心分层
UI 层会议领域层RTC 层信令层媒体层原生层
23.2 一句话记住
信令管协商和状态,SFU 管媒体转发,WebRTC 管实时传输,原生层补设备与编解码能力,Electron 负责把桌面端体验和系统能力串起来。
23.3 选型结论
多人会议主流选 SFU默认先用 WebRTC 自带媒体栈能力不足再接管本地编解码Electron + Native Addon 适合桌面增强场景
24. 背诵口诀
会议系统先分信令和媒体,客户端再分房间、设备、RTC 和原生;多人会议优先 SFU,弱网靠自适应,本地编解码看性能与平台能力,Electron 负责把桌面体验做完整。