跳至文章
← 返回工程

Electron 不是你屏幕录制器的瓶颈

用于“Electron 不是你屏幕录制工具的瓶颈”的封面插图

TL;DR — Electron 有实际的内存成本。它不必施加显著的录制或导出惩罚。

在我们的 M4 Mac mini 上,本地 ScreenCaptureKit 录制器和同样由 Electron 托管的本地录制器以 57.70 和 57.53 帧每秒生成 4K 视频。一个 4K 编辑着色器在直接使用 Metal 时,每帧 p95 为 1.62 毫秒,而通过 Electron 的 WebGL 到 Metal 路径则为 1.90 毫秒。一次受控的 1080p H.264 导出在本地 VideoToolbox 上以 7.54 倍实时运行,而通过 Electron 的 WebCodecs 路径则为 7.46 倍。

间隙不是零。它只是没有出现在传统论点所指出的位置。

Electron 明显的损失是内存:直接本地录制主机为 45 MB,而签名的 Electron/Node 主机在添加 Chromium 渲染器之前为 94 MB。在此测试中,打包的 Tight Studio 会话稳定在大约 744–749 MB。这是一个值得诚实提及的权衡。这并不证明捕获的帧必须通过网页传输,也不意味着导出必须依赖软件编码。

我们使用 Electron 构建了 Tight Studio,所以我们对这个问题很感兴趣。这就是为什么我们使基准测试可控且可重复,并且为什么这篇文章包括了既让 Electron 显得不如人意的结果,也包括了让它显得不错的结果。

示意图显示 Electron 在本地捕获时处理产品控制,Metal 支持的 GPU 渲染,以及硬件编解码器处理媒体路径

“原生 vs Electron” 是错误的抽象层次

桌面应用程序不是单一执行引擎。

Electron 提供了一个 Chromium 渲染器、一个 Node.js 主进程以及一个多进程应用程序框架。它也支持本地模块。Electron 自己的文档明确指出,应用程序可以使用本地代码来访问平台 API 和进行性能关键的工作。

这意味着 Electron 屏幕录制器至少可以通过两种非常不同的方式构建:

  1. 通过 JavaScript 和浏览器界面捕获、合成、复制和编码帧。
  2. 在产品 UI 和编排中使用 Electron,而 ScreenCaptureKit、AVFoundation、Metal、VideoToolbox 或其他本地媒体引擎处理关键路径。

那些应用程序共享一个框架标签,但它们不共享性能架构。

Electron 已经驱动高性能桌面应用

这种架构并不罕见。当前 macOS 版本的 Codex 和 Claude 都使用 Electron。在本文所用的机器上,Codex 26.825.41651 声明 ElectronAsarIntegrity 用于它的 app.asar 软件包,而 Claude 1.26832.0 同时附带 Electron Framework.frameworkapp.asar

Electron 自身的文档也列出了使用该框架构建的产品,包括 Visual Studio Code、Figma、Docker Desktop、Loom、Canva、Notion、1Password、Slack、Discord 和 Signal。它们涵盖了代码编辑与调试、协作图形、容器管理、屏幕录制、凭证管理、消息传递、语音与视频以及 AI 工作流程。

该列表不是性能基准,也不能证明每个 Electron 应用都是高效的。它展示了一个架构观点:选择 Electron 作为桌面外壳并不意味着外壳必须执行每一个昂贵的操作。本地模块、GPU 进程、本地服务以及远程系统可以承担专业的工作。

您可以在没有特殊工具的情况下重现 macOS 捆绑检查。在 Finder 中选择 显示包内容,然后检查 Contents/Info.plist, Contents/Resources/app.asar,和 Contents/Frameworks/

Tight Studio 采用第二种模型。在 macOS 上,屏幕帧由使用 ScreenCaptureKit 的 Swift 模块捕获,并用 AVAssetWriter 编写。录制过程不会绕过 DOM、React 或 Chromium 画布。在编辑和导出过程中,GPU 合成和硬件编解码器 API 负责昂贵的工作;JavaScript 负责协调流水线。

苹果将 ScreenCaptureKit 描述为其用于帧捕捉和音频捕捉的高性能 API。Electron 并不阻止应用调用它。原生模块可以调用相同的框架,接收相同的内容 CMSampleBuffer 对象,并将它们交给相同的系统编码器。

我们进行的基准测试

我们避免比较两个成品。一个应用程序可能渲染字幕、光标运动、摄像头裁剪和五个叠加层,而另一个则重新复用原始录制。较快的结果几乎不能告诉我们关于 Swift 或 Electron 的任何信息。

相反,我们保持工作量不变:

  • 机器: Apple M4 Mac mini,10 核 CPU,10 核 GPU,16GB 内存,macOS 26.5.2。
  • 录制: 完全相同的打包本机捕获引擎,一次从其直接的 Swift CLI 运行,一次从 Tight Studio 的签名 Electron/Node 可执行文件运行。两者都以 60 fps 的目标记录了相同的 3840×2160 动画显示。
  • 编辑: 相同的程序化背景、圆角卡片、网格、阴影和动画光标着色器,分辨率为3840×2160。Native 使用 Metal;Electron 通过 ANGLE 的 Metal 渲染器使用 WebGL 2。每一帧都有同步边界,因此隐藏画布也不能让工作消失。
  • 导出: 300 帧,分辨率 1920×1080,30 帧/秒,H.264,目标码率 12 Mbps。本地使用 Metal 加 VideoToolbox。Electron 使用 WebGL 加 WebCodecs 并请求硬件加速。
  • 运行次数: 每条路径三个。表格报告中位数。

未包括电池结果。这是一个 Mac mini,要获得可信的电池声明,需要进行更长、受控的 MacBook 测试。

零基准图表比较直接的本地录制和 Electron 混合录制、4K 编辑以及 H.264 导出吞吐量

结果

阶段直接本地Electron/混合Electron 差异
4K 录制输出速率57.70 帧/秒57.53 帧/秒-0.29%
录制主持人 CPU7.06%6.98%-0.09 分
录制 OS-服务 CPU31.34%32.76%+1.42 分
录制主持人峰值内存45.36 MB94.39 MB+49.03 MB
4K 编辑着色器吞吐量684.23 帧/秒593.77 帧/秒-13.22%
4K 编辑着色器 p95 帧时间1.62 毫秒1.90 毫秒+0.28 毫秒
1080p 导出吞吐量226.10 帧每秒223.78 帧每秒-1.02%
1080p 导出速度7.54 倍实时7.46 倍实时-1.02%

这些是在一台机器上的短期、可控测试。它们确定了这些架构可能实现的功能;并不保证每个 Electron 应用都能如此高效。

录制:Electron 不需要触碰帧

录制结果几乎是平局,因为在关键点上两条路径是相同的。

ScreenCaptureKit 生成帧。AVAssetWriter 和系统编解码器堆栈对其进行编码。Electron 端会请求本地录制器开始、停止、暂停和恢复。它不会通过 IPC 通道接收 4K 像素缓冲区,也不会在 JavaScript 中对其进行编码。

在三次运行中,本地应用的中位数帧率为 57.70 fps,而 Electron 主机的中位数帧率为 57.53 fps——差异为 0.29%。中位数录制器 CPU 本地为 7.06%,Electron 主机为 6.98%。macOS 捕获服务的平均占用率分别为 31.34% 和 32.76%。

帧率结果是重要的。微小的 CPU 反转是普通的运行间噪声,而不是 Electron 以某种方式加速 ScreenCaptureKit 的证据。

有一个值得披露的测试细节。macOS 授予已签名应用程序身份屏幕录制权限。我们的开发版 Electron 二进制文件没有该权限,因此 Electron 录制运行使用了 Tight Studio 的已签名可执行文件,以 Electron 的 Node 兼容模式运行。这隔离了原生桥接,但省略了 Chromium 渲染器。我们单独测量了打包的壳,而不是悄悄地将 94 个 MB 主机呈现为完整的 Electron 应用。

编辑:翻译后的 Metal 仍然是 Metal

JavaScript 并不直接暴露 Apple 的 Metal API。这一事实有时被扩展为更广泛的说法:Electron 无法使用 Metal 支持的 GPU 渲染。

在 macOS 上,ANGLE 为 OpenGL ES 提供了一个 Metal 后端,这正是 Chromium 在 WebGL 之下可以使用的。我们的 Electron 基准测试将其渲染器确定为 ANGLE Metal Renderer: Apple M4

Direct Metal 更快。本地中位数运行渲染 684 帧每秒;Electron 渲染 594 帧每秒,吞吐量差距为 13%。P95 帧时间从 1.62 毫秒增加到 1.90 毫秒。

这是可衡量的开销。在 60 fps 的 16.67 毫秒帧预算下,它也是 0.28 毫秒。

真正的编辑器当然不只做一个着色器。它们解码视频,上传或导入纹理,渲染文本,计算动画状态,并响应输入。粗心的实现可能会通过复制、分配、同步 IPC 或 React 工作耗尽剩余的预算。但浏览器合成器并不自动成为软件渲染器,而在 Mac 上使用 WebGL 并不能证明 GPU 已被绕过。

当 WebGL 或 WebGPU 路径不足时,Electron 仍然允许使用原生 Metal 模块。架构可以根据子系统选择其逃生通道。

导出:硬件编码器不在乎哪个按钮启动了它

VideoToolbox 是 Apple 对硬件编码器和解码器的低级接口。Chromium 有一个 macOS VideoToolbox 编码器后端,而 WebCodecs 向应用程序公开了硬件加速偏好设置。

在我们的原生运行中,VideoToolbox 确认使用硬件编码。Electron 运行通过 WebCodecs 请求硬件。WebCodecs 不会暴露所选编码器名称,因此我们无法声称具有 API 级别的 Electron 选择证明。其性能和输出与硬件路径一致:原生编码 300 帧的中位时间为 1.327 秒;Electron 用时 1.341 秒。输出大小的差异不到 1%。

计算结果为实时的 7.54 倍对 7.46 倍——有 1% 的差距。

这并不意味着每个 Electron 导出器都很快。当应用程序出现以下情况时,导出会变慢:

  • 从每一帧的 GPU 读取像素;
  • 通过 JavaScript 或 IPC 复制完整帧;
  • 在软件中编码;
  • 不必要地将解码、渲染、音频和编码阶段序列化;
  • 将整个输出保存在内存中,而不是进行流式传输;
  • 使用 UI 线程作为渲染工作线程。

那些是管道选择,而不是 Electron 强加的要求。

一个真正的 Tight Studio 导出

微基准测试显示开销的来源。产品测试告诉我们整个流程是否有用。

我们还对 Tight Studio 现有的五片段导出回归设备运行了三次。112 秒的时间线测试每个片段的解码、GPU 渲染、音频、编码、拼接和 1440×1080 的复用。导出时间分别为 81.54 秒、80.94 秒和 81.28 秒。中位数为 81.28 秒,即 1.38 倍实时时间。

生成的文件长度为112.36 秒,大约30 帧每秒,包含 H.264 视频和 AAC 音频。这个测试并不是通用的导出速度评分——源媒体和特效会影响结果——但它显示了一个从头到尾的 Electron 应用在可重复的仓库测试中导出速度快于播放。

图表显示一个 112 秒的 Tight Studio 项目导出中位数为 81 秒,即实际时间的 1.38 倍

Electron 真正损失的部分:内存

Electron 嵌入了多进程浏览器运行时。这会消耗内存。

直接的本地录制内容主机峰值为 45 MB RSS。签名的 Electron/Node 主机峰值为 94 MB。我们的最小 Electron 编辑进程树大约为 360 MB,导出进程树大约为 394 MB。带有新配置文件的打包 Tight Studio 会话在这个特定应用状态下大约稳定在 744–749 MB。

零基准内存图表比较匹配的本地和 Electron 录制主机,并有单独的 Electron 进程树上下文

最后这个数字不是 Electron 的定律,也不是本地应用的比较。它是提醒不要将最小测试壳用作市场宣传的伪装。

在受限的机器上,内存可能很重要。它会造成压力、增加交换,并间接消耗能源。但已分配的 RAM 并不等同于记录的 CPU、丢失的帧、GPU 帧时间或编码器吞吐量。将一种指标当作所有其他指标的代理会导致错误的工程结论。

实际目标不是“完全不使用 Chromium 内存”。而是让浏览器运行时远离原始帧热点路径,及时关闭媒体对象,限制缓冲区大小,流式输出,并保持闲置工作处于闲置状态。

评估屏幕录制软件的更好方法

请询问每个子系统实际的功能:

  • 哪一个 API 捕捉屏幕?
  • 帧是在哪里合成的?
  • GPU 后端是否支持硬件加速?
  • 选择了哪种编码器实现?
  • 会发生多少次全帧复制?
  • 像素数据是否会跨越 IPC 或 JavaScript 边界?
  • 编辑器能在目标分辨率下保持 60 帧每秒吗?
  • 每秒输出的导出时间是多少?
  • 在相同的工作负载下,CPU、内存、丢帧、功耗和热量表现如何?

“原生”和“Electron”是有用的实现细节。它们是弱的基准结果。

结论

一个完全本地的应用程序具有最低的外壳开销,并且可以最直接地访问平台 API。如果两个团队构建了同样优化、功能相同的管道,本地应用仍然具有优势——尤其是在内存和最后的 GPU 控制增量方面。

但是 Electron 应用程序并不需要用 DOM 节点和 JavaScript 循环来构建其媒体引擎。它可以通过 ScreenCaptureKit 捕获,通过基于 Metal 的 GPU API 进行合成,使用硬件媒体引擎进行编码,并将性能关键的工作移入本地模块或工作线程。

我们的测量发现记录帧速率差距为 0.29%,合成 4K 着色器吞吐量差距为 13%,受控导出差距为 1%。 我们还发现了很大的内存差距。 这就是权衡的诚实形式。

框架设置默认值。管道设置性能。

来源和重现

  • 苹果:ScreenCaptureKit
  • 苹果:VideoToolbox
  • electron:本地代码和 electron
  • electron:进程模型
  • Electron:为什么选择 Electron 以及生产应用示例
  • ANGLE:Metal 后端支持
  • chromium: macOS videotoolbox 编码器
  • W3C: WebCodecs 硬件加速

基准测试框架、原始运行表、权限警告和解释限制正在准备独立公开发布。当该软件包可以独立克隆和运行时,我们将在此添加仓库链接。额外的苹果硅机器和受控的 MacBook 功率测试将扩展这些结果,但它们不包括在上述声明中。

在 X 上分享