1. Electron/Chromium屏幕录制技术方案选型
在桌面端实现屏幕录制功能时,Electron和Chromium提供了多种技术路线。根据我的项目经验,主要存在三种典型方案:
1.1 WebRTC API方案
Chromium内核原生支持的WebRTC API是最直接的方案。通过getDisplayMedia()方法可以获取屏幕流:
const stream = await navigator.mediaDevices.getDisplayMedia({ video: { cursor: "always", displaySurface: "monitor" }, audio: false });优势:
- 零依赖,纯浏览器API实现
- 支持系统级权限管理
- 自动处理多显示器场景
局限:
- 无法录制最小化窗口
- 帧率受浏览器限制(通常≤30fps)
- 无法录制DRM保护内容
实测发现:在Windows平台使用NVIDIA显卡时,启用硬件加速会导致录制画面撕裂。需在chrome://flags中关闭
Override software rendering list
1.2 rrweb方案
rrweb通过DOM序列化实现录制,特别适合Web应用操作回放:
import { record } from 'rrweb'; let events = []; record({ emit(event) { events.push(event); }, });适用场景:
- 需要记录用户交互行为
- 对录制文件大小敏感
- 需要跨设备回放
性能优化点:
- 使用
sampling配置降低事件采样率 - 启用
blockClass过滤敏感元素 - 配合
canvas插件录制Canvas内容
1.3 FFmpeg + Electron方案
在Electron主进程调用FFmpeg可实现更底层的录制控制:
const ffmpeg = require('fluent-ffmpeg'); const { desktopCapturer } = require('electron'); desktopCapturer.getSources({ types: ['window', 'screen'] }).then(sources => { ffmpeg() .input(sources[0].id) .outputOptions('-c:v libx264', '-preset ultrafast') .save('recording.mp4'); });进阶配置:
- 使用
-framerate 60提升帧率 - 添加
-pix_fmt yuv420p确保兼容性 - 通过
-threads 4启用多线程编码
2. 多显示器录制难题破解
2.1 显示器识别与选择
Chromium的chrome.system.displayAPI可获取显示器信息:
chrome.system.display.getInfo(displays => { displays.forEach(display => { console.log(`显示器 ${display.id}: ${display.bounds.width}x${display.bounds.height}`); }); });常见问题:
- 主显示器ID在不同会话间可能变化
- 缩放比例影响坐标计算(需使用
bounds而非workArea)
2.2 跨显示器录制方案
方案一:拼接录制区域
const { width, height } = require('electron').screen.getPrimaryDisplay().workAreaSize; const recorder = new VideoRecorder({ x: 0, y: 0, width: width * 2, // 假设双屏等宽排列 height });方案二:多实例独立录制
# 启动多个Electron实例分别录制 electron recorder.js --display=1 & electron recorder.js --display=2实测建议:NVIDIA显卡用户需关闭"多显示器优化"设置,否则可能导致帧率减半
3. 性能优化实战记录
3.1 内存控制技巧
WebRTC内存泄漏排查:
// 必须手动释放MediaStream stream.getTracks().forEach(track => track.stop());Electron进程管理:
- 启用
webPreferences: { sandbox: true }隔离渲染进程 - 使用
--disable-gpu参数避免GPU内存泄漏
3.2 编码参数调优
x264推荐配置:
-preset ultrafast -tune zerolatency -crf 28 -g 60 -keyint_min 60硬件加速方案对比:
| 技术 | Windows | macOS | Linux |
|---|---|---|---|
| NVENC | ✅ | ❌ | ✅ |
| QuickSync | ✅ | ❌ | ❌ |
| VAAPI | ❌ | ❌ | ✅ |
| VideoToolbox | ❌ | ✅ | ❌ |
4. 典型问题排查手册
4.1 黑屏问题排查流程
- 检查系统权限(特别是macOS需要屏幕录制权限)
- 验证
desktopCapturer是否返回有效源 - 尝试禁用硬件加速:
app.commandLine.appendSwitch('disable-gpu'); - 检查显卡驱动兼容性
4.2 音频同步问题
解决方案:
// 手动同步音视频时间戳 const audioContext = new AudioContext(); const videoStream = await navigator.mediaDevices.getDisplayMedia(); const audioStream = await navigator.mediaDevices.getUserMedia(); const combinedStream = new MediaStream([ ...videoStream.getVideoTracks(), ...audioStream.getAudioTracks() ]);5. 工程化实践建议
5.1 模块化设计
推荐录制模块架构:
recorder-core/ ├── capture/ # 采集模块 │ ├── webrtc.js │ ├── ffmpeg.js │ └── rrweb.js ├── encoder/ # 编码模块 ├── storage/ # 存储管理 └── renderer/ # 预览渲染5.2 错误恢复机制
实现断点续录:
class Recorder { async recover() { const lastState = await fs.readFile('last_state.json'); this.#startTime = lastState.startTime; this.#writeStream = fs.createWriteStream('output.mp4', { flags: 'a' }); } }6. 跨平台兼容性处理
6.1 Windows特定问题
- 需要处理DPI缩放(
process.env.DEVICE_SCALE_FACTOR) - 注意窗口标题匹配规则(中文系统需处理编码)
6.2 macOS权限管理
自动检测权限状态:
const { systemPreferences } = require('electron'); const hasPermission = systemPreferences.askForMediaAccess('screen');6.3 Linux依赖处理
打包时需包含这些依赖:
# Debian系 apt install -y libxcb-shape0 libxcb-xfixes0 libxcb-randr07. 安全与隐私考量
7.1 敏感信息过滤
在rrweb中配置:
record({ blockClass: 'credit-card, password-input', maskTextClass: 'sensitive-text' });7.2 录制内容加密
使用WebCrypto API:
const key = await crypto.subtle.generateKey( { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt'] );8. 调试与性能分析
8.1 Chromium调试标志
启用录制诊断日志:
electron --enable-logging --v=18.2 性能分析工具
使用Chrome Tracing:
const { startTracing, stopTracing } = require('electron').contentTracing; startTracing({ categories: 'disabled-by-default-devtools.timeline' });9. 扩展功能实现
9.1 鼠标高亮效果
通过CSS注入实现:
document.addEventListener('mousemove', e => { highlight.style.left = `${e.clientX}px`; highlight.style.top = `${e.clientY}px`; });9.2 键盘输入指示
监听全局键盘事件:
require('electron').globalShortcut.register('CommandOrControl+Shift+K', () => { showKeyboardHint(); });10. 项目部署优化
10.1 自动更新方案
集成electron-updater:
autoUpdater.checkForUpdatesAndNotify();10.2 崩溃报告收集
使用electron-crash-reporter:
crashReporter.start({ productName: 'ScreenRecorder', submitURL: 'https://your-domain.com/crash-report' });在开发过程中,最耗时的往往是各种边界条件的处理。比如在Windows 11上,当系统开启HDR时,色彩空间转换会导致录制视频发灰。最终通过强制指定色彩矩阵解决:
ffmpeg -colorspace bt709 -color_primaries bt709 -color_trc iec61966-2-1