中文EN

dsh-see-now

vision已测通过npmApache-2.0

让只有文字的智能体「看」实时屏幕或摄像头:每帧按画面变化量打分,只把真正变了的帧拼成一张带编号、带音轨条的宫格图——看视频、看演示、看游戏都行,token 只花在变了的地方。

下载量 / Downloads
6,403
依赖体积 / node_modules
1.98 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-see-now

沙箱测试结果

阶段结果
1 安装✓
2 列装✓
3 挂载✓
4 启动—

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

See Now · 让 AI 实时看见你的屏幕

AI 不再"听你描述屏幕",而是自己看 —— 而且只传"画面变了"的那几帧。

一个给 DSH 用的实时视觉插件:把你的屏幕(或摄像头 / 视频文件)变成一串按变化量筛选过的画面,压进一张几帧拼成的图,交给模型。

静止的屏幕几乎不花钱;一镜到底的视频按"运动量"给帧;硬切幻灯片每切一次留一帧。


授权说明 / License

Apache License 2.0 —— 随便用。个人、公司内部、闭源产品、SaaS、二次分发都可以,

不需要问我要授权,也不收费。只要保留 [LICENSE](./LICENSE) 和 [NOTICE](./NOTICE) 这两份文件。

如果你觉得它替你省了时间,欢迎扫码打赏 —— 纯自愿,不影响上面任何一个字:

<p align="center">

<img src="./docs/images/reward-qr.png" alt="赞赏码(微信 / 支付宝)" width="240">

</p>

提交 PR 前读一下 [CONTRIBUTING.md](./CONTRIBUTING.md) —— 现在不需要签 CLA 了,

按 Apache-2.0 的规矩来就行。


看看它长什么样

调试窗(开发期用,不在发布包里):左边是抓到的每一帧,留下的带缩略图和格号,没留下的只剩一根分数条;右边是正在拼的那张图,按真实像素位置摆,新帧落格会亮一下,重排时格子会滑动。

逐场景模式(scene:true):每换一次画面单独出一张满幅图,右下角「已出图」每条都标着 1 帧 100%。

悬浮窗:AI 说的话在这里出现并被念出来(say 是唯一通道)。

外观可以在设置 › 看你看的东西 › 悬浮窗样式里换:实时玻璃(跟着桌面模糊,吃 CPU)、

静态磨砂(不抓屏,CPU 接近 0 —— 觉得卡就选它)、纯色、自动。改完立刻生效,

不用重开 DSH;它和陪看共用同一份 ~/.dsh/watch-window.json。


它解决什么问题

想让 AI 陪你看屏幕,最直觉的做法是"定时截全屏喂过去"。两个死结:

做法 · 问题

每 2 秒截一张全屏 · 一分钟 30 张图,全是重复画面,token 直接烧穿

每隔 30 秒截一张 · 中间发生了什么全丢了,AI 只会说"看起来你在用电脑"

See Now 换了个思路:先判断这一帧值不值得看,再决定传不传。

  • 每个画面帧先打一个 0–255 的"变化分"(HSV 三通道加权差,在 64×36 网格上算,约 0.2ms)
  • 只有"画面突然换了一张"或"一直在动、攒够了量"才留下来
  • 留下来的几帧拼进同一张图,一张图的固定成本摊到 4~8 帧上

结果:同样一段 30 秒的操作,别人烧 30 张图,这里常常只要 2~3 张。


有多省

场景 · 表现

静止屏幕(看文档、发呆) · 几乎不出图。20 秒给一张兜底帧,让你知道"确实没变"

滚网页、切窗口 · 变化剧烈 → 留几帧 → 每 15 秒左右给你一张

一镜到底的视频 · 没有切点,靠"积分"攒够一个采样点才出帧

硬切幻灯片(每张停 2 秒) · 每切一次留一帧,6 张照片 → 6 帧

成本口径(按宿主 DeepSeek-V4 的 patch 网格算:14px patch 向上对齐 → 42px 一格 → rows×(cols+1)+2):

档位 · 画布(画面 + 音轨条) · 每张 token

low(默认) · 798×450 + 12px = 798×462 · 222

standard · 1050×600 + 30px = 1050×630 · 392

high · 1260×720 + 36px = 1260×756 · 560

ultra · 1596×900 + 24px = 1596×924 · 860

一张图里塞 4 帧还是 8 帧,价格一样 —— 所以"多留一帧"几乎免费,"漏掉一帧"才贵。

宽度故意不对齐 16:9,而是对齐 42(800→798、1066→1050、1280→1260、1600→1596):

800 会被 pad 到 812 = 19.3 格,白算一整列;798 正好 19 列,面积只少 0.25%,每张省 11~24 token。

这是整个链路里唯一零代价的降本点(storyboard 那边也是这么干的)。

音轨条不额外花钱:token 是按 42px 一行算的阶梯函数,450 高的画面占 11 行、上界 462 ——

底下空着 12px 也照样收 11 行的钱。条就用这 12px(其余档位同理:600 余 30、720 余 36、900 余 24)。

所以"加条"和"不加条"的 token 完全一样,关掉它只是图干净一点,省不到钱。

看久了会变贵 —— 但原因不在这个插件

每张 222 token 只是编码成本。真正吃钱的是累积:图在会话历史里是一段 base64,

一张 798×450 的 PNG 约 130 KB,base64 之后约 173 KB。

DSH 有个「图片省略」机制:**单个请求里保留的 base64 图片总量超过 maxRequestImageBytes

(默认 20 MiB)时,它会把最老的图片永久替换成一段「附件路径」占位文字,然后重试。**

关键词是永久 —— 它改的是会话历史本身。历史一改,DeepSeek 的前缀缓存从被改的那个

位置往后全部对不上:每省略一张老图,那一段上下文就重新计费一次。

(社区实测:图片从第 43 万 token 处才开始出现,每省略一张,后面 14 万 token 重新算钱。)

换算:20 MiB ÷ 173 KB ≈ 120 张。dense 档 110 秒出 6 张(社区实测),一小时约 200 张 ——

半小时出头就撞线;默认节奏 15~40 秒一张,也在 1 小时上下。

这个插件拦不住它:省略发生在宿主发请求之前,插件只看得到自己交付的那张图。能做的只有:

  • 长会话分段:陪看一两小时后开个新会话,比让老图被反复省略便宜得多;
  • 别一直挂 dense:出图频率是默认档的两三倍;
  • 静止画面本来就不出图 —— 那段时间是真的免费。
真要根治得在宿主侧:让省略从最前面开始(连同更早的历史一起截),而不是在历史中间
挖一个洞 —— 那样前缀缓存仍然连续。这不在本插件的范围里。

快速开始

在 DSH 里用

已经发布到 npm,用 DSH 自带的 dsh plugin 装(它本质是 profile 维度的 pnpm 包装器 +

插件登记器,会在装前预检 engines/peer、装后自动把 dsh.bundle 写进 profile):

dsh plugin --profile web add dsh-see-now
  • web 是浏览器里用的那个 profile;桌面版换成 --profile desktop(那个 profile 需要先开过一次桌面端才会被初始化)。
  • 装完重启 DSH 生效(插件树在进程启动时组合)。
  • 重启之后不用新开会话:工具表是每一步重新组装的,旧会话下一轮就能看到 see_now

(宿主还会插一条 tool-addition 告诉模型多了这个工具)。所以「工具表在会话开头就定死了」

不成立 —— 挂不上多半是没重启,或者装的是旧副本。

  • 卸载:dsh plugin --profile web remove dsh-see-now
  • 升级:dsh plugin --profile web update dsh-see-now

关掉悬浮窗之后想再打开:点 × 只是这一次不看,插件不会自己弹回来。手动叫:

npx dsh-see-window            # 开窗(已经开着就什么都不做)
npx dsh-see-window --status   # 只看它在不在
npx dsh-see-window --force    # 杀掉重开
npx dsh-see-window --close    # 关掉

<details>

<summary>从源码装(改代码时用)</summary>

git clone https://github.com/SAOS-3624/dsh-see-now.git
cd dsh-see-now
node scripts/install-dev.mjs      # 拷进本机 DSH 的 desktop profile
install-dev 是复制不是软链(Node 解析裸包名要走真实路径,软链会找不到宿主的
@deepseek-ai/dsh-tools)。装完同样要重启 DSH。

</details>

平台

平台 · 屏幕引擎 · 要额外做的

Windows · ddagrab,不行退 gdigrab(自动探测) · 无

macOS · avfoundation · 系统设置 → 隐私与安全性 → 屏幕录制,勾上跑 DSH 的 App

Linux · — · 还没接(要补 x11grab / PipeWire)

「看屏幕」和「悬浮窗」是两件事,上表说的是采集引擎。悬浮窗(Tk)在 0.1.4 之前
在 macOS/Linux 上必崩(ctypes.windll,issue #40),现在能起来了:Windows 专有的
DPI/WDA 调用都按平台收口,没有 WDA 的系统改走"抓到自己就填掉"那条路。
Retina 上窗口坐标是逻辑像素、和 mss 的物理像素会差一个缩放倍数,背景可能对不齐 ——
那类机器在设置里选 frost(静态磨砂)或 solid(纯色),这两档都不抓屏,不吃这个亏。

ffmpeg 不用进 PATH:插件会按 DSH_FFMPEG_PATH / FFMPEG_PATH / DSH_FFMPEG_DIR /

~/.dsh/tools/ffmpeg/bin / ~/.dsh/bin 的顺序自己找(DSH 桌面版把 ffmpeg 装在第四个位置)。

然后让模型调:

see_now({ action: "watch" })          // 阻塞到你攒够一张图,然后把图交回来
see_now({ action: "watch", say: "…" }) // 同时说一句话(只有 say 会进悬浮窗、会被念出来)

第一次调用约 1 秒返回当前屏幕;之后每次返回"这段时间里发生的事"。

不进 DSH,当普通 Node 库用

包本身不依赖 DSH,capture / pipeline / png 都是独立导出的:

import { spawnFrames } from 'dsh-see-now/capture';
import { createPipeline } from 'dsh-see-now/pipeline';

const p = createPipeline({ width: 800, height: 450, fps: 12, queueDepth: 0 });
const run = spawnFrames({
  source: { kind: 'screen' },           // 或 { kind:'file', path:'x.mp4' }
  width: 800, height: 450, fps: 12,
  onFrame: (f) => p.push(f),
});

setInterval(() => {
  const sheet = p.take();               // 一张 PNG + 每帧的时间戳/档位/来源
  if (sheet) require('fs').writeFileSync(`sheet-${sheet.at}.png`, sheet.png);
}, 200);

声音

核心不内置任何 TTS 引擎,只 dynamic import 一个你指定的模块。配好之后,

say 会进悬浮窗并且被念出来;普通回复永远只有字。

// ~/.dsh/voice.json
{ "adapter": "/绝对路径/examples/voice-say-mac.mjs" }

自定义模型:适配器自己的配置走 options,原样交给 attach(api, options) ——

换自己训的模型不用改适配器源码:

// ~/.dsh/voice.json
{ "adapter": "D:/my-voice/index.mjs", "options": { 

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:16,最后更新 2026-11-06

链接

GitHub · Homepage · npm

同类插件