Steven
Steven1 分钟阅读

为什么屏幕录制录到了错误的显示器(以及我们的修复)

在双显示器环境下,无论你在哪块屏幕上工作,GeekBye 录制和截图的都是主显示器。修复只是一个小小的函数 — 但它的第一个版本是错的,而代码评审看出了原因。

屏幕录制
多显示器
工程
GeekBye 发布
为什么屏幕录制录到了错误的显示器(以及我们的修复)

这是一个只有当你拥有两台显示器时才存在的 bug — 所以它悄悄地存活了一阵子。你在侧边那块屏幕上工作,开始一段 GeekBye 录制,结果它录的是你的显示器。带菜单栏的那块。你并没有在看的那块。

同样的缺陷,以更安静、更糟糕的形式,击中了 GeekBye 作为上下文发给 AI 的截图:在你的第二块显示器上按下截图快捷键,AI 拿到的却是第一块的画面。没有任何视觉提示 — 助手只是在就错误的屏幕作答,而你被晾在一边,纳闷它怎么这么糊涂。GeekBye v2.0.10 把两者都修好了。

两条管线,一个偷懒的默认值

桌面上的屏幕采集是两条各自独立的代码路径,而它们都不约而同地选中了主显示器:

  • 视频录制会枚举可用的屏幕采集源,然后取第一个 — sources[0]。在 macOS 上,那实际上永远是主显示器。没有选择器,也没有任何关于你究竟在哪儿的逻辑。我们自己代码里的注释白纸黑字写着*"自动选择第一个屏幕采集源。"*
  • 截图用的是 macOS 的 screencapture 命令,带上 -m 标志。这个标志只有一个含义:仅主显示器。 写死的。

两条路径都从没问过那个真正要紧的问题:用户在哪块屏幕上?

有一件事从来没有坏过,值得澄清一下,因为大家总以为它坏了:在同一块显示器上切换 macOS Spaces 一直都好使。采集发生在显示器层级 — 它抓的是所选显示器上当时可见的那个 Space。这个 bug 从来不是关于 Spaces 的。它自始至终都是关于选错了那块物理显示器。

那个看起来显而易见 — 却是错的 — 的修复

正确的信号看起来很简单:采集用户所在的那块显示器。我们的第一版实现锚定了 GeekBye 的悬浮窗 — 采集悬浮窗待在哪块显示器,就采集哪块。

代码评审正确地毙掉了它。GeekBye 的悬浮窗是作为一个铺满工作区的窗口,创建在主显示器上,位置为 (0,0)。只有当你亲手把它那颗胶囊拖到另一台显示器上时,它才会移动 — 而那些用来挪动它的键盘快捷键会被钳制在主显示器的尺寸范围内,所以它们根本无法把它移到第二块显示器上。把采集锚定在悬浮窗上,意味着:对于每一个没碰巧把悬浮窗拖到自己工作屏幕上的用户,这个"修复"都会径直退回到主显示器。它几乎修不了任何人 — 却在单显示器开发机上的一次快速测试里,看起来像是修好了。

正确的锚点是光标。你的鼠标在哪里,那就是你正在工作的那块显示器 — 而且它对采集启动的每一种方式都正确:键盘快捷键在你指着的地方触发,而点击 Record 按钮时,按定义你的光标就在那块显示器上。最终的修复是一个两行的函数:离光标最近的那块显示器。视频把它的采集源匹配到那块显示器的 id;截图则把那块显示器的边界传给 screencapture -R(一个具体的矩形),而不是 -m 那个主显示器标志。

我们特意选了 -R(一个用全局屏幕坐标表示的显式矩形)而不是 -D(一个显示器索引):操作系统的显示器索引跟框架的显示器排序之间没有保证的对应关系,所以用索引会变成又一场猜谜。而一个来自真实显示器边界的矩形是毫不含糊的 — 而且在发布之前,我们在一套真正的多显示器机架上验证了这个标志的行为,包括那些摆在主屏左侧的显示器所带的负坐标。

为什么这是一个很好的教学型 bug

  1. "采集屏幕"背后藏着一个抉择。 在单显示器上没有抉择,所以这个抉择从没被设计过 — 它是被默认掉的。多显示器正是每一个隐含默认值浮出水面的地方。
  2. 悄无声息地错,比明晃晃地错更糟。 视频那个 bug 惹恼了人。截图那个 bug 误导的是 AI,而且是隐形的。当你构建那些给模型喂上下文的功能时,一个错误的输入会产出一个自信满满的错误输出,而任何地方都不会报错。那些才是最值得死磕去追猎的失败。
  3. 一个在你机器上通过的修复,可能在其他所有人机器上失败。 锚定悬浮窗的那版在单显示器测试里能跑。这个 bug 的全部要害就在于有多台显示器 — 而评审者选择就窗口的真实位置进行推理,而不是去相信那个绿灯测试。评审不是在能跑的代码上盖个橡皮章;它是关于代码为什么能跑的第二个模型。

GeekBye v2.0.10 为录制和截图两者都发布了基于光标的修复。如果你在用多台显示器,采集现在会跟着你走。

关于这一系列里相邻的发布,请看为什么你的 AI 笔记助手会在会议中途停止录音(v2.0.9),以及为什么 AI 转写总是听错技术术语(v2.0.11)。关于悬浮层在通话中的表现,请看如何在屏幕共享时保持隐身