DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins

dsh-mobile-use

Mobile Use

Put a real phone in the DSH right panel: interact directly with the live mirror, circle an area to annotate and send it back to the session, and let the model read the UI text tree without screenshots. Uses only the local loopback; no screen uploads.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add dsh-mobile-use@1.4.34
READMECompatibilityVersions

Compatibility and provenance

Mobile Use is published as dsh-mobile-use and currently resolves to version 1.4.34. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
npm
Registry updated
11/4/2026

Versions

1.4.34stable
11/4/2026
1.4.33stable
11/3/2026
1.4.32stable
11/3/2026
Show 41 more versionsCollapse versions
1.4.31stable
11/3/2026
1.4.30stable
11/1/2026
1.4.29stable
11/1/2026
1.4.28stable
11/1/2026
1.4.27stable
11/1/2026
1.4.26stable
11/1/2026
1.4.25stable
11/1/2026
1.4.24stable
11/1/2026
1.4.23stable
11/1/2026
1.4.22stable
11/1/2026
1.4.21stable
11/1/2026
1.4.20stable
11/1/2026
1.4.19stable
10/31/2026
1.4.18stable
10/31/2026
1.4.17stable
10/31/2026
1.4.16stable
10/31/2026
1.4.15stable
10/31/2026
1.4.14stable
10/31/2026

Related plugins

Loading related plugins…

Latest
1.4.34
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
7.3 MB
Files
48
Surface
web
License
MIT
Source
npm
GitHub
★ 2
Weekly downloads
7,816
Security scan
✓ v1.4.34 scan passed
Last push
11/4/2026
View source ↗Project homepage ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
1.4.13stable
10/31/2026
1.4.12stable
10/31/2026
1.4.11stable
10/31/2026
1.4.10stable
10/31/2026
1.4.9stable
10/31/2026
1.4.8stable
10/31/2026
1.4.7stable
10/31/2026
1.4.6stable
10/31/2026
1.4.5stable
10/30/2026
1.4.4stable
10/29/2026
1.4.1stable
10/29/2026
1.4.3stable
10/29/2026
1.4.2stable
10/29/2026
1.4.0stable
10/29/2026
1.3.0stable
10/29/2026
1.2.1stable
10/28/2026
1.2.0stable
10/28/2026
1.1.1stable
10/28/2026
1.1.0stable
10/28/2026
1.0.4stable
10/28/2026
1.0.3stable
10/27/2026
1.0.1stable
10/27/2026
1.0.0stable
10/27/2026

Related plugins

More verified plugins in vision-media.

Experimental Voice Input Bundle@deepseek-ai/dsh-experimental-voice-input-bundleExperimental voice input with local SenseVoice; downloads its runtime on first useModlens@liustack/modlensPlug-in vision for text-only LLMs, powered by the free Antigravity CLIImage Gendsh-image-genBring ChatGPT-like image generation to DeepSeek Harness — Gemini, OpenAI, Seedream, DashScope, local ComfyUI & more.Ab Ocrdsh-ab-ocr--- description: "The out-of-tree ocr tool: recognizes a scanned PDF or image page by page, merges the pages in order only after the last one, and saves one Markdown document with the heading levels the model decided." kind: "package-reference" ---

README

dsh-mobile-use · 把真手机装进 DSH

右栏就是你手机的画面:点一下是设备上点一下,圈一处再写一句话,带圈图和圈内控件一起回到会话。

模型不用截图也知道屏上有哪些字、哪个按钮能点、刚才点了之后变了什么。装一次,DSH 里所有会话都能用——不需要 MCP 行、不需要额外 agent、不上传任何画面。

git clone https://github.com/regrevia/dsh-mobile-use.git dsh-mobile-use
# 在 DSH 里:plugin_manager action=install_bundle target=$HOME/dsh-mobile-use

环境变量(都可选):ADB(adb 路径)、ANDROID_SERIAL(默认设备)、FFMPEG(转码路径)。见 .env.example。 宿主需要 adb(Android platform-tools);镜像还要 ffmpeg。设备端辅助程序(uiautomator2)随包附带,首次使用自动推送。

三个真正不同的地方

① 实时镜像,不是截图循环。 侧栏「实时ADB」走 screenrecord H.264 → 宿主 ffmpeg 抽帧转 fMP4 → MSE 播放:首帧 1380 ms,画面一变到上屏 +163 ms,静止时约 1 帧/秒(内容驱动),最后一个观众走后留 20 秒,重开实测 2440 ms → 18 ms。点按按真实媒体矩形归一化,缩放、平移、横竖屏同一套算法。

② 圈选标注,把「这里」说清楚。 在画面上圈一块,连圈图 + 圈内控件 + 前 12 秒操作时间线 + 最近 6 秒 6 帧拼图一起推回当前会话。拼图取自内存最近 40 帧,265 ms 建好、112 KB,不碰设备、不 seek 还在写的录屏文件。

③ 读界面,不截图。 设备端常驻 uiautomator2:adb_ui 一次 120 ms 返回「文字 + 资源 id + 中心坐标 + ref」,压成 200–1300 token 纯文本;同样一次确认,screencap -p 要 0.5–3.2 s、0.3–8.9 MB,再花一次带图推理。自绘/Flutter 文本树为空时自动补一层本机 Vision OCR 兜底。不想走视觉模型时还有两条免视觉通道:adb_look 把屏幕压成颜色网格并给出区域差异(热 32–41 ms),adb_ocr 直接认右栏直播帧(热 110–116 ms)。

作品牌差异一句话:同类插件多在让 DSH 的网页适配手机或让手机连回电脑,这个方向相反——把手机装进 DSH,让 AI 直接操作真机。

同一块地盘上还有谁

手机方向在 DSH 生态里已经有人做,各自解决的其实不是同一件事(摘自插件市场当前介绍):

  • 从手机连回电脑:liguobao/ds-harness-remote、wenbin-wb/dsh-bridge —— 把正在跑的会话推到手机浏览器里继续,手机是显示器。
  • iOS 设备上的操作:ZSeven-W/dsh-ios —— 模拟器或 USB 连接的 iPhone,按无障碍标识或 OCR 操作,带可点的侧栏面板。

这个插件是第三条:Android 真机、画面进右栏、标注带回去。差别不在「工具数量」,而在模型看到的就是设备本身——文本树 120 ms 给出文字与坐标,画面一变 163 ms 上屏,圈一处就把「这里」变成一条带图的消息。

为什么

原做法是 adb exec-out screencap 出 PNG,再 read_image 让模型看图。一次「确认页面对不对」要花:一次截图进程 + 一张几百 KB~9 MB 的图 + 一次带图的模型步。

实测(小米平板 8,3200×2136,Android 15,2026-10)对比同一动作的两种取法:

取法耗时返回体积模型侧成本
adb -s X exec-out screencap -p0.5 s(纯色页)/ 3.2 s(相机页)0.3–8.9 MB PNG1 张图 ≈ 1.5–2 k token + 一次带图推理
adb -s X exec-out uiautomator dump /dev/tty0.33 s(静态页)/ 2.2 s(持续动画页)8 KB XML压成 460–2872 字符 ≈ 200–1300 token 纯文本
uiautomator dump --compressed2.1–2.4 s5.6 KB不要用,慢 6 倍换 30% 体积
dumpsys activity 取前台 Activity0.07–0.09 s一行判断「有没有进目标页」用它
logcat -d -t 2000.11–0.14 s数 KB看报错用它

耗时不是全部:截图那条路每次还要一次 read_image 往返,文本树直接把「文字 + 资源 id + 中心坐标」写进上下文,点击不再需要算坐标。

工具

工具作用
adb_ui读界面文本树:ref、控件类型(语义角色:Text / Btn / Img / Input / Switch / List …)、文字、#资源id、@中心坐标,尾部 * 可点击 / ~ 可滚动 / [x] 勾选 / [off] 不可用。支持 filter、full、depth(只列到第 N 层)、max_nodes(默认 400,打满会明说「已截断」并给收窄办法)、wait_for_text / wait_for_id / wait_for_activity / wait_activity_gone(等离开启动页/登录页)/ wait_until_gone(替代 sleep + 反复截图);within_ref / within_rect 只看一块(列表里某一行的内部结构、抽屉里的按钮),框外控件不占行、深度按框内重算;等待也能用 wait_for_xpath / wait_xpath_gone
adb_wait只等条件、不返回整棵树,省 token(回执带「N 次轮询」看等待花了多少 dump)(within_ref / within_rect 只看框里的控件,等某一行里的按钮):text / id / desc / gone / texts(全出现)/ any_texts(任一出现)/ activity / activity_gone(等离开启动页/登录页)/ stable(界面静止)。超时会说清停在哪个页面、能点什么;until 等同一个控件进入某状态(enabled / clickable / checked / focused)才返回,灰按钮不会误判成等到;dismiss: true 被权限/升级/评分弹窗挡住时自动点掉确认按钮(最多 2 次)再接着等,回执列 dismissed;没等到会自动留一张截图(shot.path,只失败才抓);也能等 xpath 命中 / xpath_gone 消失;列表刷到 ≥N 项用 count_min(配 text/id/desc/xpath)
adb_tap按 ref / text / id / desc / point="x,y" 点击(within_ref 限定在某一行/容器里找,点行内按钮不用先算坐标),long: true 长按;可带 wait_for_text / wait_for_id / wait_until_gone / wait_for_activity / wait_activity_gone 点完直接等结果,或 wait_stable 等界面静止再回执「变了没变」;回执里 changed 说变没变,reason 给原因码(keyboard-covered / obscured / unclickable / / / / ), 直接列出这次多/少了哪几行;没生效还会自动留一张截图();点后等待也吃得下 / ; 点完留一张截图(省一次 ); 顺手把点完的新树带回来(判变化时本来就读过,ref 属于新快照,接着点下一项不用再 )

adb_wait 这类等待不是死等:前 600ms 每 120ms 读一次,界面一直没变就退到 240→600ms 一次,10 秒超时下省掉一多半 dump;超时前还会补一次带 OCR 的读,自绘界面不会被判成「没有」。

文字匹配前会去掉零宽字符(\u200b、BOM、方向标记)并把连续空白归一成一个空格:屏上明明写着却「找不到」的情况,多半是标题里夹了看不见的字符。

失败回执是统一的:前台页面 + 屏上前几行 + 截图路径,再加上 crash 缓冲里有没有 FATAL EXCEPTION(有就直接点名去看 adb_crash)——「没找到控件」和「应用崩了」不用再自己排查。

性能

同一台测试机(小米平板 8,3200×2136,Android 15,USB 直连,宿主 macOS,2026-10)上的实测。下表数字均为实测;约 1 帧/秒 是内容驱动下的实测近似值,不是估算。

能力旧做法现在实测
截一张图exec-out screencap -p 出 PNGexec-out screencap -j 设备端直出 JPEG,按右栏显示宽度缩放PNG 3.2 s / 8.9 MB → 330 ms;900 px 34 KB,600 px 19 KB
读界面文本树uiautomator dump 每次冷启动uiautomator2 常驻服务直接读树dump 350 ms → 120 ms
单条 adb 命令每条 execFile 起一次 adb每台设备一条常驻 adb shell 通道33 ms → 20 ms
侧栏直播JPEG 长轮询逐帧抓(保留作兜底)screenrecord --output-format=h264 + ffmpeg 转 fMP4 + MSE960×640;首帧 1380 ms;画面一变到上屏 +163 ms;空闲约 1 帧/秒(screenrecord 内容驱动)
近 6 秒回看连拍截图再拼本地环形录像抽 6 帧拼图,不碰设备6 帧拼图 365 ms
多步操作一步一个工具往返adb_do 一次调用串起多步2 步 318 ms
侧栏重开每次重新起流、等首帧最后一个观众走后录屏留 20 秒冷开首帧 2440 ms → 20 秒内重开 18 ms
只截一块截整屏再自己裁adb_shot region 在宿主侧裁640×420 13 KB(整屏约 80 KB),732 ms
判断界面变没变每次重截整屏再比像素adb_look 采样推流里的最新一帧,不碰设备冷启(截图 648 ms)1096 ms → 热帧 164 ms(帧龄 34 ms),约 6.7×
读某块区域的字截整屏再识别adb_ocr region 从推流帧裁出那一块,只识别它1000×600 区域 121 ms(p50,连续 460 轮浸泡)
  • 截图这条路省的是设备编码、回传体积和浏览器解码三段:PNG 3.2 s / 8.9 MB,JPEG 330 ms,900 px 34 KB、600 px 19 KB;右栏只显示几百 px 宽,按显示宽度缩放后体积和延迟一起降。
  • 读界面默认走文本树:uiautomator2 常驻 120 ms,比朴素 uiautomator dump 的 350 ms 快近 3 倍,返回的仍是可点的文字 + 资源 id + 坐标。
  • 每条命令的开销在通道不在命令:常驻 shell 把起进程的 33 ms 压到 20 ms。
  • 直播按内容驱动:H.264 960×640 在画面静止时约 1 帧/秒,变化到上屏 +163 ms;首帧 1380 ms 含页面加载与建流;MSE 起不来时仍退回 JPEG 长轮询。
  • 侧栏重开几乎是零成本:录屏与最后一段 IDR 都还在,20 秒内重连直接用,实测 2440 ms 降到 18 ms;超过宽限才真正停掉。
  • 区域裁切省的是 token 而不是设备时间(整屏 screencap 仍要跑),但一张 640×420 的图比整屏小一个量级,模型看细节反而更准。
  • 起流失败的两个真实原因都已处理:本地 adb 被强杀后设备端 screenrecord 会活到 --time-limit,占住编码器让下一次开流必失败;同一毫秒起两个录屏也会互相打架。现在开流/停流都先清残留,且只有真故障才置错误。
  • 窗口层不用额外 dump:uiautomator2 的 dumpWindowHierarchy 一次返回所有可见窗口(前台页 + 悬浮桌宠 + 状态栏 + 输入法),实测 96–113 ms / 25.7 KB / 59 节点(桌面 + 桌宠同时在屏)。adb_ui 仍只读前台页,adb_window 把同一份 XML 按 depth 0 切成窗口——全程多花的只有 CPU,不多一次设备往返。
  • adb_watch 的采样上限由整树 dump 决定:请求 10 Hz 实际约 4 Hz(每次约 100 ms dump + 间隔),所以它报的是实测平均间隔而不是标称频率;要再快只能减少树体积,目前没做。
  • 悬浮窗的文字树是真信息:桌宠气泡里的「没听清,按住再说」直接从无障碍树读到,不用 OCR、不用截屏;桌宠尺寸就是 #petRoot FrameLayout 的 bounds(实测 462×594)。
  • adb_recent 命中直播内存帧时 365–443 ms 且不碰设备;没人看直播时要现场录 4 秒(整条约 5 s),换来的是「真的是刚才」而不是几分钟前的旧段
  • adb_motion 两条路径的成本差得很远:磁盘段够新时 380 ms 出结论(不碰设备),要现录则 3.4–4.7 s(其中录屏占 3.4–4.4 s);因此先用「刚才几秒」的磁盘段,只有确实没有新段才现场录,并在文案里写明是现录还是几分钟前的旧段。
  • adb_do 2 步 318 ms 说明多步流程的瓶颈仍是设备侧动作,不是工具往返。

安装

# 一次性:装进当前 profile(对所有会话生效)
# 在 DSH 里用 plugin_manager:action=install_bundle, target=$HOME/dsh-mobile-use

装完 plugin_manager list_plugins 里应出现 include:adb(enabled=true、fiberPhase=active)。

配置(可选,写在 bundle patch 的 config 下):

- id: adb
  name: dsh-mobile-use
  config:
    serial: ""             # 固定设备序列号;留空则取 ANDROID_SERIAL,再退回第一台 online 设备
    adb: /opt/homebrew/bin/adb  # 可选;不写按常见路径探测

卸载:plugin_manager action=set_plugin, target=adb, enabled=false,或移除 bundle。

自测

node selftest.mjs              # 只跑只读工具(安全)
node selftest.mjs --tap        # 额外真点一次,会动设备
node selftest.mjs --serial emulator-5554

已知边界

  • 改了 mirror.js / ocr.js 后要同步改 index.js 顶部的 ?v= 后缀:宿主热重载只重读入口文件,被它 import 的模块仍走模块缓存,不加后缀改了不生效(实测:/state 的 screen 一直是竖屏 2136x3200,加上 ?v= 重载后变 3200x2136)。

  • 中文输入:adb shell input text 不支持非 ASCII,adb_input 会明确报错而不是静默吞字。中文走剪贴板或 App 内的粘贴。

  • 动画页读树慢:uiautomator dump 内部会等界面空闲,相机预览这类持续刷新的页面要 ~2 s;静态页只要 0.33 s。这种页面优先用 adb_app foreground(0.09 s)判断页面,只在真要读控件时 adb_ui。

  • ref 有时效:每次 adb_ui 重新编号,超过 2 分钟或界面变了就失效,会报错提示重新读,不会点错位置。

  • 多设备:默认第一台 online 设备;同时插着平板和模拟器时用 config.serial 或 --serial 明确指定。

  • 同机两个宿主:GUI 插件和长稳脚本各起一个宿主连同一台设备时,设备端清场由持锁的那个宿主负责(锁在 /tmp/dsh-mobile-use-host.lock),两个宿主不会互杀 recorder。但一台设备的硬件编码器只有一路:两边同时推流会互相抢帧,画面每次都要冷启(实测冷回退 1096 ms,单宿主热帧 164 ms / 帧龄 34 ms)。要在同机跑长稳脚本,用 ADBM_STREAM_SWEEP=0 关掉脚本侧的清场,并避免两边同时看画面。

两个容易踩的坑

热重载后侧栏挂不上:宿主热重载会重新执行页面侧模块,但页签登记处是页面级的单例,旧登记还在,新登记会抛 tab type id "adb-mirror" is already registered,页签行建出来了、内容却永远不挂载。现在遇到这个冲突直接整页重建一次(30 s 内最多一次,有弹窗时不动),重建后登记处是干净的,want 还在,页签自动开、自动出画面。插件更新后如果侧栏没反应,按一次 ⌘R 即可——这是目前唯一需要人动手的地方。

右栏归属:右栏是全局唯一可见栏,插件只在「右栏正挂着你发起的那个会话」时才占它;屏幕上是别的会话时改用定向接口只往发起会话自己的布局里建页签,不展开、不切页签、不碰别人正在看的那一栏。

更新日志

1.4.34(侧栏再窄也不裁画面;关窗就断流)

  • 画面按容器缩放:侧栏只有几百像素宽、或设备是平板这类宽高比时,之前会按图片原始像素铺开再被裁成左边一条;现在画框永远钳在容器内、object-fit: contain 留边,整屏都在。
  • 只留一条拉流路:MSE 起不来时先停掉那条连接再切抓帧,不再两条路同时拉;「画面没有响应,正在重新连接」不再卡在空转。
  • 原生视频页同一处几何一起修:#video 铺满舞台、object-fit: contain,竖屏平板比例也完整显示。

1.4.33(卡片说人话:省的是 token,不是清晰度)

市场卡片重写成五件能验证的事,不再是一段参数说明:

  • 看一次屏是 200–600 token 的文本树,不是上千 token 的截图(约省 60–85%),热帧判断 100–200 ms。
  • 右栏实时镜像,圈一处写一句话,带圈画面与圈内控件一起回到对话。
  • 原始 H.264 直进 WebCodecs,不转码;p50 2 ms、丢帧 0,解不了自动退 MSE。
  • 声音一个开关,默认关、按序列号记住;开着才多一条音频 socket,关窗一起回收。
  • 关窗 3 秒内解码器/录屏/设备端 server 全没,闲置通道 90 秒自清,关掉的请求不会自己弹回来。

声音开关的「记住」在这一版才真正生效:刷新后偏好会重新同步给宿主,按钮保持上次状态,出声仍等一次手势。

1.4.32(声音:一个开关,默认关,开了才为它付代价)

  • 能听设备的声音了:播放器多一个「声音」按钮,点开就是把设备的输出声音(audio_source=output,48 kHz 立体声 s16le 裸 PCM)接到浏览器播放。实测 22 秒连续收 1047 个包、每包 4096 字节、包间隔 21.33 ms,与视频通道并行不抢配速。
  • 默认关,且按序列号记住:关着时 scrcpy-server 根本不建音频采集(启动参数里连 audio_codec / audio_source 都不出现),延迟、CPU、内存与 1.4.31 完全一致。这是全局唯一一个音频控件;地址栏 ?audio=1 / ?audio=0 可临时覆盖。
  • 设备给不了就自己退:设备端采集失败(被通话占用、ROM 不支持)时音频流直接结束并把开关复位,按钮置灰——不会留一个点了没反应的开关。
  • 关窗照样回收:音频订阅者计入通道回收判定,关窗后音频连接随视频一起收,设备端不留采集进程。

1.4.31(裸流直通默认开启,画面路径不再过转码)

  • 直通默认走 WebCodecs:宿主把 scrcpy 的原始 H.264 直接推到页面,VideoDecoder 解码上屏,不再经 ffmpeg 转 JPEG。实测宿主写出到拿到帧 p50 2 ms / p90 2–3 ms,26 秒稳态一条连接、解码器只配置一次、丢帧 0。
  • 修掉每 3 秒重连一次的真凶:页面那组「连上了没 META 就重连」的 MSE 看门狗在直通模式下恒成立,把健康连接当卡死掐掉,20 秒内重配解码器 9 次、max 抖到 368 ms。直通分支现在跳过这组判据,cfg 从「跟连接数一起涨」变成恒为 1。
  • 冷启动更稳:静态画面下补要三次关键帧;连不上 10 秒先退回 MSE 给画面,不会一直黑屏。
  • 两处可见性:页面 3 秒诊断上报带 stream.avc(连接数、重配数、解码数、丢帧、队列峰值、错误),/state.avcEnds 留最近 8 次直通连接结束原因。
  • 解不出画面时一律自动退回 MSE,用户不需要改参数;?avc=0 可强制慢路径做对比。

1.4.30(关窗顺手收掉编码器,关过就别自己弹回来)

  • 关窗真的把 scrcpy 通道收掉了:以前只停录屏,通道(设备端一个编码器 + 宿主一条 adb 进程)还留着。现在关窗后 3 秒确认没人回来就 stop 掉,设备端 server 按 scid 一并收,ps 上 com.genymobile.scrcpy.Server 归零。
  • 闲置通道 90 秒自清:没人看、也没人手碰过就收,下次开栏懒启动(约 1 秒)。ADBM_CHANNEL_IDLE_MS 可调。
  • 用户亲手关过的请求不再自动开栏:/want 带 closed 标记,同一请求不会把右栏自己弹回来;下一次明确要求才重开。

1.4.29(延迟口径不再误报)

  • /stream/info 不再用「启动时刻减分片 PTS」算延迟(两个原点不同,读出来动辄 7 秒)。改成 frameAgeMs:最后一帧到达距今多久,持续变大才是真卡住;画面上屏延迟看页面里的 lag_ms。
  • 手册里对应的口径说明同步改掉。

1.4.28(操作手册 + 转发口随设备清理)

  • 新增 docs/agent-guide.md:判定顺序、镜像生命周期、资源不变量、延时口径、排障入口。
  • pruneGoneDevices 一并清掉自己建过、设备已不在的 adb 转发口。

1.4.27(关窗先回话,再收尾)

  • /close 先应答再收尾:收尾里有一条同步 adb(清场/量尺寸),设备忙时能把「关窗」拖到 7 秒。现在先返回 {"closed":…},收尾放到下一拍。
  • 关窗 beacon 直接停流:用户明说不看了,不再留 2.5 秒给重开侧栏;还有观众或镜像仍被要求时照旧不停。

1.4.26(追帧不来回切、缩放收成一个按钮)

  • 追帧加回差:落后 0.45 s 才跳尾,小幅漂移用 1.25× 追,追进 60 ms 放回 1×。以前每帧都可能改倍速,改一次卡一下;现在只在跨过两条线时改。
  • 缩放一个按钮轮流放大:适应 / 2× / 3× 合成一个,标签写「按下会变成什么」,面板少两行。

1.4.25(关窗当场收工)

  • 关页即停:播放页在 pagehide / beforeunload 用 sendBeacon 打一次 /close,宿主只收这一次的那台设备,且只在不剩观众时才收;别的会话还在看的镜像不受影响。以前关窗要等 2.5 秒宽限 + 心跳超时,现在关窗那一刻就开始收。
  • 新增 /close?serial=… 路由,同时把镜像最后观看时间清零、按需停分段录制,并让播放流走「观众走光」的收尾路径。

1.4.24(状态探测不再续命镜像)

  • 探测不再续命:/watching 以前任何一次查询都会把观众的计时顶到现在,于是关掉窗口后只要还有进程在查状态,镜像就永远不算空闲。现在只有带 watch=1 的调用才算「有人真的在看」,纯查询只读不回写。实测:纯探测 3 秒后设备上录屏 0 个、pid 文件 0 个;显式 watch=1 起录后 10 秒无人再要,自己收干净回到 0。
  • 段边界兜底:分段录制每段开头再看一眼有没有观众,没人就不再起新的一段——即使停止调用漏了也不会白录。

1.4.23(关掉镜像窗口就收工)

项之前现在
关掉镜像窗口后的采集链退订只排一个「空闲回收」定时器,宽限沿用视觉 keepalive:开着镜像再关掉,设备和宿主的录屏、转封装、JPEG 桥还要再占最多 10 分钟镜像和视觉两条需求分开算:最后一个观众断开只等 2.5 秒(够扛住侧栏刷新/换页重连),且 15 秒内没真读过帧就把 keepalive 压回短宽限。实测断开后 3 秒 stop(),宿主 ffmpeg 0 个、设备 screenrecord 0 个、pid 标记文件已删;下次打开照常冷启(adb_look 673 ms 出图)
面板按钮输入框旁另有一个「文本」按钮,和回车重复;Tab 键在手机上几乎用不到去掉这两个,保留发送/最近/清除 + 回车提交 + 返回/桌面/回车/删除 + 缩放一档
分段录制的 pid 文件每段一个 /data/local/tmp/dsh-mobile-use-rec-<serial>-<tag>-<n>.pid,只写不删:看 6 分钟攒 32 个,重启后仍留着一次观看复用同一个 pid 文件,段尾连同片段一起删;开录前扫一遍同 serial 的旧文件,pid 已死的直接清(活着的不碰)。实测连续 3 段 pid 文件始终 1 个,关窗 10 秒后 0 个

1.4.22(视觉流不再 175 s 后自己死掉)

项之前现在
只看视觉时的转封装背压没人开镜像时仍起 ffmpeg 转封装,没人读它的 mp4 就背压,进而 pause 掉录屏 stdout(JPEG 支路共用同一条管道)⇒ 断帧 ⇒ 看门狗杀录屏重开,1 分钟 4 次、每次 1 s 空窗没镜像观众就不起转封装(少一个常驻 ffmpeg);万一背压只丢转封装,不掐采集链。静置 4 分钟实测:录屏 + JPEG 解码各 1 个进程、PID 不变、sessions 停在 1
adb_look / adb_ocr 的免截图快路径只看 JPEG、不进镜像观众数:录满 RECORD_LIMIT(175 s)正常退出后没人续录,之后的视觉读又掉回 screencap(实测 619–1096 ms)宽限内有人读过帧就照样续录,冷启一次能热一整个 keepalive(默认 10 min);宽限外照旧释放,不常驻

1.4.21(换设备不再攒缓存)

项之前现在
换设备/重启模拟器树快照、屏尺寸、dump 队列、常驻 shell、转发口都按序列号存,旧设备的那些一直留到进程退出每 5 分钟核对 adb devices,只清「已不在列表、且没有活跃推流」的设备;在线设备不动,adb 返回空表时整轮跳过

1.4.20(双宿主不再互杀 recorder)

项之前现在
同机两个宿主双方「开录前清场」都按 marker 扫设备,会杀掉对方正在用的 recorder,来回重建清场前先读宿主锁:同机已有活的第二宿主就不清设备端,交给持锁那个;对方退出后自己接手(实测交接只收掉遗留的 q6drq0-7,GUI 自己的 recorder 不动)

1.4.5(市场可安装)

项之前现在
市场卡片徽章显示「未声明宿主要求」,点安装没有依据npm 包里声明 engines.dsh >= 0.2.0-rc.1(与 node >= 20),徽章按已发布 manifest 判定
README 开头一上来是 1.2 的故障表,看不出它是什么先说清它做什么——实时镜像、圈选标注、免截图读界面;版本记录移到文末

1.2(实测:画面不再播 6 秒后卡死,单帧 168 ms 上屏)

故障之前现在
播几秒后永久卡住客户端拼包每帧 Array.from + [].concat,1 MB 关键帧下是 O(n²),追不上服务端 2 MB 积压被断开,重连又补同一个 GOP,看起来就是「播 6 秒定格」拼包改成「追加只拷贝一次、解析用游标」,实测连续滑动 4 秒 111 帧上屏、readyState 4、缓冲持续前进
画面全黑、控制台 APPEND_FAILEDsourceopen 里先 addSourceBuffer 再把 INIT 排进队列,排队分片先喂给解复用器先把 INIT 排到队首再挂 sourceBuffer,实测首屏直接可播(3200x2136)
延迟没法归因只有「帧数」计数,分不清是采集慢还是播放器落后stream.info() 新增 lastPts / ptsAgeMs(最近一片的解码时间与年龄);页面 window.__adbm 暴露 meta/init/media/appends/appendErr/buffer 计数,归因一次就看出来
端到端延迟未测边滑动边用 requestVideoFrameCallback 量已上屏帧:最小 152 ms、中位 168 ms、最大 436 ms(含一次重连追赶)

1.1.1(实测:宿主不再被清理路径打崩,右栏只开给发起会话)

故障之前现在
空闲回收 / 子进程回调抛异常回调里调了不存在的方法(killStale)就冒到顶层,DSH 直接退出码 1全部定时器与子进程回调走统一兜底 guardCall,异常只写诊断日志;stop() 幂等,清理方法缺失或对象已销毁时也照样停完不抛;test/lifecycle.test.mjs 固定 8 种形状
右栏开错会话广播式 open + 标题相近就认领,可能开进别人正在看的会话只认 mounted 严格相等的发起会话;拿不到会话 id 直接拒绝打开;空会话不发广播
页面重复执行客户端 bundle 被执行两次 → duplicate factory,整条 web boot 失败客户端入口只注册一次(失败回滚标记可重试);页面版本号与 client.rev 同源,不再来回重载

1.1(实测:动作不再点到旧界面,画面从第一帧就能解)

能力之前现在
点按时效2 分钟内的快照都照点,界面一变就点空超过 1.5 s 先重读一次树核对目标;目标没了、挪动超过 48 px 就报 stale_snapshot,不点旧坐标
多个同名控件静默点第一个(常点到父容器)报 ambiguous_target 并给数量,改用 ref 挑;同一文字多份时按离旧位置最近认领,不误判
超时重试读命令超时会重放;写命令也可能重放一次只有严格只读的白名单会重试(含 2>&1 不算写);input/am/pm/重定向/find -delete/sed -i/logcat -c/wm size WxH/date -s 一律按写算,超时报「设备可能已执行,不重放」
u2 服务固定端口 9008,冲突就残废;jar 判断恒为真adb forward tcp:0 动态拿本机端口并记住归属;jar 按退出码判断、推送失败即报错;冷启动实测 1.1 s
首帧解码观众可能先收到媒体分片、后收到 moov,画面起不来初始化段先到先发,未到就不发解不了的分片;首屏 META→INIT→MEDIA,实测首帧 2.4 s、无重复帧
GOP 缓存只按条数截断,可能把 IDR 截掉、新观众从 GOP 中间起播按字节封顶(4 MiB)且只留「IDR 起头」的连续段,超限整段丢弃等下一张 IDR
长跑内存常驻 shell 缓冲只增不清,每条命令叠在上一条输出后面每条命令读完清缓冲、单条输出封顶 8 MiB;连续 12 次 dumpsys 宿主 RSS 不涨

0.9(实测:侧栏不再「一卡一跳」,面板能自己操作)

能力之前现在
画面来源每 200 ms 抓一张 JPEG(设备侧 screencap 一帧 867 ms)H.264 裸流 → 主机 ffmpeg 抽帧转 JPEG,12 s 采样 22.9 fps,帧间隔 p50 41 ms
首取帧等下一拍抓帧有缓存帧时 2 ms 返回;没缓存时平均等 46 ms(长轮询 ≤2500 ms,不空转)
点按坐标按显示宽度一个比例算,缩放/转屏后偏按下位置归一化到真实媒体矩形再乘设备分辨率,缩放/平移/横竖屏都用同一套
看细节只能看整屏缩略图Ctrl/⌘+滚轮 1–4×、2×/3×/「适应」按钮、2× 以上 Shift 拖动平移,边界自动夹住
键盘只能点截图画布吃键盘:回车/返回/删除/Tab/方向键直达设备
文字ASCII 直送,中文无解/text 走 u2 setClipboard + 长按粘贴,输入框回车即发,失败回填草稿
与对话协同得回头读聊天记录才知道刚点了哪面板每 2 s 读 /actions,对话里刚做的操作显示成一行(-1.2s 点击 @640,1200)

页面自报现场(/diag)现在带构建号:/state.build 与 client.rev 对不上时,面板会自己拉新版本,插件更新后不用再按 ⌘R。

0.8(实测:看的成本降下来、不看就完全停)

能力之前现在
侧栏每帧体积1618×1080 JPEG ≈ 140 KB1024×684 · 21–48 KB(右栏显示宽度只要几百 px,多余像素白解码)
侧栏帧率5 fps,每 120 ms 一拍2.8–3.4 fps,200 ms 一拍、2 张抓帧并发;实测 /state 报 3.4 帧/秒
没人在看侧栏仍在抓帧、仍在推0 次抓帧:没有观看者时抓帧泵直接空转,/state 的 watchers 到 0
切走 / 最小化 / 面板滚出视野照常占 CPU页面侧 IntersectionObserver + visibilitychange 判定,断开直播流,重新被看见再自动接上
盲等重开靠 sleep 后反复试页面不在前台也能用 openTabIn(发起会话, kind) 定向把页签建进该会话自己的布局(实测 tabsIn 回 guide,adb-mirror),回到该会话时 800 ms 一次的挂起请求立刻展开并出画面,不用再叫一次

0.7(实测:看不清字也能读、动效给数字、标注不再偏)

能力之前现在
界面只有自绘/Flutter、文本树空只回一句「没有可读文字」adb_ui 自动补一层本机 Vision OCR(ocr:"force" 可强制):实测 force 全流程 1771 ms(截屏 0.36 s + 3.5 MB 传输 + 识别 1.58 s,21 段),只当兜底、不当默认
截屏取字exec-out screencap -p 3.0–3.1 s / 8.5 MB设备端 screencap -j 落盘再 cat:0.36 s / 3.5 MB(PNG 路径保留作回退)
判断「变大变小不协调」连拍截图靠眼睛adb_anim 给数字:每 150–250 ms 一帧的中心 / 宽×高表,加上超调 px、方向反转次数、平均步长、峰值步长、平滑度、稳定耗时
卡顿/被杀/内存涨截图猜adb_proc:top 最吃 CPU、mem 看单包 PSS 明细、list 列进程、audit 对账宿主解码器与设备端录屏/scrcpy 进程
内嵌 H5 定位不准只能读控件树adb_web:CDP 直读 DOM(list / dom 选择器 / eval),返回 CSS 矩形与换算好的设备坐标,可直接喂 adb_tap point=
侧栏标注位置偏wm size 报竖屏 2136x3200、画面是横屏 1618x1080,标注整体缩到左上角按真实画面横竖对齐后再换算:3200/1618 = 1.978,标注/点按与设备坐标一致

adb_anim 读的是控件树坐标:列表滚动、页面转场这类合成器驱动的动画可能全程报「没变」,那种情况改用侧栏「最近 6 秒」拼图看。OCR 走本机 Vision(macOS),一个 worker 进程、空闲 45 s 自杀;只支持 macOS。

0.6(实测:一个回合跑一串动作、截图 0 ms 复用、精确落点)

能力之前现在
「点开→等加载→输入→发送」4–6 次工具调用、4–6 个模型回合adb_do 一次调用(实测 4 步:home→等「设置」→点→等「WLAN」= 1614 ms / 1 回合)
侧栏在看画面时截图0.5–3.2 s(screencap + 转码)1 ms(直接拿直播里最新一帧,liveFrame)
点完再确认界面2 次调用(tap + adb_ui)1 次:adb_tap 带 wait_for_text / wait_for_id / wait_until_gone,返回命中/超时与当前 Activity
看「点完到底变了什么」整棵树重读adb_ui changed_only:只给 + 新增 / - 消失,没变化时一行「界面没有变化」
系统开关(桌面/返回/最近/锁屏/亮屏/转屏/通知栏/快捷开关/夜间)界面里找按钮,或自己拼 input keyeventadb_action 一条命令(实测 home 126 ms)
点文字落到哪最近可点祖先的中心祖先大得离谱(>6 倍面积)且中心离文字远时点文字自己:MIUI 桌面点「设置」实测从 1600,1068 修到 2283,1986
侧栏路由只靠端口回环 + 同源三重校验(peer / Host / Origin·Sec-Fetch-Site),伪造来源实测 403

0.5(实测:常驻 shell、真人轨迹、动效回看)

能力之前现在
轻点耗时(含工具往返)120–151 ms61 ms(首次 101 ms,建通道成本;之后 61)
adb_sh 每命令开销70–90 ms(新起 adb)2–4 ms(常驻 shell 提交,命令本身另算)
曲线/长按拖动input swipe 只能直线adb_gesture 逐点 DOWN/MOVE/UP(实测 5 控制点 / 16 步 / 请求 600 ms → 1161 ms 返回)
标注回传给模型圈选图 + 圈内控件再加操作时间线(-3.2s 点击「开始」@640,1200)与最近 6 秒 6 帧拼图(265 ms 内建好,112 KB)

常驻 shell:插件为每台设备保一条 adb shell 交互通道,命令串行排队、用随机标记切分输出;超时/断开自动重建并退回一次性 adb shell,不会卡死。退出时统一关闭。

adb_gesture 的段数是 duration/40(3–40 段):设备端每条 input motionevent 有约 35 ms 进程下限,所以 600 ms 的手势实际 1.1 s 左右;要更顺就减点、拉长时间。多指(双指缩放)input motionevent 不支持,需要 u2 gesture 或 root sendevent。

标注回传落点:~/.dsh/adb-mirror/annotations/。拼图取自内存里最近 40 帧(约 8 秒,5 fps),不 seek 录屏文件——录屏是 720×1280 且末段还在写,seek 会空手。

0.4(实测,小米平板 8,已 root)

  • 直播 4.5–5.0 帧/秒:连续看 20 s 收到 121 帧(5.0 帧/秒),/state 报的实测帧率 4.3–4.9。做法:3 张 screencap -p 并发轮流补位,每张一出就交给一次 ffmpeg png_pipe 转 JPEG,按 200 ms 固定节拍把最新帧写给侧栏。
  • 没人看时零开销:关掉侧栏后实测 frames 停在 159 不再增长,设备端 screencap 进程消失;设备上的 10 s 分段录像照旧走,本机只留最近 3 分钟。
  • 本机开销:转码约 16 ms CPU/帧(≈8% 单核),每帧约 54 KB、本机 240 KB/s,全在回环地址上。
试过实测结论
一张一张抓单张 0.65 s → 1.4 帧/秒不够
3 张并发抓3–4 路并发 0.61–0.68 s → 4.3–4.9 帧/秒采纳
常驻 ffmpeg image2pipe 吃 PNG喂 1 张后 3 s 不出字节;-flush_packets / -analyzeduration 0 也无效,只在 stdin 关闭时一次性吐出不能用于直播,改每帧起一次 png_pipe
有帧才推并发抓帧成簇完成,画面被削到 1.2–1.7 帧/秒改为固定 200 ms 节拍重发最新帧
抓帧时的设备侧占用screencap -p 峰值约 1 核只在有人看时抓

0.3(实测,小米平板 8,已 root)

  • 读界面提速 15 倍:设备端常驻 uiautomator2(openatx,Apache-2.0)走 app_process,adb_ui 从 2343 ms 降到 136–153 ms,同样返回文本树与 ref。首次使用自动 push vendor/u2.jar + 装 vendor/app-uiautomator.apk 并拉起服务,之后复用;进程死了下次调用自愈。
  • 实时ADB 侧栏:直播 2.8–3.4 帧/秒(/state 实测 3.4,单帧 21–48 KB),画面上能直接点、能圈一块把「这里 + 设备坐标 + 前 12 秒操作时间线」连同截图推回当前会话(实测注入成功,返回 {"ok": true});本机留最近 3 分钟分段(10 s 一段 × 18 段,实测 17 段 212 KB)。全部在本机,不经过外部服务。

镜像的实测结论(都踩过)

事实实测结论
screenrecord --output-format=h264 - 静止画面 8 s8.7 KB、只出 1 帧直播不能只靠录像
同一路 h264 加 -vf fps=4ffmpeg 直接 -22、0 字节单帧被 fps 滤镜丢掉,删掉滤镜
改为 screencap -p 一帧0.7–1.2 s直播改走截图续帧,稳
screencap -p 的字节头PNG 签名(不是 JPEG SOI)先找 89 50 4e 47 再交 ffmpeg png_pipe
设备端分段录制 10 s → cat 拉回单段 8–16 KB、可 ffprobe 出时长环形缓冲走分段文件,不走管道

0.2(实测数据,小米平板 8,已 root)

新增能力:

  • adb_state:一次往返拿前台 Activity、焦点窗口、窗口栈、键盘、方向、分辨率、亮屏、电量、root。实测 262–376ms(比截图 + 读图快,且弹窗/键盘判断更准)。
  • adb_sh root=true:以 su -c 执行;实测可读 /data/data/com.example.app/shared_prefs(非 root 对照为 Permission denied)。
  • adb_tap 自动落最近可点祖先 + dry_run 预演落点(先确认再点,避免点错返工)。
  • adb_device 增加设备画像(ro.build.characteristics、sdk、root)。

测量记录(同一设备,逐条实测)

动作耗时备注
adb_state(7 段 dumpsys 合并一次 shell)262–376ms含 5 次 dumpsys + wm size
dumpsys window(设备侧)0.03–0.05s含 mCurrentFocus / mFocusedApp + 18 个窗口
dumpsys activity activities | grep mResumedActivity时有时无MIUI 上不可靠,已改用 window 的 mFocusedApp
uiautomator dump(静态页 / 动画页)0.33s / 2.2s动画页仍是最慢的一环
screencap -p PNG0.49–0.58s(90KB)相机预览页曾达 3.2s(8.9MB)
原始 RGBA screencap(想省 PNG 编码)2.05–2.38s(27MB)比 PNG 慢,已放弃
关掉动画缩放后 dump2.05s → 1.64s只省约 20%,不是银弹

踩过的坑

  • 合并 shell 命令里 echo ##A 会被 sh 当注释,整条命令静默不执行 → 标记改成 @A@。
  • 前台 Activity 不能用 dumpsys activity activities 抓(MIUI 缺行),统一走 dumpsys window 的 mFocusedApp;焦点窗口 ≠ 前台 Activity 时判定为有弹窗/浮层。

路线图(未实现,按收益排序)

  1. scrcpy(~120k★)视频流:连续 H.264 + 精确输入,单帧约几十毫秒,适合扫码/相机预览这种截图极慢的页面。
  2. WebView CDP:拿到 DOM 文本与 JS 状态,替代 WebView 内稀疏的文本树。
  3. 手表/眼镜:靠 ro.build.characteristics=watch 等做设备画像;圆屏按内切矩形裁剪点击坐标;走 adb pair/adb connect 的无线 ADB;GL 自绘界面文本树为空时回退截图。均【未核实】。
  4. root 直读:shared_prefs/files 已可读;数据库需 push 一个静态 sqlite3 二进制(当前系统无 sqlite3)。

许可

代码 MIT。第三方组件见 THIRD_PARTY_NOTICES.md。

gone
page-switched
no-response
same-screen
delta
shot.path
wait_for_xpath
wait_xpath_gone
shot: true
adb_shot
tree: true
adb_ui
adb_inputtext(ASCII,空格自动转义)、key(ENTER/BACK/DEL…)、submit(enter / search,输完直接提交)、ime(auto / clipboard / adb,ADBKeyboard 已装且是当前输入法时中文走广播更快)、swipe、clear;回执给 method(ime/paste/input)、field(输入框回读)、verified,verify: true 时 ASCII 直发也回读一次,不用再补 adb_ui
adb_gesture真人轨迹:points 折线逐点 DOWN/MOVE/UP,duration_ms、hold_ms;曲线拖拽、按住再拖;滑完可等文字或 wait_for_xpath / wait_xpath_gone
adb_applist(42 个可启动应用 + 前台,找包名第一步)、info(versionCode/versionName + 前台)、install(-r -d)、start、stop、clear、uninstall、foreground
adb_sh设备端任意命令,输出截断到 20k 字符;日志、dumpsys
adb_shot只在要看颜色/布局/相机画面时截图,默认缩到长边 900 px,返回路径给 read_image;region="x,y,w,h" 只回一块(看桌宠、小图标时体积降一个量级);带 ref 只截那个控件(实测桌宠页一个图标 126×126 / 1.6 KB,整屏 600×900 / 39 KB)
adb_look不看图也能看清画面:把屏幕压成颜色网格(每格一个字母)、列出同色块的位置与占比、给出与上一次的差异;region 只看一块、cols/rows 调网格密度。canvas/游戏/自绘界面、文本树没有文字时用它——比 adb_shot 快、不花图片 token
adb_ocr直接读屏上的文字,不花图片 token:给 ref 或 region 只读那一块,回一批带坐标的文字,坐标可直接给 adb_tap point=。优先认右栏直播帧(热 110 ms),文本树能读时优先用 adb_ui
adb_device列设备、状态、型号、当前选中设备与分辨率
adb_state一次往返:前台 Activity、焦点窗口、窗口栈、键盘、方向、分辨率、亮屏、电量、root(125–195 ms:七条 dumpsys 并发跑,串行要 371 ms)
adb_do一串动作一次跑完(最多 20 步):点 / 滑 / 输入 / 按键 / 系统动作 / 等文字,任何一步失败就停并报第几步;每步可 retry 重来注入前的偶发失败;失败时自动留一张截图到 ~/.dsh/adb-evidence/<序列号>/(只留最近 20 张);步骤也能带 until(等同一控件进入某状态)与 dismiss(本步等待时自动点掉挡路弹窗);步骤也能用 xpath 一次定位点掉,tap/id 步与等待/核对步都可配 within_ref(或坐标框 within_rect)只在一行里找、只在一行里等「已关注」;找目标也能用 assert_activity/assert_activity_gone(核对页面)/desc/cls/exact/regex/index/long_ms(长按时长)(同一文字匹配到多个时点第几个,从 0 开始)(和 adb_tap 一致,只有描述的图标按钮、半截类名的控件都能点);输入步可写 clear: true 先清空聚焦输入框;某步写 on_fail: "continue" 就允许它失败(记一笔跳过,后面照跑);同一步要连做几次写 repeat(1–20,配点击/滑动/按键/系统动作/scroll_to,连点「下一集」不用抄十遍);整串跑完可加 shot: true 顺手留一张截图、tree: true 顺手把跑完的界面读回来(ref 归新快照);scroll_to 还能写成对象(text/id/desc/cls/xpath + direction/until/dismiss/max_swipes),滑到「真的能点」的那个再动手;每步还能 wait_for_xpath / wait_xpath_gone / assert_xpath / assert_xpath_gone / assert_count_min(配 count_xpath)当条件,收尾 assert_no_crash 读 crash 缓冲区跟开始时比,多了就当场报并留证
adb_action系统动作一条命令:home / back / recents / lock / wake / rotate / notifications / quick_settings / night_mode;可带 wait_for_text / wait_until_gone,动作和确认一次调用做完;等待支持 wait_for_xpath / wait_xpath_gone
adb_file设备 ↔ 宿主文件:action 给 ls / pull / push,只放开 Download/Pictures/DCIM/Documents/Movies/Music/Android\ media 与 /data/local/tmp;pull 默认落 ~/.dsh/adb-files/<设备>/,两次都比对 md5,回执写字节数与是否一致
adb_pinch双指缩放:mode 给 in / out,percent 给幅度、steps 给步数;走设备端 u2 的 pinchIn / pinchOut,可带 wait_for_text / wait_for_xpath 等一次等到位
adb_record录一段屏幕并取回宿主:seconds 给 2–30 秒(默认 5),阻塞到录完,返回 mp4 绝对路径与字节数,设备上的临时文件自动删;只观察不注入
adb_clipboardaction=read 取剪贴板原文(复制不上屏的内容也拿得到),action=write 写入 text 并自动回读确认;长文本走粘帖比逐字输入快几十倍
adb_crash最近的崩溃与 ANR:FATAL EXCEPTION 摘要、进程名、首段堆栈,外加 dropbox / /data/anr 现场(有 root 时);用户只说「闪退了」时先查它
adb_recent「刚才那几秒」的 6 帧拼图:动效比例/位移/卡顿这类单帧看不出的问题用它。优先用直播内存帧,没有就现场录一小段(约 +4.5 s),都不行才回落到磁盘段并注明「不是刚刚」
adb_find按选择器一次拿全部命中:text/id/desc/cls/pkg AND、exact/regex/text_matches、clickable/enabled/visible/checked/selected/scrollable/focused/editable、index、within_ref(按 ref 框裁,xpath 也认)、同处去重;也能直接喂 Appium 写法 xpath(//*[@text="登录"]、//LinearLayout/node[2]、//*[contains(@text,"登")]、//*[@clickable="true"][1]、[last()]、not(@attr)、@attr!="值"、starts-with(@attr,"值")、A and B / A or B、反向轴 .. / following-sibling:: / preceding-sibling::;@text/@desc 同样自动去掉零宽字符),在已 dump 的节点上本地求值,实测 94 节点 19–266 µs。没找到自动留截图
adb_scroll_to滚到目标出现:给 text/id/desc 一路滑到看见为止,回执带滑动次数、命中节点和是否到底;until 让灰着的同名项继续滑,dismiss 自动点掉挡路弹窗(最多 2 次);不用模型自己算滑动次数
adb_anim动画/过渡诊断:开 animation_scale 相关的 debug 开关看窗口动画、过渡、Animator 时长,定位「它到底在动什么」
adb_proc进程/内存:top / mem / list 一次 shell 拿回,判卡顿、被杀、内存涨,不用截图猜;audit 对账宿主子进程与设备端录屏/scrcpy(查残留、查谁在占编码器)
adb_events系统事件:logcat 里按 tag/pid 抓崩溃、ANR、Activity 切换,回执按时间倒序
adb_web内嵌 H5:CDP 直读 DOM,返回 CSS 矩形和换算后的设备坐标,可直接喂 adb_tap point=;App 没开 WebView 调试时明确报错
adb_window按窗口看界面:一次 dump 列出所有可见窗口(前台页、悬浮窗/桌宠、状态栏、输入法),给包名、尺寸、位置和窗口内控件树。adb_ui 只看前台页文字,悬浮窗/桌宠这类独立窗口用它;实测 236 ms(含前台 Activity 查询)
adb_watch采样一个控件的几何随时间变化:id/text/class 选靶,给出宽高与位置序列、最大单步、抖动次数、多久稳住,用来量化「刚才那个东西大小/位置变化不协调」。动画在 WebView 画布内部时几何不变,会如实说明并指向 adb_motion
adb_motion量化「刚才那几秒」的动效:传 region="x,y,w,h" 或 target(文字 / 资源 id 子串,自动取控件框),逐像素比对给每帧变了多大、变在哪、抖了几下、多久稳住。圈定区域时用「外缘半径」衡量变大变小(桌宠大小动画就量这个),全屏时只认最大连通块并说明判不准;变化帧少于 4 帧或幅度太小时拒绝下抖动/回弹结论
adb_mirror侧栏「实时ADB」:低帧率直播 + 手点 + 圈选推回会话;status / peek / recent / stop