概览
dsh-screenshot
README / ZH
插件文档
目录摘要
dsh.pub 核对固定版本的组合包契约、运行时事实与分发语义;完整 README 请查看源仓库。
在 GitHub 阅读完整 READMELIMITATIONS
已知限制
- **仅在本机 Windows + DSH `desktop` profile 实测**,其他平台/版本未验证。 - 长截图的 auto 模式**优先投递滚轮**(不动光标),判定靠"下一张画面变没变"。投递要投给 **点位下面那个控件**:投给顶层窗口时 Chromium 认、**WinForms 等旧式应用不认** (实测:顶层窗体只触发自己的 MouseWheel,内容不滚;投给 `WindowFromPoint` 的叶子才滚)。 不认时自动降级成移光标。Qt / Java / Electron 的自绘滚动容器**尚未逐个实测**。 - 长截图**一次滚一格滚轮,不是滚"一屏的 80%"**(R58 改的)。滚轮的 `delta` 单位是 1/120 格, 应用再按自己的行高翻(WinForms 默认 3 行/格):以前按像素发(520px 区域 → `-416`), 被读成 3.5 格 ≈ 10 行,**一次滚掉 811px,比一屏还高** —— 两帧之间没有重叠,拼接器只能猜。 现在按格发;一格的位移由目标应用决定。 - 但**一格能滚多远是应用决定的**:40pt 大字一帧 ≈ 237px,而 10pt 小字一帧只有 **60px**。于是 "一帧固定一格"能覆盖的总高 = 帧数上限 × 一格 —— 后者在密集小字页面上只够 ~2900px,一张 3840px 的页面会被**静默截掉一截**(R60 实测:40 帧停在 2880px,`stopReason` 还是空的,用户 看到的就是一张"正常"的长图)。现在**每帧滚几格按实测位移自适应**(R60):滚过一帧就知道一格 值多少像素,把步长调到区域高度的 ~45%(上限 3 格,重叠仍剩一大半);同一张 3840px 页面 **18 帧**到底、每条色带 160px 一条不差。撞到帧数上限时 `stopReason='max-frames'`, 客户端会明说"后面可能没截完",不再说"已经到底了"。 - 拼接器**不接受"没有重叠的两帧"**:残差超过阈值就报错并保留会话("滚得太多了,分两次滚"), **不会**再静默拼出一张又高又像真的错图(R58 用探针量到过 +479px 的静默重复内容)。 只差几个像素的重复帧(光标闪烁、时钟跳秒)会被识别成"同一张画面"直接跳过,不再塞进一段重复内容。 - 拼接偏移在缩小图上粗搜之后,再做一次**全分辨率精修**:粗搜的量化误差是 ~4px/像素, 以前每条接缝会因此偏 2px(重复/丢掉 2px 内容),现在缝落在像素上(探针断言每条色带 79px)。 - 长截图的区域**外缘**如果有会自己动的东西(滚动条拇指、缩放手柄、贴边浮层),那些列在帧间 就不一致。拼接器现在**两遍(粗搜 + 精修)都先裁掉外缘**(宽度的 6%,至少 6px、至多 40px)再找 重叠(R59),所以滚动条可见也能拼。实测:R58 的真实帧在未裁边时精修残差 **0.20–0.22**(左缘在闪 的光标),裁边后 **0.00**,偏移不变;合成的"右侧 14px 滚动条 + 拇指每帧移动"四帧,偏移 237/237/237 与真值一致(不裁边时同一组会挑错偏移)。 - 区域**内部**有东西自己动(视频、转圈、每帧重画的图表)时,**整块区域在帧间永远不一致**。拼接器 先按普通残差找接缝;判成"没有重叠"时才走第二条路 —— 它看的不是"残差降下来了没有",而是 **分歧长在哪儿**:动画是一块紧凑区域,错的偏移是满屏字都对不齐(R63)。实测:一块 220×130 每帧 重画时,真值处的普通残差是 **29.29**(远高于 8.00,任何残差都不可能接受它),而"分歧外接框"只占 重叠的 **0.48**、框内 **49%** 像素超阈值;错偏移是 **1.00** / 27%。这条判据在**真实屏幕纹理**上 也是对的(`dev/stitch-tex-probe.mjs`:四条臂的偏移逐帧精确,动画块之外的成品与真值**逐像素相同**)。 ⚠️ R61 用的是"去掉最差 30% 的行"的评分,它在色带夹具上成立,但在真实纹理上会**偏向最窄的重叠** (真值 237 px,裁剪评分选 386 / 397 / 509,还静默多贴过 +160 px)—— 这是 R63 换掉它的原因。 - **窄到几行的重叠不算证据**(R63):27 行真实文字能巧合地给出 **2.37** 的平均差,于是错了 256 px 还"看起来像真的"。重叠不足区域高度 35% 时,只有**逐像素精确**(残差 ≤ 1.0)才作数 —— 色带夹具 真的会一格滚掉 75%,它每次都精确到 0.00,所以这条不会误伤真截图。 - **窄重叠"精确"也可能落在错的偏移上**(R65,真实纹理上抓到的真 bug):一页应用(一次滚一屏减一行, 25% 重叠)某一对帧有两个**逐像素精确**的候选 —— 真值 390(130 行证据)与 477(43 行,因为页面上 43 行内容自己重复了 87 px)。粗搜在 2.6:1 的缩小签名上偏好 477(43 行缩成 16 行签名全等,而 390 落不到签名行上),旧规则又把它当"精确"接受 → 成品 4117 而不是 4030(**静默 +87 px**、243 523 个 像素错)。现在窄重叠会**重判一次**:在这些候选里取**最深的最小值**,一样深时取**重叠最多**的 (`py/stitch.py#find_exact_shift`)。实测同一条夹具 4117 → **4030 且逐像素相同**。 另一半也是实测的:同一条臂上另一种错法(386,"只比真值差 4 px")也被这条规则挡住 —— 它落在容差里 但不是最深的最小值。 - **窄重叠 + 重叠带里有东西在动 = 诚实的拒绝**(R65):重叠只剩 25%、而那块每帧重画的区域正好压在 重叠带里时,这一带**没有任何可用证据**(真值处残差 37.98 > 8.00),结构判据又**故意**不看 35% 以下 的重叠(R63:11 行文字满足过它,并挑了个错的 509 px)。所以它会报 `no-overlap`、退出 3、**不出文件**, 而不是拼一张看起来对的图。自动滚的步长是区域高 45%,正常不会走到这里;真遇到就"分两次滚"。 - 同位置重复帧**仍然先判后拼**("内容没前进、只有那一小块在变")。顺序反了会把重复帧按猜出来的 偏移贴进去 —— R63 实测:色带夹具 + 动画那条臂因此多出 **158 px** 重复内容。 - **已知边界**:在动的那块会在成品上留一道"重影"(每帧各贴了一次),这是拼接的必然结果;这种情况 自动滚也认不出"到底"(整帧永远在变),会话会走到帧数上限并如实报 `max-frames`("后面可能没截完"), 但成品本身是完整的。 - 上面这几条现在有**真实纹理**上的独立探针(R63,R65 扩到六条臂):`dev/texreplay.py` 拿一张真截屏 造长页面、切出已知帧,六条臂分别断言"偏移逐帧精确 / 成品与真值逐像素相同(动画块那几列除外)/ 同位置帧跳过 / 跳太远必须报错 / 窄重叠也精确 / 窄重叠+动画必须拒绝"。它第一次跑就抓到两个真 bug (上面两条 ⚠️),R65 加窄重叠臂时**又抓到第三个**(上面那条 +87 px)。 - 改拼接器时先看 `texreplay.py landscape`(R64):它把**每个评分的前几名**和**真值处的四个数** 摆在一起(`python dev/texreplay.py landscape --dir <build 出来的目录> --pair <第几对>`)。R63 那四个 bug 没有一个能从产品 JSON 里看出来 —— 每个评分都只报"一个数字"。实测(真实纹理、真值 237): 普通滚动时真值是唯一 0.00、结构判据在 486 个位移里**只认它一个**;动画页里真值处普通残差 **29.33**(任何残差都不能接受),而按行裁剪与普通评分都会选到 **511**(最窄重叠),结构判据仍只认真值。 - 夹具(`dev/longshot-backdrop.ps1`)默认藏滚动条;`-Scrollbar 1` 保留它,探针的第四条臂就是 用这个跑一遍 auto,证明上面那条不是纸面结论。 - **剪贴板是全机独占资源**:别的程序正占着时截图复制会失败(实测报「所请求的剪贴板操作失败」)。 助手会重试 4 次;仍失败时**客户端会明说"没复制成功"并留下诊断**,不会假装复制过。 - 「截图时隐藏 DSH 界面」靠**标题**找窗口(`DeepSeek Harness` 子串匹配);窗口标题被改得 面目全非时只会不藏(截图照常),不会报错。 - 私有备份仓:按 `.gitignore` 排除了 `node_modules`、运行时缓存、调试 dump 与备份文件;要复现运行请自行 `npm install`(如有依赖)。 - 文档中出现的 `$DSH_WORKSPACE`、`$TK_ROOT`、`%USERPROFILE%` 等是**占位符**,使用前需替换成本机实际路径。
