资讯动态

OpenScreen Windows 原生光标捕获诊断流水线:从 GetCursorInfo 采样器到 WGC Helper 与真实编辑器预览校验

发布时间:2026/9/6 18:56:02 来源:尧图企业网站定制
OpenScreen Windows 原生光标捕获诊断流水线从 GetCursorInfo 采样器到 WGC Helper 与真实编辑器预览校验【免费下载链接】openscreenCreate stunning demos for free. Open-source, no subscriptions, no watermarks, and free for commercial use. An alternative to Screen Studio.项目地址: https://gitcode.com/GitHub_Trending/open/openscreen本文基于 OpenScreen 仓库的 Windows native cursor test pipeline 文档展开讲解两条专为 Windows 原生光标捕获设计的本地诊断流水线一条是不启动应用、直接用GetCursorInfo采样真实系统指针并产出规范化CursorRecordingData与预览视频的独立诊断脚本另一条是启动真实 Electron 应用、注入 fixture 视频与光标 sidecar 数据、从 OpenScreen 编辑器 UI 逐帧截屏并编码为 WebM 的预览校验脚本。读完本篇你将掌握这两条流水线的完整命令、环境变量、产物结构与内置断言逻辑并理解它们背后的 Windows 原生捕获后端WGC helper契约、可用性与 Click Bounce 已知缺口从而在不走完整“录制→编辑→导出”人工循环的前提下快速迭代光标渲染代码。1. 为什么需要这条诊断流水线OpenScreen 在 Windows 上把光标从“烧录进视频”改为“独立采样 后期重建”录制时系统指针被排除在画面之外光标位置、形状、hotspot 与点击事件以旁路数据sidecar形式记录再由编辑器预览和导出管线重新合成。这种架构让Size、Smoothing、Motion Blur、Click Bounce等光标效果可以在不重新录制的前提下反复调参但也引入了新的验证难题——任何采样、坐标归一化或 hotspot 计算上的偏差都会表现为预览/导出中光标漂移或形状错位。因此 docs/testing/windows-native-cursor.md 定义了两条刻意保持“本地化、快速迭代”性质的开发者工具它们只产出短视频与 JSON 报告让光标改动可以在几分钟内被肉眼与数据双重检查而不必每次都走一遍完整的人工 record/edit/export 循环。需要强调的是文档明确指出这两条诊断不能完全替代端到端的人工录制校验——在合入光标相关改动之前仍应在打包后的应用里做一次真实录制与导出。2. 诊断一原生光标采样器test:cursor-native:win2.1 命令与行为概览npm run test:cursor-native:win该脚本对应 scripts/test-windows-native-cursor.mjs在 package.json 中注册为test:cursor-native:win。它不启动 OpenScreen 应用而是完全独立地运行一次受控的光标捕获实验。脚本启动后会启动一个基于 WindowsGetCursorInfo的采样器PowerShell 内注入 C# P/Invoke 类型用SetCursorPos驱动真实系统指针沿一条正弦波形路径移动步长 120ms在路径中点还会注入一次真实的左键按下/释放用于验证点击事件捕获捕获原生光标句柄handle、hotspot、光标位图资产并把标准IDC_*光标类型与句柄做映射识别将样本写成规范化的CursorRecordingDatasidecar 兼容格式生成一个抽象预览视频路径 / 资产 / hotspot 叠加渲染生成一个真实屏幕预览视频以当前桌面截图为背景把重建的光标叠加上去。输出目录会打印在命令结果中形如C:\Users\user\AppData\Local\Temp\openscreen-cursor-native-...代码中实际是os.tmpdir()下以openscreen-cursor-native-${Date.now()}命名的目录。脚本在启动时强制检查process.platform win32非 Windows 平台直接报错退出。2.2 采样器的 Windows API 实现细节从 scripts/test-windows-native-cursor.mjs 的源码看采样脚本通过Add-Type动态编译一个OpenScreenCursorDiagnosticInterop类核心 P/Invoke 包括GetCursorInfo(ref CURSORINFO)每轮采样读取光标可见性标志flags 1、hCursor句柄和ptScreenPos屏幕坐标GetIconInfo/CopyIcon/DestroyIcon/DeleteObject把光标句柄转成Icon再绘制进 32bpp ARGB 位图并导出 PNGbase64 data URL同时读取xHotspot/yHotspot采样器对每个新句柄只抓一次资产$lastCursorId去重并在 finally 中释放 GDI 对象GetAsyncKeyState(0x01)轮询左键状态高 16 位为“当前是否按下”低 1 位为“两个采样之间是否发生过切换”SetWindowsHookEx(WH_MOUSE_LL, ...)低级鼠标钩子统计WM_LBUTTONDOWN/WM_LBUTTONUP用于捕获采样间隔之间的快速点击。标准光标识别使用一张IDC_*常量表arrow 32512、text 32513、wait 32514、crosshair 32515、up-arrow 32516、resize-nwse 32642、resize-nesw 32643、resize-ew 32644、resize-ns 32645、move 32646、not-allowed 32648、pointer 32649、app-starting 32650、help 32651通过LoadCursor(NULL, IDC_*)加载后与采样到的句柄比对。对于无法映射到标准类型的光标还有一段启发式分类尺寸 24–64px、hotspot 位置区间、不透明像素占比等尝试区分closed-hand/open-hand。真实指针驱动脚本buildMousePathScript会把主屏 bounds 内缩 80px在垂直方向叠加Sin(t * 2π)波形幅度min(180, height/4)在路径中点调用mouse_event(MOUSEEVENTF_LEFTDOWN) 12ms MOUSEEVENTF_LEFTUP制造一次合成点击桌面截屏脚本则按CURSOR_TEST_SCREEN_FRAME_INTERVAL_MS间隔把主屏CopyFromScreen到 960 宽的 PNG 帧序列并输出带时间戳的frames.json。2.3 产物结构与内置断言输出目录中的关键文件文件内容report.json采样数、资产数、唯一光标句柄数、唯一位置数、左键按下/点击样本数、错误数、首尾样本、生成产物路径cursor-recording-data.jsonsidecar 兼容的光标数据下文详述preview.webm抽象路径/资产/hotspot 预览1x/2x/3x 位图重建 矢量替换光标real-capture-preview.webm真实桌面截图背景 重建光标叠加assets/*.png从 Windows 捕获的原始光标位图events.json、report.html、real-capture-report.html原始事件流与可视化诊断页Playwright 无头 Chromium 打开后captureStream录制为 WebMcursor-recording-data.json的结构由toRecordingData生成version: 2、provider为native无资产时为none每个样本包含相对首个样本的timeMs、按主屏 bounds 归一化的cx/cy、assetId即光标句柄、visible、cursorType以及由左键状态转移推导的interactionTypeclick/mouseup/move每个资产包含id、platform: win32、base64 PNG、宽高、hotspotX/Y与scaleFactor: 1。脚本最后会执行assertReport即一组硬性验收条件任何一条不满足都会以非零退出sampleCount floor(DURATION_MS / SAMPLE_INTERVAL_MS / 3)采样连续性底线至少存在可见光标样本、至少捕获到 1 个光标资产 PNGuniquePositionCount 4指针确实发生了可观察的移动errorCount 0左键点击交互必须被观察到leftButtonPressedSampleCount 0且clickSampleCount 0。2.4 环境变量覆盖$env:CURSOR_TEST_DURATION_MS 3000 $env:CURSOR_TEST_SAMPLE_INTERVAL_MS 16 $env:CURSOR_TEST_SCREEN_FRAME_INTERVAL_MS 80 $env:CURSOR_TEST_OUTPUT_DIR C:\temp\openscreen-cursor-test npm run test:cursor-native:win结合源码完整的取值与默认值如下非法或非正值会被警告并回退到默认值环境变量默认值含义CURSOR_TEST_DURATION_MS1800指针驱动与桌面截屏的总时长msCURSOR_TEST_SAMPLE_INTERVAL_MS25GetCursorInfo采样间隔msCURSOR_TEST_SCREEN_FRAME_INTERVAL_MS100桌面截图帧间隔msCURSOR_TEST_READY_TIMEOUT_MS5000等待采样器ready事件的超时msCURSOR_TEST_OUTPUT_DIR系统临时目录下openscreen-cursor-native-时间戳产物输出目录3. 诊断二OpenScreen 真实编辑器预览捕获capture:openscreen-previewnpm run capture:openscreen-preview该脚本对应 scripts/capture-openscreen-preview.mjs与上一条诊断形成互补它启动真实的 Electron 应用注入 fixture 视频与光标 sidecar 数据打开编辑器从真实的 OpenScreen 预览 UI 逐帧截图再编码成 WebM。它回答的问题是诊断流水线里重建出来的光标行为在真实编辑器里是否渲染得一模一样。从源码看其完整流程是Sidecar 发现默认扫描系统临时目录中所有openscreen-cursor-native-*子目录里的cursor-recording-data.json取 mtime 最新者——即最近一次npm run test:cursor-native:win的产物找不到时直接报错提示先运行采样诊断。可用CURSOR_RECORDING_DATA_PATH强制指定具体文件不存在会抛错$env:CURSOR_RECORDING_DATA_PATH C:\path\to\cursor-recording-data.json npm run capture:openscreen-preview构建检查要求dist-electron/main.js与dist/index.html存在即先跑过npm run build-vite设置OPENSCREEN_PREVIEW_SKIP_BUILDtrue会跳过构建并只做存在性检查否则脚本会自动通过cmd.exe触发npm run build-vite。注入 fixture把 tests/fixtures/sample.webm 复制为openscreen-preview-fixture.webm并把 sidecar 复制为同名的.cursor.json再通过window.electronAPI.setCurrentVideoPathswitchToEditor让应用直接进入编辑器。逐帧截图等待编辑器窗口URL 含windowTypeeditor中的video与canvas选择器就绪设置 1280×800 视口静音并把currentTime依次置为index / FPS每帧等待 40ms 后对页面截图保存为frames/frame-XXXX.png。编码 WebM启动无头 Chromium把全部 PNG 帧按设定 FPS 绘到 canvas 上用captureStreamMediaRecorderVP9 WebM编码出openscreen-preview.webm。$env:OPENSCREEN_PREVIEW_SKIP_BUILD true $env:OPENSCREEN_PREVIEW_FRAME_COUNT 120 $env:OPENSCREEN_PREVIEW_FPS 30 $env:OPENSCREEN_PREVIEW_OUTPUT_DIR C:\temp\openscreen-preview npm run capture:openscreen-preview环境变量默认值含义OPENSCREEN_PREVIEW_SKIP_BUILD未设置即自动执行build-vite置为true时跳过构建仅校验产物存在OPENSCREEN_PREVIEW_FRAME_COUNT90从编辑器捕获的帧数OPENSCREEN_PREVIEW_FPS30逐帧定位间隔index / FPS秒与输出视频帧率OPENSCREEN_PREVIEW_OUTPUT_DIR系统临时目录下openscreen-real-preview-时间戳输出目录CURSOR_RECORDING_DATA_PATH最新一次采样诊断产物强制指定 sidecar 文件输出目录中的文件openscreen-preview.webm真实 OpenScreen 编辑器预览视频、frames/*.png逐帧截图、report.json含outputDir、sourceCursorRecordingDataPath、fixtureVideoPath、outputVideoPath、frameCount、fps。4. 两条诊断共同验证的能力按照原文档两条脚本组合起来可以快速检查Windows 光标样本是否可见且连续visibleSampleCount、sampleCount底线断言原生 hotspot 在缩放到3x时是否仍然锚定正确预览页同时绘制 1x/2x/3x 位图重建与红色十字 hotspot 标记标准 Windows 光标是否通过IDC_*被正确识别采样器句柄比对表高质量 SVG 光标替换是否跟随原生 hotspot诊断页中的 “pretty 3x” 矢量箭头即以同一 hotspot 为锚点绘制真实 OpenScreen 预览是否与诊断流水线渲染出一致的光标行为capture:openscreen-preview与preview.webm的对比依据。再次强调文档给出的边界这两条诊断不是完整端到端人工录制校验的替代品。光标改动在发布前还需要在打包应用里完成一次真实 capture session 与导出。5. 已知缺口Click Bounce 尚未可见生效原文档明确将 Windows 原生光标的Click Bounce标记为 backlogSize、Smoothing、Motion Blur可以通过预览/导出验证但Click Bounce在打包应用的人工测试中没有表现出可见效果。当前诊断只能观察到合成的点击元数据leftButtonPressed/clickSampleCount这不足以验证真实 OpenScreen record → preview → export 路径上的弹跳动画。该问题的完整跟踪项位于 docs/engineering/windows-native-recorder-roadmap.md 的 “Native Cursor Click Bounce Is Not Visibly Applied” 小节Backlog 部分其中记录了已尝试的手段向样本加入interactionType: click | mouseup | move、GetAsyncKeyState轮询与低比特位快速点击捕获、WH_MOUSE_LL鼠标钩子实验、把采样器改为临时.ps1文件以规避 Windows 命令行长度限制以及当前诊断结论采样元数据可以被记录但尚未转化为真实打包应用中可见的 bounce 效果后续排查方向包括检查真实.cursor.jsonsidecar 中点击的timeMs是否准确、对比原生 DOM 光标路径与旧版PixiCursorOverlay的点击视觉状态以及在必要时把点击事件下沉到小型原生光标 helper。6. 背景Windows 原生捕获后端WGC Helper理解上述诊断的价值需要知道它们所处的捕获架构。应用现已把 Windows 录制从 ElectrongetDisplayMedia切换到外部 WGC helper进程目的正是消除此前导致重建光标在预览/导出路径中漂移的“坐标与时钟分裂”。6.1 可用性规则Windows 10 build 19041 或更新版本存在可用的 helper 可执行文件。前者在 electron/ipc/handlers.ts 中由isWindowsGraphicsCaptureOsSupported实现解析process.getSystemVersion()的第三段作为 build 号判断build 19041不满足时 IPC 侧会返回 “Windows Graphics Capture requires Windows 10 build 19041 or newer.” 错误。helper 的可执行文件按以下顺序解析见 electron/native/README.mdOPENSCREEN_WGC_CAPTURE_EXE本地开发与诊断electron/native/wgc-capture/build/wgc-capture.exe本地 Ninja 构建产物electron/native/wgc-capture/build/Release/wgc-capture.exe多配置构建产物electron/native/bin/win32-x64/wgc-capture.exe或electron/native/bin/win32-arm64/wgc-capture.exe打包预构建。helper 目前实现显示器/窗口视频捕获、系统音频环回、默认麦克风捕获、Media Foundation 网络摄像头捕获以及针对 NVIDIA Broadcast 等特定虚拟摄像头的 DirectShow 回退。摄像头画面以右下角画中画叠加进主 MP4黑色预热帧会在首个可见帧出现前被忽略。光标采样的原生实现位于 electron/native/wgc-capture/src/cursor-sampler.cpp。6.2 构建与 smoke 测试本地构建 OpenScreen 的 helpernpm run build:native:win构建会把 CMake 产物写到electron/native/wgc-capture/build/wgc-capture.exe并复制到electron/native/bin/win32-x64/wgc-capture.exe。直接对 helper 做 smoke 测试npm run test:wgc-helper:win npm run test:wgc-helper:win -- --capture-cursor npm run test:wgc-window:win npm run test:wgc-audio:win npm run test:wgc-mic:win npm run test:wgc-mixed-audio:win npm run test:wgc-webcam:win这些脚本名在 package.json 中统一映射到 scripts/test-windows-wgc-helper.mjs 及其不同的 CLI 参数--window、--system-audio、--microphone、--webcam等。如需对某个特定摄像头/麦克风做手动验证还可分别设置OPENSCREEN_WGC_TEST_WEBCAM_DEVICE_NAME/OPENSCREEN_WGC_TEST_MICROPHONE_DEVICE_NAME见 electron/native/README.md。6.3 指向自定义 helper 与进程契约若要在本地诊断中使用另一个兼容 helper把环境变量指向该可执行文件再启动开发态应用即可$env:OPENSCREEN_WGC_CAPTURE_EXE C:\path\to\wgc-capture.exe npm run build-vite npm run devhelper 的进程契约应用以一个 JSON 配置参数启动该进程helper 输出 JSON 生命周期事件并打印遗留的Recording started标记应用通过 stdin 发送stopstop\n来结束录制helper 最终打印Recording stopped. Output path: path。V2 JSON 配置形态含schemaVersion、sourceType/sourceId、outputPath、fps、captureSystemAudio/captureMic、麦克风/摄像头设备与增益参数、outputs.screenPath等字段的完整示例与字段说明见 electron/native/README.md。7. 实操建议推荐的验证顺序结合两条诊断与 helper smoke 测试一个典型的光标改动验证流程是修改光标采样/渲染相关代码后先跑npm run test:cursor-native:win让assertReport的连续性、可见性、资产、移动、点击五类断言自动把关并打开real-capture-preview.webm目测 1x/2x/3x 与矢量替换光标的 hotspot 锚定用同一份最新的cursor-recording-data.json跑npm run capture:openscreen-preview可配OPENSCREEN_PREVIEW_FRAME_COUNT120对比openscreen-preview.webm与诊断预览是否行为一致涉及捕获链路时依次执行test:wgc-helper:win系列命令确认 helper 各通道含--capture-cursor正常合入前在打包应用中完成一次真实录制会话与导出的人工端到端校验Click Bounce在未关闭 roadmap 中的 backlog 项之前不应被视为已交付能力。【免费下载链接】openscreenCreate stunning demos for free. Open-source, no subscriptions, no watermarks, and free for commercial use. An alternative to Screen Studio.项目地址: https://gitcode.com/GitHub_Trending/open/openscreen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价