录屏假光标被打回:画出来的不算操作,与”输入送达”的四处假信号
一句话律:演示鼠标操作,观众要看的是”手怎么动”,不是”屏幕上有个圆点在动”——浏览器里画的光标无论放多大都不是系统指针;顺着这条往下,录屏自动化里每一个”看着对”的信号都要问一句”它测的是不是我以为的那件事”。
现象
教程录屏交付 11 条,被一句话打回:“这不是鼠标操作”。
那批素材是 Playwright 无头浏览器录的,页面里注入一个 CSS div 当光标。收到的第一版反馈是”鼠标指针太小、看不清落点”,我据此把假光标从 18px 调到 30px、描边 2.5→3.5px、点击涟漪终点 52→88px——方向从一开始就是错的。假光标再大也只是网页里的一个圆点,真实系统指针全程没动。
根因与正解
改用 humancast 驱动真实 Windows 指针(最小急动度轨迹 + 贝塞尔弧线 + 落点前微抖 + 终点过冲回修),配成混合架构:
- CDP 算”点哪”:Playwright
connectOverCDP用 DOM 选择器拿元素位置——选择器比坐标稳,UI 一改就自动跟着走; - humancast 让真实鼠标”走过去”:录进画面的是系统指针。
坐标不靠推 DPI,走闭环标定:真实鼠标先走两个已知屏幕点,从页面 mousemove 读回 clientX/clientY,反解仿射变换。实测 screen = page × 1.0 + (2560, 87)。这一步绕开了混屏 DPI 的全部推理——本机主屏 2560×1440 物理 = 2048×1152 DIP(125% 缩放),Chrome 报 availLeft: 2048 而 Win32 报 2560,硬算必错。
四处”看着对”的假信号(终端录屏,同一天连废 3 条)
换到 PowerShell 终端录屏后,前三条全废。没有一条是被录软件的问题,全是判据测错了东西:
-
“有子进程”不等于”命令在跑” ⚠️首次 我用”PowerShell 有没有活着的子进程”判断命令结束,但空闲的 PowerShell 本身就挂着一个
conhost.exe子进程,判据恒为真:git clone一路等到 300s 超时才往下走,后面全部错位。要按 exe 名过滤。 底下还压着一层:CreateToolhelp32Snapshot没设restype = c_void_p,64 位句柄被 ctypes 默认按c_int截断。修完实测:空闲 → False,命令在跑 →['node.exe'],跑完 → False。 -
“开打前验过前台”不等于”全程在前台” ⚠️首次 后台进程调
SetForegroundWindow会被 Windows 静默拒绝(不报错,就是不生效)。抽帧确认第一条废片里pnpm run build和pnpm dsh web根本没敲进终端——画面停在上一条命令的提示符上,而脚本以为自己敲完了。 humancast 自带保险丝window.require_foreground(hwnd)(“不是目标窗口就一个键都不发”),但只在开打前验一次不够:一条长路径要敲三四秒,中途焦点被抢走,后半截就飞出去了。实测把后半截{项目工作区}\lab\install-demo"敲进了另一个窗口,终端里只剩半条cd "E:,未闭合的引号让 PowerShell 进了续行模式>>,后续两条命令全被吞进续行,最后pnpm install在盘根目录跑,报ERR_PNPM_NO_PKG_MANIFEST。 正解:AttachThreadInput强抢前台 + 分段打字,每 6 个字符重验一次,抢不到就中止。 -
“屏幕没变化”不等于”命令没执行” ⚠️首次 用屏幕变化确认回车生效,测出来永远是”没变化”。量了才知道:一条命令回车后整屏差异只有 0.0014,光标闪烁的本底噪声是 0.00012,而 humancast
wait_change默认tol=0.002正好卡在信号上方——默认值不是保守,是完全失灵。取 0.0005(噪声 4 倍、信号 1/3)才分得开。 另一半是取样时序:基线必须在按回车之前取。秒回命令(git --version)在press返回时输出已经画完了,回车后再取基线永远比不出差异,脚本会白敲第二次回车、多出一个空提示符。 -
“刚拿到焦点”不等于”能开始打字” ⚠️首次 焦点切换瞬间打字会掉前几个字符,实测
git --version变成t --version。要是落在git clone上,整条素材废在第一行。 正解:命令前补两个空格当牺牲字符(PowerShell 不在乎前导空格),掉的是空格不是git的g。 我一度改用 ESC 当”热身键”——这是个错误做法:ESC 会把”上一条没提交成功的命令”整行清掉,等于毁尸灭迹,现场连证据都不剩,反而更难查。修一个症状引入一个更坏的 bug。
附:同批次其它坑
Remove-Item -Recurse -Force删不掉 pnpm 的node_modules⚠️首次:报mismatch between the tag specified in the request and the tag present in the reparse point。pnpm 的node_modules里全是 reparse point,PowerShell 处理不了。这句报错极易被误读成”文件被占用”,去查占用进程是白费功夫(我查了一轮进程树和监听端口)。用cmd /c rd /s /q。- OBS 开录会把自己拉到前台:Chrome 一失去前台,下一次点击就被当成”激活窗口”吞掉(实测设置弹窗压根没开)。开录后要留延时并重新置前台。
- 终端字号是”鼠标太小”的同类问题:默认 conhost 字体在 1920×1080 下几乎看不清,教学素材等于白录。正解是让 shell 自己调
SetCurrentConsoleFontEx(Consolas 30px)——只影响那一个窗口,不写注册表,不污染用户环境。 .ps1要 CRLF + UTF-8 BOM(⭐二次验证,见关联):LF 会让 here-string 解析炸;无 BOM 则 PS 5.1 按 ANSI 读,中文窗口标题变乱码,脚本按标题找窗口就永远找不到——症状是”窗口没起来”,跟真的没起来完全一样。- 废片文件名必须编号:我用了固定名
.FAILED.mp4,第二条废片落盘时把第一条覆盖了。协作红线写的是”不删废片”,覆盖同名文件同样是删——约 382MB 的废片没保住。
第五处假信号:我自己的摘要 ⭐二次验证
收口写回执时,我把交接单里的「C 类 9 条」写成了「转 Mac 端另录,本机不再处理」—— 而原文写的是「Claude Code 本机处理(9 条,原误标 Mac)……本机 Windows 即可录,无需 Mac 设备」, 意思完全相反。等于我把 9 条本该我做的活,在回执里写成了别人的。
错因:写回执时我用的是自己对交接单的摘要记忆,没回去读原文那一节。而这份交接单的 C 类恰好前后改过三版(Mac 另录 → 执行人自己有 Mac → 根本不需要 Mac),我的记忆停在中间那版。
这跟协作方同日总结的「转述链衰减律」是同一条,只不过那边衰减的是人与人之间的转述, 这边衰减的是我自己对原始材料的压缩——而后者更隐蔽,因为它不经过任何人, 不会有第二个人在场提出异议。长会话被压缩、跨会话交接、隔天续做,都会制造这种”自摘要”。
判据很简单:凡是要写进交付物的”谁做什么”,落笔前回原文那一节重读一遍, 不用回忆、不用信摘要——重读一节的成本是十几秒,写反的成本是 9 条素材没人做。
教训
- “把它调大”之前先问”它是不是那个东西”。假光标从 18px 调到 30px 是完全正确的执行 + 完全错误的方向;反馈说”看不清”,真问题是”根本不是它”。
- 每一个绿灯都要问”它测的是不是我以为的那件事”:conhost 让”有子进程”恒真、默认阈值让”屏幕变化”恒假、
SetForegroundWindow静默失败让”已置前台”恒真。三个判据全是假的,而症状都长得像”程序跑得好好的”。 - 单次验证成本高的任务,先做不录制的彩排。每条素材 3–10 分钟,我”改一处 → 录一次 → 再废”重复了三轮;第四次之前改成先跑一遍不开 OBS 的干跑,1 分钟就验完了整条输入链路。这个顺序早两小时用上就不会废三条。
- 自己的摘要也是转述。长会话压缩、跨会话交接、隔天续做都会生成”我记得规格是这么写的”,它和别人的转述一样会衰减,且更隐蔽——没有第二个人在场纠正。
- 红线要按后果理解,不按动作理解。“不删废片”约束的是”废片还在不在”,不是”有没有执行删除操作”。
关联文档
- ping通不等于路通_fake-ip假信号与节点带宽实测选型_v1 —— “永远绿的信号最没用”同族;其中「PS 5.1 按 ANSI 读 UTF-8 无 BOM 致中文标识符静默走错分支」在本轮二次验证(这次是中文窗口标题)
- 全站文字截断体检_检测工具本身要先被证伪_v1 —— “检测工具本身要先被证伪”的跨场景二次验证:本轮是默认阈值卡在信号上方,工具两端都要用已知样本标定
- 构建产物的脏改动不是事故_复发是归因错了的信号_v1 —— 归因错了会让”修复”引入更坏的问题(本轮的 ESC 热身键)
- 2026-08-19_DeepSeekHarness教程收口日_MCP改写与录屏重录交接复盘_v1 —— 同一天、同一项目的协作侧复盘,其头号律「转述链衰减律:执行前回原始材料」在本文第五节由我二次验证(这次衰减的是自摘要)
- 交接文档不是需求原文_接手先回溯上游_v1 —— 同族先例
- 零作品的比赛_界面演完不等于链路存在_v1 —— 「X 不等于 Y」同族:那边是界面演完≠链路存在,这边是画出来的光标≠鼠标操作