万象-微信文件与视频号取件

SKILL研究检索
研究检索 未标注权限 许可证不明确
安装这个技能

从本机微信取出别人转来的文件、图片与笔记,做摘要与脱敏扫描后停下等确认。

一句话选型结论

按资料字段整理

万象-微信文件与视频号取件是研究检索类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类研究检索 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_de2353f3/omni-wechat-fetch
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

研究检索
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_de2353f3仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791671929
正文体量62.7 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
查资料并整理出处

让模型按主题查资料,并把引用来源整理成清单。

网页与文献要点提炼

把长文、论文、网页压成能直接看的要点。

竞品与行业汇总

按关键词汇总竞品动态与行业信息。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在研究检索场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
万象-微信文件与视频号取件当前 未标注权限 未标注 未标注 未标注 有
寻找技能 浏览器控制 GitHub 仓库 3120.0 万 Codex、Claude、Cursor 有
自我改进 Agent 接触敏感数据 ClawHub 市场 1646.4 万 OpenClaw 有
灵魂追踪 联网访问 GitHub 仓库 758.9 万 Codex、Claude、Cursor 有
自我完善 联网访问 ClawHub 市场 682.9 万 OpenClaw 有
微软代工厂 调用外部服务 GitHub 仓库 661.4 万 Codex、Claude、Cursor 有

SKILL.md 全文

62.7 KB
模型实际读到的说明书原文,来自技能仓库

万象-微信文件与视频号取件

一句话流程:
> 读 ini 找数据根 → 按 mtime 时间窗定位 → 只读复制到项目目录 → 零依赖解析成文本 → 摘要 + 脱敏扫描 → 输出确认卡 → 停,等用户拍板

微信不会把内容交给 Agent,必须自己到本地数据目录里捞。


0. 四条铁律(违反即失败)

铁律 原因
源目录只读 微信数据目录是运行时缓存,删改会导致微信异常。只 copy2 出来,绝不 move/rename/delete
不编造内容 抽不到就写「未提取到」+ 给出替代路径。绝不能凭文件名猜内容
总结后必停 输出确认卡即结束本轮,等用户明确确认才做下一步
★ 先对齐标准再动手 用户给了参考文件时,先读完再动手,不许边试边摸索;动手前显式确认一件事:要「封面层」还是「内容层」(决定 30 秒还是 10 分钟)。做完被退回 = 标准没对齐,属可避免的失败

0.1 资源纪律(2026-09-20 立为长期标准)

> 缘起:用户批评「已经给了参考还是能出问题,这种来回折腾的方式不是我想要的……把方法写入自有技能,避免浪费资源浪费时间」。

  1. 先定层级再动手:只要封面层,30 秒交,别启动 E 路线;确认要内容层,才启动播放→扫内存→下载→解密→转写全链。
  2. 一次给足预算,同时设止损线:单卡全链 ≈ 5–10 分钟。15 分钟没出本体 → 停,转 A 路线并如实告知(请用户手机复制链接)。不许无限重试。
  3. 不重试已证伪的路:裸 URL(400)/ _b.dat(全加密)/ 磁盘找视频(零写入)—— 三条已证伪,每次跳过,不要在同一个坑里反复摔。
  4. 方法当场沉淀:本次新踩的坑与判据,当轮就写回本技能(含 references/视频号卡片提取速查卡.md),不许留在临时脚本里 —— 换窗口即归零。
  5. 交付分两层标注:封面层(作者/标题)与内容层(转写/读帧)必须分开写;拿不到内容写「未提取到」+ 替代路径。

1. 先问清楚三件事(能省一半时间)

问 为什么
文件、图片、还是笔记? 「笔记」=聊天里的卡片(标题+缩略图+"笔记"角标),正文在加密消息库,只有图片能取出;「文件」是真文件,可直接读
大概几点发的? 用 mtime 精确定位,比按名字猜快得多
发到哪个会话? 文件传输助手 / 某个群 / 某个好友 —— 决定 msg\attach\<hash> 里哪个 hash 目录

先让用户发一张聊天界面截图,看清卡片样式与时间戳,最省事。


2. 数据根定位(90% 的失败在这一步)

微信允许把数据目录挪到任意盘,所以不要只看 C 盘 Documents。

2.1 常见位置(参考,不作依据)

C:\Users\<用户>\Documents\WeChat Files\      # 3.x 默认
C:\Users\<用户>\Documents\xwechat_files\     # 4.x 默认
<任意盘>:\WeChat Files\  /  <任意盘>:\xwechat_files\   # 用户自定义(很常见!)

2.2 ★ 权威做法:读 ini,不猜盘符

# 4.x:C:\Users\<用户>\AppData\Roaming\Tencent\xwechat\config\<32位hex>.ini
#      整个文件内容就是一行盘符/路径(例:E:\)
# 3.x:C:\Users\<用户>\AppData\Roaming\Tencent\WeChat\All Users\config\<8位hex>.ini
#      内容为路径(例:E:\微信及企业微信)

本机实测(2026-09-18):
- 4.x 根 = E:\
- 3.x 根 = E:\微信及企业微信
- ⚠️ 同一个微信会同时存在 3.x 与 4.x 两套目录,都要扫

实现要点(locate.py 已实现):
- ini 文件名是 <32位/8位hex>.ini,用 glob 按 config\*.ini 枚举,不要枚举用户名;
- 读出来的内容可能带 BOM/杂字节,先 utf-8 再 gb18030 双重解码兜底,取第一行 strip 后即路径;
- 正则只认 [A-Za-z]:\\ 开头的盘符路径,其余内容一律不信;
- 都会把数据根写进 All Users / config 下的 ini,直接读它,别靠猜;找不到或解析失败时,把候选盘符列出来问用户,绝不默认 C 盘。

2.3 验证

print([d for d in os.listdir(root)])   # 期望看到 WeChat Files / xwechat_files

3. 目录结构:什么内容落在哪

3.1 真·文件(可直接读)

<根>\WeChat Files\<wxid>\FileStorage\File\YYYY-MM\           # 3.x
<根>\xwechat_files\<wxid>_<hex>\msg\file\YYYY-MM\            # 4.x
<根>\WeChat Files\<wxid>\FileStorage\Fav\                    # 3.x 收藏
  • 同名文件冲突会自动加 (1) (2) → 判"最新一版"要看 mtime,不看序号
  • 同一文件常被多次复制(手机端 + 电脑端各存一份),需按 MD5 去重

3.2 ★ 聊天图片 / 附件

<根>\xwechat_files\<账号>\msg\attach\<32位hex>\YYYY-MM\Img\
                                              ...\Rec\       # 语音
<根>\xwechat_files\<账号>\cache\YYYY-MM\Message\<hash>\Bubble\  # 气泡(加密 .dat)
                                                   ...\Thumb\   # ★ 卡片/图片封面缩略图(真 jpg)
  • <32位hex> 是会话指纹(每个联系人/群一个),同一会话每次收图都进同一个 hash 目录

3.2.1 ★★★ 会话反解:<hash> 就是 md5(会话 username)

实测(2026-09-19,已用 md5 字典对 12 个 hash 验证):

md5("filehelper") = 9e20f478899dc29eb19741386f9343c8   # ← 文件传输助手

⇒ 不要再靠"时间+内容像不像"猜某个 hash 属于哪个会话。
拿到对方 wxid / 群 id 就能直接算出 hash 并精准定位;
特别地「文件传输助手」的 username 恒为 filehelper,可与用户口述的会话名一一对上。

3.2.2 卡片封面怎么取(视频号 / 图文卡片)

文件 位置 内容
NNN_<epoch>_thumb.jpg Message\<hash>\Thumb\ 卡片封面,真 JPEG,竖版多为 540×720
NNN_<epoch>_b.dat Message\<hash>\Bubble\ 气泡渲染数据,加密,同名配对
  • 配对判据:同名 _thumb.jpg 与 _b.dat 同时存在 ⇒ 是卡片;只有 thumb ⇒ 是普通图片。
  • 封面上的标题可以读全(见 scripts/ocr_cards.ps1);
    视频本体、链接、作者、发布时间一律读不到(微信不落视频号视频本体,元数据在加密库)。
  • 一张典型卡片能拿到的信息量:主题 + 封面上的卖点/数据,
    足够判断"要不要点开看",但回答不了"视频里说了什么"。对用户必须这么讲清楚。

3.2.3 要"博主讲了什么"怎么办(2026-09-19,四条路线)

封面只是入口,用户真正要的是内容。按代价从低到高:

路线 做法 代价 拿到什么
C 同源还原 封面 OCR 出标题 → 公网检索博主原文(很多卡片标题=公众号/开源项目标题) 零(无需用户操作) 博主的原话/方法/数据,但是同源文字,不是视频转写
D 屏幕通道 omni-digital-world/scripts/screen_record_av.py 录屏(画面+系统声),或 screen_capture.py 只留变化帧 用户点播放 + 别切窗口 画面 + 声音。2026-09-19 订正:原写「本机无音频采集设备、只有画面」已过时——dshow 枚举不到设备,但 WASAPI loopback 走渲染端点绕得开,已实测打通(peak=0.2000 / 72.4% 有声样本)。⚠️ 抓的是默认渲染端点,用户切到别的声卡就录不到
A 链接直解 用户在手机上从分享面板「复制链接」,再用 channels_fetch.py 下载 用户复制一次 视频本体 → 可转写 + 读帧(最完整)
~~B 缓存捞取~~ ~~电脑微信播完 → 从 msg\video\ 捞~~ — ❌ 已证伪:播放期间该目录与 cache 零写入,见坑清单
~~F 网页版 filehelper~~ ~~用网页版 filehelper.weixin.qq.com(手机扫码登录)直读卡片~~ — ❌ 已证伪(2026-09-21,代码级):其 _appMsgProcess 只处理 appmsg type 5(链接)/6(文件),APPMSGTYPE_ 常量表根本没有 51(表=0/1/2/3/4/5/6/7/8/9/10/13/15/16/17/2001/100001),而视频号卡片是 <type>51</type> ⇒ 必落 default → 只渲染「无法显示此消息,你目前使用的微信版本暂时不支持此类型的信息。」;且全包 cdnthumburl/thumburl/appmsg.sourcedisplayname 命中 0 ⇒ 连标题和封面都拿不到。实现包=res.wx.qq.com/t/wx_fed/base/webwx-transfer/<ver>/main.*.js(入口 49 B 是 loader,必须浏览器里 reload 录包才拿得到真包)

A 路线的重要前提:PC 端视频号播放器没有「复制链接」入口(用户 2026-09-19 实测并截图)。
链接只能从手机端拿 —— 别让用户在电脑上找,那是白费工夫。

纪律:
- 四条路线拿到的信息必须分层标注(封面 / 同源二手 / 屏幕读图 / 视频转写),不能混起来当"读全了"。
- C 路线找到的内容可能只是"同题不同文",要在产出里写明出处与置信度,并提示可核对原始仓库。
- 拿不到视频时绝不脑补内容——写"未提取到"再给替代路径。

3.2.4 ★★★ E 路线:进程内存直取(唯一能拿到视频本体的磁盘路线,2026-09-20 实战定型)

> 定位:A 路线(手机复制链接)最完整但需用户操作;E 路线不需要用户碰手机 —— 在电脑端播放卡片后,从 Weixin.exe 内存里捞出带完整鉴权的下载 URL,直接下载视频本体,再解密 + 转写。这是目前唯一"全自动拿视频内容"的路。

前提认知(先看这三条,否则必走弯路)

  1. 微信播视频号时视频不落盘(msg\video\ 零写入)—— 别去磁盘找视频文件。
  2. _b.dat 气泡数据全加密(实测头 07 08 56 32 08 07 00 04,可见中文 0 条)—— 不要试图从中提取标题/作者,纯浪费时间。
  3. 裸 encfilekey 下载 = HTTP 400 —— feed 里的裸 URL 缺鉴权参数。必须凑齐 token + svrbypass + sign + ftype=666 才是完整 URL。

完整流程(五步,缺一不可)

① 置前微信 → ② 点播放 → ③ 高频扫内存抓完整 URL(+**邻近数字串=候选 key**)
           → ④ 下载 → ⑤ 解密(**ENCLEN = 明文 free box 起点**,由 `wxchannels_unpack.py` 自动定)
           → ⑥ 抽帧验归属 → ⑦ 转写 → ⑧ **关播放器**(缺 ⑧ 必污染)

① 置前(否则点击落空):WorkBuddy 窗口会抢焦点,d.activate() 会抛错。用四步法强制置前:

user32.ShowWindow(hwnd, 9)                                   # SW_RESTORE
user32.SetWindowPos(hwnd, -1, 0,0,0,0, 0x0001|0x0002)        # TOPMOST
user32.SetWindowPos(hwnd, -2, 0,0,0,0, 0x0001|0x0002)        # NOTOPMOST
user32.AttachThreadInput(t_fg, t_me, True)
user32.SetForegroundWindow(hwnd)
user32.AttachThreadInput(t_fg, t_me, False)
# 验证 user32.GetForegroundWindow() == hwnd

> wxd.pick_main() 返回 dict({hwnd,cls,title,rect,vis}),用 m["hwnd"],别用 m[0]。

② 点播放:直接 SetCursorPos(r.left+rx, r.top+ry) + mouse_event(0x0002/0x0004)。
> 别用 d.mouse_tap()(本机抛 TypeError: not all arguments converted)。

③ 高频扫内存(核心):遍历所有 Weixin.exe 进程的可读区域(State==0x1000 且 Protect in (0x04,0x20,0x40,0x80,0x02)),用正则抓:

URLP = re.compile(rb'https://finder\.video\.qq\.com/251/20302/stodownload\?encfilekey=[A-Za-z0-9]{40,200}[^\s"\'<>\\]{0,2000}')
  • 按 0.3s 间隔连拍 6–8 次(本卡 URL 可能在某一瞬出现)。
  • 判据是「带 token+svrbypass+ftype=666」,不是「encfilekey 存在」 —— 后者全是噪声。

④ 下载:Range: bytes=0-1023 先探,Content-Range 给出真实总长。UA 必须带微信特征串。
> 尺寸是归属的第一道筛:卡片封面才几十 KB(如 40–80 KB),若探到 >100 MB,基本是推荐流污染,不是本卡 —— 直接换候选,别下。

⑤ 解密:decode.js <输入> <key> <输出> [加密字节数]
- 🔴 ENCLEN ≠ 全文件长度(2026-09-21 订正,旧判据是错的):加密段只覆盖头部 ftyp+moov,free+mdat 本来就是明文。传全长度会把明文 mdat 用 XOR 破坏掉。
- 正解:ENCLEN = 密文中 size==8 的明文 free box 起点偏移(实测 t0=209772 / t1=196243)。
- 定位法:在密文里搜 b"free",其前 4 字节若为 00 00 00 08 ⇒ 该 box 起点即 ENCLEN。
- 验证:解出后 box 链须为 ftyp → moov → free(8) → mdat,且 mdat 长度恰好抵到文件尾。
- 🔴 密钥 = 目标 URL 邻近的数字串(2026-09-21 新判据):不必靠 key 池试解 —— 在内存里以目标 encfilekey 的 URL 为锚,取其前后 ±4000 字节内的 8–12 位数字串,按与 URL 的字节距离升序排候选,第一个命中率最高(实测 272905582,dist=59 字节)。
- 🔴 参数顺序是 <输入> <密钥> <输出>(我曾写成 <输入> <输出> <密钥> → 全部 RuntimeError: Aborted())。
- ftyp 检测通过(解密后 buf[4:8] == 'ftyp')只是最低门槛,不等于产物完整 —— 必须接着做下面的自洽性核对。

★★★ 产物完整性验收(2026-09-21 定型,两步都要做)

> 背景:137 的 t1 曾一度误判为「已解出」(box 链完全正确、能抽帧、能转写开头),但实际只覆盖前 11.26 秒。事后查明真正的判据,避免再次把半成品当成品。

第一步 · ffmpeg 实测解码时长 vs 容器 Duration(唯一可信的"能播多长"判据)

ffmpeg -i <解密件> -f null -      # 看末尾的 time= 与头部的 Duration 是否对齐
  • ✅ 完好件:Duration=00:08:26.85 → 解出 frame=15184 time=00:08:26.83(对齐)
  • ❌ 半成品:Duration=00:04:13.20 → 只解出 frame=336 time=00:00:11.26(差 22 倍)
  • ⚠️ 不要用「mdat 内 NAL 走链计数」当判据:实测已完整解码的 card124 与 126 件也只走 1 个 NAL 就断(hvc1/avc1 的 mdat 不是纯长度前缀流),该判据对完好件同样"不过",无区分度。

第二步 · moov 自洽性核对(判 mdat 是"真载荷"还是"按需窗口")

读 stsz 表(注意:stsz 的 sample_count 在 box 偏移 +16,样本表从 +20 起,容易错位 4 字节):

样本字节合计  vs  (mdat box size - 8)
  • ✅ 完好件(card124):42,746,952 vs 47,020,925 → 确实偏小 ~9%(存在 chunk 空洞,这是正常的)
  • ⚠️ 但比例须落在合理区间:若偏小超过 ~90%(如 137 的 t1:32,208,939 vs 33,903,187 → 偏小 5.00%,看似"更吻合"),反而是危险信号
  • 🔴 决定性证据是「按 stsz 把样本拼出来时长多少」:137 t1 的 stsz count=7596 ≈ 正好 11.3 秒(7596/672 ≈ 11.3s,与实测可播 336 帧 ≈ 11.2s 吻合),而 mvhd 声明 4:13 ⇒ moov 的样本表本身就是按"约 11.3 秒"写的。

⇒ 结论性判据:若 mvhd 声明的 duration 远大于 stsz 样本能拼出的时长,则该文件是「按需窗口流」(只有播放缓冲窗口内的那段有效),不是完整本体。此类候选只能给"画面层",给不了"内容层",立刻止损换路线,别在它上面继续试 key / 试对齐。

路线优先级(2026-09-21 依据实测重排)

优先级 路线 判据
1 D 屏幕通道(录屏 + WASAPI loopback) 在"产物完整性"无法保证时,录屏是唯一能拿到完整内容的路(画面+声音都在渲染端,不受分片布局影响)
2 E 进程内存直取 仅在产物通过上面两步验收时才算成功;否则只取画面层
3 A 手机复制链接 最完整,但需用户操作(PC 播放器无「复制链接」入口,别让用户在电脑上找)
4 C 同源还原 零成本,但拿到的是同源二手文字,须标注出处与置信度

> 已证伪勿再试:三假设(mdat 另起密钥流 / 丢弃 N 字节 / 含 free 头)全部测过,全部失败(起始码 0、解码 0 帧)⇒ 不要再在「mdat 段另起密钥流」方向花时间。视频号不落盘;消息库与 Bubble/*_b.dat 全加密;decode_key 不在静态 feed 载荷里。

⑥ 抽帧验归属(不可跳过):解密后抽 t=0.2/0.8/1.4 帧,Agent 亲眼看画面与封面比对。
> 「竖屏=本卡」是错的:续播推荐流里也有竖屏。归属只能抽帧看内容。

⑦ 转写:faster-whisper,见 §3.2.5。

关键坑(每条都踩过)

坑 现象 解法
★ ENCLEN 传「全文件长度」(旧判据是错的,2026-09-21 已订正) 明文 mdat 被 XOR 破坏,抽帧大量失败 ENCLEN = 密文中 size==8 的明文 free box 起点(搜 b"free" 且前 4 字节 00 00 00 08)
★ 用 NAL 走链计数判完整性 完好件也只走 1 个 NAL 就断 ⇒ 判据无区分度 改用 ffmpeg 实测解码时长 vs Duration
★ box 链正确就认为解好了 137 t1 box 链完美、能抽帧,实际只覆盖 11.26s 补做 moov 自洽性核对(见上节);再看 mvhd duration vs stsz 样本可拼时长
★ 在「按需窗口流」上死磕 t0/t1 试 6 种密钥流对齐方案全失败 判据一现即止损,换 D 录屏路线
decode.js 参数顺序错 RuntimeError: Aborted() <输入> <key> <输出>
裸 URL 直接下 HTTP 400 Bad Request 必须带 token+svrbypass+sign+ftype=666
URL 尾部粘内存噪声 ...X-snsvideoflag=xWT126_isDecrypt:true}_feedId:... 截断到 X-snsvideoflag= 值末尾再请求
续播污染 单次扫描 59–86 个 feed,无一本卡 播放后立刻扫;尺寸 + 抽帧双筛
decode_key 与视频不同区 配对 264 组,目标 encfilekey 配对 0 组 decode_key 只挂图片类前缀(KGDRibp2wkic…/2fG3V4WwQP…/rjD5jyTuFrIp…);视频是 rgjNqbibdAo…/6xykWLEnztLc…,从不相邻
密文熵判断 熵 7.99–8.00、无 ftyp/moov/mdat 确认全加密,只能靠正确 key 解
下载物截断 moov 声明 54s 但只 49 帧可解 该资产是截断的 H5 预览碎片;remux 能过、decode 报 Invalid NAL unit size
★ 用「竖版」当归属筛子 我按竖版排除,把真正的本体(横版 1280×720)误判成污染 「竖版=本卡」和「横版=不是本卡」都不成立。本卡可能是横版(如 card137)。筛尺寸可以,筛朝向不行 —— 归属只能抽帧看画面(见⑥)
★ 卡只有片头就以为拿错了 card137 解出 35.01s,抽帧是「两个 SKILL 提升你的 AI 审美」片头,转写仅 1 句 这是 E 路线拿到的本体就是「无音轨 / 截断的 H5 预览片段」 —— 画面是真的、时长是真的,但内容不完整。判据:ffmpeg -i 看流信息,若 Audio 流存在但抽出的音频远短于视频时长(实测 35.01s 视频只抽出 2.11s 音频),即 mdat 截断 ⇒ 该候选只能给画面层,给不了内容层,别在它上面继续花时间
★ 已解出 ≠ 是本卡 164 个 key × 19 个候选试解,5 个命中(56.24s / 10.87s / 176.53s / 35.01s / 12.47s),其中 4 个是推荐流污染 试解命中只是第一关,必须过「抽帧看画面」才认。命中率高≠成功率高,反而说明播放器只放在推荐流首页(本卡 URL 根本没进内存)
ffmpeg 读中文路径 Invalid argument 复制到 ASCII 路径再处理
批量试解产生海量临时文件 被 SAFE_DELETE_BULK_CONFIRM_REQUIRED 拦 试解不落盘:一次性加载 wasm,在内存里试全 key 池(trykeys_batch.js),只输出命中 key
bash 环境 ls/tail/head/dirname → exit 127 一律 Write .py 再跑,不写 shell 管道

配套脚本(scripts/,均零第三方依赖)

脚本 用途
wxchannels_decode.js WxIsaac64 解密(ENCLEN = 明文 free box 起点,不是全长度);放 _wasm/,需同级 wasm_video_decode.{js,wasm}
xorrange.js 任意区间 XOR(<in> <key> <out> "<start:len:discard,...>"),用于验证"mdat 段是否另起密钥流"这类对齐假设
trykeys_batch.js 不落盘批量试 key:一次加载 wasm,对一个文件的整个 key 池试解,只输出 ftyp 命中的 key(避免临时文件爆炸)
wxchannels_scan.py 扫 Weixin.exe 内存,抓带完整鉴权的 stodownload URL
wxchannels_pull.py 窗口置前 / 点击播放 / 关播放器(nav / play / close)

★ 密钥邻近提取(省掉整个试解环节):以目标 encfilekey URL 为锚,在其前后 ±4000 字节内提取 8–12 位纯数字串,按与 URL 的字节距离升序输出候选。实测第一个候选即命中(272905582,dist=59)。

🚨 续播铁律(用户已三次强调 · 违反=产物直接报废)

每张卡读完必须当场关闭播放器,否则视频号自动接播下一条无关视频,把录像、录音、内存扫描一起污染。

实证(137):正片 216.3s 讲完("…今天跟大家分享,拜拜"),播放器不关闭就自动接播下一条(「墨米·WorkBuddy+微信读书skill」3:15),录像尾部 216–253s 全是别人的内容。记录过 ≠ 会执行——所以必须让判据自动化,不靠记性。

关闭方式(wxd.py 里没有 close_player,别去找它):

u.PostMessageW(hwnd, 0x0010, None, None)     # WM_CLOSE
🔴🔴 关窗的三个致命细节(2026-09-21 全部踩过,缺一个就会漏关)

① 播放器不是 Weixin.exe 的窗口 —— 它由 WeChatAppEx.exe(CEF 宿主)渲染!

进程家族:Weixin.exe(主程序,1 个)
          WeChatAppEx.exe(视频号 / 播放器 / 小程序宿主,实测 3 个)

⇒ 按 IMAGENAME eq Weixin.exe 过滤 PID 会既找不到也关不掉播放器(现象:日志全程 waiting、播放器不被置顶、画面被别的全屏窗盖住只录到声音)。PID 集合必须同时含 Weixin.exe + WeChatAppEx.exe。

② 必须 include_hidden=True(枚举不可见窗口)
视频号自动接播的瞬间窗口会瞬时不可见。只枚举"可见"窗口会:(a) 误判「播放器已关闭」→ 提前停录;(b) 清场时漏掉它 → 无关视频继续挂播。⇒ 关闭判据要连续 3 次(≈0.6s)都找不到才认定关闭;句柄变了要跟随新句柄而不是当"已关闭"。

③ 关闭必须"验证到零",且按标题白名单保护小程序窗
Chrome_WidgetWin_0 是通用 CEF 类名(本机十几个无关进程都用),盲关会误伤。判据:

cls.startswith("Chrome_WidgetWin") and PID ∈ {Weixin.exe, WeChatAppEx.exe}
and title ∈ {"微信", "视频号", ""}      # 播放器 / 视频号独立窗 / 无标题壳

非白名单标题记 skip 日志(便于事后审计是否漏关),不要静默跳过。

🛡️ 常驻守卫(把"记得关"变成机制 · 本机已部署)

脚本被强杀(点停止/超时)时 finally 不会执行 —— 这就是污染反复出现的真因。解法=独立守卫进程
(scripts/wxchannels_guardian.py,用 WMI 启动才能跨命令存活,见下文"进程逃逸"):

判据 行为
存在 _rec/_guardian.stop 永久休眠(用户要自己看视频时用)
_rec/_guardian.hb 不存在 或 mtime>15min 休眠(防止几小时后误关用户的视频)
_rec/_rec.lock 存在(正在录制) 不动手
以上都不触发,且发现播放器窗 立即 WM_CLOSE + 复核残留

⇒ 录制脚本负责:开录前清场、结束时关、finally 兜底;并写 _rec.lock;退出时删 lock、刷新 _hb。
⇒ 守卫负责:收尸(脚本被强杀留下的播放器)。

⚠️ 窗口恢复必须校验"尺寸"而不只是"位置"

微信被挤下线 / 停在紧凑态时,主窗可能变成 296×388(rect 正常、不在屏幕外,但内容全错位)。
⇒ 恢复后校验 宽≥800 且 高≥800,不足则 SW_MAXIMIZE → SW_RESTORE → SetWindowPos 重试 6 次;仍不达标必须中止(宁可不动,也不能按错坐标乱点)。

⚠️ 微信会被其他设备挤下线(硬阻断,需用户介入)

现象:主窗尺寸突变 + 标题不再是账号昵称,弹窗「当前账号于 XX:XX 在 <设备名> 设备上登录。此客户端已退出登录」。
⇒ 此时任何点击都无意义,唯一出路是用户重新扫码。先截图确认状态再动手,别把"窗口尺寸异常"当成 bug 反复重试。

★ 自动识别"正片已结束"(2026-09-21 用 137 录像离线标定)

信号 正片内 切条瞬间
视频区帧差 MAD(缩 64×38 灰度,0.4s 采样) 中位 0.022 t=216.5 → 0.0848
音频 RMS(0.2s 块) 0.03–0.08 t=216.0 → 0.0060

⇒ 判据:RMS 骤降至 &lt;0.006 且此前 2s 内出现过 &gt;0.03 + 其后 1.2s 内 MAD ≥0.05 → 判正片结束 → 立即关播放器。
- 必须设 warmup ≥15s:开头"未开播/加载中"同时有静音与画面剧变,会误触发。
- MAD 单用不可靠:正片内转场 MAD 也能到 0.15+(137 在 61.5s/66.5s 处即如此),必须与音频骤降配对。

3.2.4b ★★ D 路线:录屏+系统声(兜底通道,2026-09-21 实测跑通)

何时走 D:E 路线拿到的只是「按需窗口流」——样本表只覆盖播放缓冲窗口内的那一段(137 t1 容器声明 253s,但 stsz 只写了 7596 帧 ≈ 11.26s,且无音轨)⇒ 产物完整性无法保证时,转 D,一次拿全。

两条流分开采:

流 工具 要点
系统声 soundcard(WASAPI loopback) sc.all_microphones(include_loopback=True),取名字含 DELL/NVIDIA 的那个(=默认扬声器);48kHz/2ch,float32→int16 写 wav
画面 ffmpeg -f gdigrab -framerate 8 -i desktop -c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p -g 16 out.mkv(用 mkv,被中断也不废)
  • 本机实测:-f dshow 枚举不到任何设备(Could not enumerate audio only devices)⇒ dshow 这条路是死的,别耗;系统声只能靠 soundcard 的 loopback。
  • 完整性校验(必做):录得时长 vs 容器声明——137 录到 253.6s,mvhd 声明 253.20s ⇒ 完整 ✓
  • 录制期间微信主窗与播放器都要 SetWindowPos(hwnd, HWND_TOPMOST=-1, …, SWP_NOSIZE|SWP_NOMOVE) 置顶:gdigrab 抓的是屏幕像素,被遮挡就录到遮挡物。
  • 结束即关播放器,见上「🚨 续播铁律」。

⚠️ 坐标与滚动(两个必踩的坑)
1. 微信窗口被最小化后(rect 为 -32000)必须先 ShowWindow(hwnd, SW_RESTORE),否则所有点击落空;恢复后回读 rect 校验(宽须 >400),并校验目标坐标落在 rect 内,再动手。
2. 微信"窗口恢复"会把自己滚到最新消息(底部) ⇒ 滚动定位必须与"恢复窗口"在同一次执行内完成:恢复 → 向下滚 6 次到底 → 向上滚 N 次 → 点击。窗口尺寸没变时 move_resize 不会重置滚动位置,但最小化恢复一定会。

⚠️ 会话区滚动:滚轮事件被微信忽略 ⇒ 只能触摸拖动(wxd.drag)。向上翻旧消息 = 手指向下拖。
(2026-09-27 复测:WM_MOUSEWHEEL 投递给主窗对会话列表同样无效,只有"一次性滚到底"偶尔生效;且滚轮会误落在会话列表上,把当前会话切走。定位坐标时务必把滚轮发到聊天区坐标,或在空会话上操作。)

🔴🔴 铁律:任何情况下都不要自动重启用户的微信(2026-09-27 二次踩坑)
- 微信 4.x 重启后必须手机扫码/确认才能登录(一键进入无效)—— 是硬阻断。
- 2026-09-21:因多次合成点击失效而重启 ⇒ 卡扫码页、任务中断。(第一次踩)
- 2026-09-27:用户明确选择"重启微信后由我重试",我写了 _tool_restart_wx.py 执行:
WM_CLOSE + taskkill /F 关掉 Weixin.exe + 8 个 WeChatAppEx.exe ⇒ 之后 subprocess.Popen 与 cmd //c start 启动均为「进程在(217MB)、窗口不出」(只有一个 -100,-100 隐藏窗),疑似被火绒安全拦截或版本对非交互启动有校验。任务因此中断。(第二次踩)
- ✅ 正确做法:先请用户手动关闭;若确需重启,由用户手动双击图标启动。
- ✅ 合成输入失效时的升级顺序(到此为止,不穷举):
清理残留播放器/僵尸窗 → 清指针(发一次 up) → 换真实鼠标(SetCursorPos+mouse_event) → 请用户手动点一下 → 停。
已证全部无效的通道(2026-09-27 穷举记录,不要再试):PostMessage 点击列表项/真实鼠标单击/真实鼠标双击(双击会开独立会话窗,不是切换列表)/长按 150ms/搜索框+剪贴板(GlobalAlloc 返回 0)/WM_MOUSEWHEEL 滚动/键盘 Down/Ctrl+Tab。

🔴🔴 d.shot() 是整屏截图,不是窗口截图(2026-09-27 最贵的一个坑)
- wxd.WeChat.shot() 不做任何裁剪,返回 1920×1080 整屏;d.rect 只用于别处,与返回图无关。
- 后果:拿整屏图像的像素坐标当窗口内相对坐标用 ⇒ 窗口在 x=940 时点击整体错位 940px,表现为"点 A 却激活 B""会话列表毫无反应"。
- 自检判据:im.size == (1920,1080) 而 d.rect 宽仅 960 ⇒ 立即断定未裁剪。
- 正确做法:所有取点一律以「整屏截图像素 ≡ 屏幕像素」为准;若需要窗口内相对坐标,自己加 rect 左/上偏移,不要假定 shot() 已裁。
- 配套标定工具:_tool_zoom.py(截取局部放大 3 倍并画 20px 刻度标尺),用它量出目标行精确 y 值再点。

3.2.5 音频转写(faster-whisper,本机实测可用)

解释器与模型(唯一正确位置):

解释器  $env:USERPROFILE\.workbuddy\binaries\python\envs\default\Scripts\python.exe
模型根  D:\AZ\faster-whisper-models\faster-whisper-medium       # ★ 唯一位置,别到处找

🔴 CUDA 必须用 PowerShell 前置 PATH(bash export PATH 不生效,会报 cublas64_12.dll is not found):

$env:PATH = &quot;$env:USERPROFILE\.workbuddy\binaries\python\envs\default\Lib\site-packages\nvidia\cublas\bin;&quot; +
            &quot;$env:USERPROFILE\.workbuddy\binaries\python\envs\default\Lib\site-packages\nvidia\cudnn\bin;&quot; + $env:PATH
$env:HF_HUB_OFFLINE = &quot;1&quot;
&amp; &quot;$env:USERPROFILE\.workbuddy\binaries\python\envs\default\Scripts\python.exe&quot; asr.py

参数(中文必须加):

m = WhisperModel(MODEL, device=&quot;cuda&quot;, compute_type=&quot;float16&quot;, download_root=MODEL_ROOT)
segs, info = m.transcribe(audio, language=&quot;zh&quot;,
                          initial_prompt=&quot;以下是普通话的句子,请使用简体中文转写。&quot;)   # ★ 不加会输出繁体
  • 不带 --model 即 medium;实测 172s 音频 ≈ 14s 转写,2099 字。

提取规则表(先看这张表,再决定走哪条 —— 避免无效折腾)

目标 能否拿到 走哪条 要点
封面上的标题/作者 ✅ OCR + Agent 看图(交叉印证) 封面 JPEG 真文件,最省事
卡片正文元数据(标题/作者/时长) ❌ —— _b.dat 全加密,别试
视频本体 ⚠️ 有条件 E 路线(首页选)或 A 路线 E 需播放 + 扫内存;必须凑齐 token+svrbypass+sign+ftype=666
视频讲了什么(内容层) ⚠️ 得本体后 转写(§3.2.5)+ 抽帧读图 只有拿到本体才谈得上
链接 ❌ 手机端复制 PC 播放器无「复制链接」入口
字幕 ❌ —— 微信不落字幕

🔴 ASR 转写为空 ≠ 拿不到内容(2026-09-27 card138 实证,必读)
视频号有一类纯文字展示型短视频:正片全程只有 BGM + 画面上的文字卡片,无人声。
- 症状:faster-whisper 输出只有 请使用简体中文转写。(那只 initial_prompt 的回声),JSON 里 segments 为空。
- 此时不要判定"取不到",立即改走读帧:ffmpeg -ss &lt;t&gt; -i rec.mkv -frames:v 1 out.png,在正片时间窗内逐秒抽 10~14 帧,Agent 亲眼读画面文字。
- 实战效果:card138 正片仅 ~7s,抽 t=2..16 共 13 帧后逐字读全了一整段提示词(比转写更准,因为文字是排版好的、无同音误识别)。
- 判据:_rec/&lt;id&gt;_transcript.txt 字节数 < 200 ⇒ 先怀疑"这是展示型",去抽帧,不要去调 ASR 参数。

资源纪律(用户明确要求,避免浪费):
1. 先定层级再动手:明确要「封面层」还是「内容层」。只要封面层,30 秒能交;要内容层才启动 E/A 路线。
2. E 路线一次给足时间预算:单卡「播放→扫→下载→解密→验帧→转写」≈ 5–10 分钟。卡上 15 分钟没出本体就转 A 路线并告知用户,不要无限重试。
3. 不重复试已证伪的路:裸 URL、_b.dat、磁盘找视频 —— 三次已证伪,别再试。
4. 交付分两层标注:封面层(作者/标题)与内容层(转写/读帧)必须分开写,拿不到内容就写「未提取到」+ 给替代路径。

E 路线命中后的三级验收(2026-09-20 card137 实战补)

试解命中一个 key ≠ 拿到本卡内容。 必须按顺序过三关,任一关不过就判该候选出局:

关 动作 判据(唯一)
1 抽帧看画面 ffmpeg -ss 1 -i cand.mp4 -frames:v 1 out.jpg,Agent 亲眼看 画面与卡片封面对得上 ⇒ 过;否则污染,出局。不看分辨率、不看时长
2 查音轨完整性 ffmpeg -i cand.mp4 看流信息 + ffmpeg -i cand.mp4 -vn -ac 1 -ar 16000 a.wav 看抽出音频实际时长 音频时长 ≈ 视频时长 ⇒ 过;音频远短于视频(如 35s 视频只出 2.1s)⇒ mdat 截断,只能给画面层
3 转写 faster-whisper(§3.2.5) 段数 ≥ 2 且有实质内容 ⇒ 内容层成立;只有 1 句片头话 ⇒ 内容层不成立,如实写「仅拿到片头片段」

> 过不了第 1 关就立刻换候选,不要对污染候选做第 2、3 关(那是最费时间的地方)。
> 过不了第 2 关=这张卡E 路线到此为止,转 A 路线或只交封面层 —— 这不是"没试够",是路本身断了,止损线在这里是正确动作。

3.3 ★★ 笔记(Note,最容易漏)

&lt;根&gt;\xwechat_files\&lt;账号&gt;\business\favorite\temp\NoteCache\
  • 用户转发一条笔记卡片时,全部图片都落在这里,mtime = 那条消息的时间戳
  • 同时 business\xeditor\mmkv\(笔记编辑器)会在同一秒写入
  • 实测:只有图片,没有 .txt/.html —— 笔记正文与标题存在加密 SQLite(msg\*.db,无免费解),别浪费时间找正文;标题只能靠用户截图或让用户口述

> 图片命名规律:微信图片_YYYYMMDDHHMMSS&lt;毫秒&gt;_N.jpg(高清原图)+ 一批 32 位 hash 文件名(同图低清副本) ⇒ 去重后会少一半。

3.4 微信自建的低价值目录(直接跳过)

Cache CustomEmotion Temp TempFromPhone PAG Sns MPPageFastLoad General
Image Video MsgAttach ResUpdate ResUpdateV2 Backup BackupFiles config
Applet WMPF publicLib publicTestLib

3b. 企业微信转发聊天归档:在线引用类资源(2026-09-19 新增)

微信 / 企微转发出来的聊天归档里混着两类载荷,处置完全不同:

载荷 形态 处置
离线附件 图片 / 视频 / 文档,物理存在于归档里 本地直接读(见本篇零依赖解析)
在线引用 转录里只有类型标签 + 一个 id 必须联网经连接器取回(见下)

权威清单:宿主会把找到的在线引用逐条列在一个专门的块里。那份清单是权威的 —— 不要从转录文本里自行推导,也不要漏掉其中任何一条。

路由(按类型走):

转录里的标签 取回通道
文档 文档类通道
微盘文件 微盘类通道
日程 日程类通道
待办 待办类通道
会议 / 智能纪要 会议类通道(纪要可能另带会议码)

每条引用本身已带上"该用哪个能力",直接用它,并先读该能力的参数说明再调用。

授权纪律(三条,全是踩过的):

  1. 授权由宿主管理:第一条命令先用只读的状态探测,不要一上来就调业务命令。
  2. 探测到未授权:此时宿主已经在弹授权对话框了 —— 你要做的是等(轮询状态,约 3 分钟上限),并且只对用户说一句"正在等你在对话框里完成授权",不要每次轮询都重复催。
  3. 绝不自行发起授权(任何形式):自行发起会打印自己的链接/二维码、甚至拉起外部浏览器,与用户正在看的那个对话框重复并互相竞争。唯一允许的授权命令是只读的状态探测。

取回纪律:

  • 先全部取回,再写摘要。在线条目是必需的源材料,不是可选参考。
  • 没取回就不许描述 —— 不要根据标签猜它的内容。
  • 单条失败重试一次;仍失败就继续取其余条目,并把它记为缺失。
  • 取回途中断在授权上(如凭证过期)→ 回到探测那一步一次,然后从断点继续。
  • 任何在线条目未取回时,不得声称"归档已完整摘要"。

被拒绝 / 超时:不要重试、不要在本轮再问一次授权;只总结归档自身的内容(转录 + 离线附件),并点名说明哪些在线条目因未授权被跳过。

输出红线:指代条目要用可读的标签 / 主题 / 标题 / 时间,绝不暴露 id 字段。这一条优先于本节其他内容。


4. ★ 性能实测数据(决定扫描策略)

本机实测(E 盘,2026-09-18):

操作 耗时 说明
单账号 FileStorage 全树 walk 10.2s 3083 目录 / 15071 文件
同上 + 逐文件算 md5 超时被杀 ← 这是 SIGTERM 的真凶
时间窗筛选后再算 md5 <1s 候选通常只剩个位数

三条结论:
1. md5 去重只能作用于「已通过时间窗筛选的候选」,绝不能对全量文件做 —— 这是最容易踩的坑
2. 多账号遍历必须带 deadline 预算 + 账号数上限
3. 顶层可按「目录 mtime 早于窗口 → 整棵跳过」预筛剪枝

正确的时间窗定位法(只列有改动的目录,别全盘 walk):

cut = time.time() - 86400
hits = []
for dp, dn, fn in os.walk(R):
    if dp[len(R):].count(os.sep) &gt; 6:      # 剪枝:太深就不进
        dn[:] = []; continue
    try:
        dm = os.path.getmtime(dp)
    except OSError:
        continue
    if dm &gt; cut:
        hits.append((dm, dp, len(fn)))
hits.sort(reverse=True)

这一步就能一眼看出用户说的那条东西落在哪(哪一分钟写入的、在哪个子目录)。


5. 活跃账号判定

一个数据根下有多个 wxid_*(历史账号)。用 Msg\*.db 的 mtime 判活跃度,只扫最活跃的 1-3 个,别全扫。

实测本机 5 个账号,最活跃为 wxid_jqzfv82qtkek11。


6. 零依赖解析(本机无任何文档库)

实测环境:仅有 PIL 12.3.0;docx/pptx/openpyxl/pypdf 全部缺失,且本机倾向不装 pip 包。
解法:.docx/.pptx/.xlsx 本质是 zip+XML,用标准库 zipfile 直读。

# docx:word/document.xml(+header/footer)
# pptx:ppt/slides/slideN.xml,抽 &lt;a:t&gt; 文本,按页分组
# xlsx:xl/sharedStrings.xml + xl/worksheets/sheetN.xml,还原单元格

实测效果:0.0 秒,中文完全正确,比走 COM 快两个数量级。优先走这条路。

老格式(.doc/.xls/.ppt)才需要 COM 兜底(WPS/Office 已装)。


7. ★ 两个必踩的编码坑

7.1 读文本必须做编码探测

微信收到的 .txt 大量是 GBK(中文记事本默认)。硬按 utf-8 读 → 全篇乱码。

BOM 优先 → utf-8 严格试 → gb18030 → utf-16 → latin-1 兜底,
用「U+FFFD + C0/C1 控制字符」数量择优

7.2 stdout 必须强制 UTF-8

实测:Windows 控制台默认 GBK,print(&quot;定位&quot;) 输出成 瀹氫綅。Agent 读 stdout 会拿到垃圾。

sys.stdout.reconfigure(encoding=&quot;utf-8&quot;, errors=&quot;replace&quot;)

8. ★ PDF 乱码闸门(必须做,否则污染整份摘要)

中文 PDF 常用自定义字体编码表,正则抽出的"文本"会是完全无意义的乱码,例:

2&#x27;4*9)&#x27;6+*+9/-4 5, ?/).&#x27;4-6;(2/) 9+);8/:?9;6+8&lt;/9/54)+4:+8

必须加质量闸门:可读字符(CJK + ASCII 可打印)占比 &lt; 0.75 或 CJK 占比 &lt; 0.15 → 判定失败并返回明确原因,而不是把乱码当摘要。

> 宁可不给结论,也不能给错结论。


9. 读图技巧(技术类资料的关键)

营销/规划图上的小字在缩略图里读不出,必须先切块放大再读:

from PIL import Image
im = Image.open(r&#x27;&lt;大图&gt;&#x27;); W, H = im.size
ox, oy = int(W*0.08), int(H*0.08)          # 8% 重叠,防止切掉字
for k, b in {&#x27;TL&#x27;: (0, 0, W//2+ox, H//2+oy),
             &#x27;TR&#x27;: (W//2-ox, 0, W, H//2+oy),
             &#x27;BL&#x27;: (0, H//2-oy, W//2+ox, H),
             &#x27;BR&#x27;: (W//2-ox, H//2-oy, W, H)}.items():
    c = im.crop(b)
    c = c.resize((int(c.width*2.2), int(c.height*2.2)), Image.LANCZOS)
    c.save(r&#x27;&lt;输出目录&gt;\%s.png&#x27; % k)

经验值:
- 四象限 2.0~2.5× 足以读清图注(楼栋号、层数、面积、路名)
- 单点小字(路名、编号)用 4~7×
- 旋转读数:路名沿斜向道路排布时,img.rotate(-90, expand=True) 转水平再读;再按道路倾角补 rotate(±9)
- 长条图别整张读 —— Read 工具会缩放,字符反而更糊;改切小段(如 (40,560,200,780) 这种 160×220 的小块)
- 一次可并行发多个 Read(同一条消息里多个 tool call),批量看图更快


10. 脱敏护栏(硬红线)

摘要前扫描并主动提示:
- 身份证号 / 手机号 / 银行卡号 / 邮箱
- 机构名(XX有限公司|设计院|规划院|置业|地产)
- 甲方/业主/委托方:XX

实测真实命中:微信里确实存在带真实姓名 + 身份证号的证明材料。
凡发现即主动列出,并明确"任何要上传/分享/参赛的产出中均不得出现"。


11. 区分「实证」与「推定」(消化营销资料时)

营销资料(区位图、效果图)精度与权威性低于设计文件与官方公告。消化时:

  1. 逐条标注来源(哪张图、哪个位置)
  2. 凡"我推出来的"必须写成推定并汇总成待核项(例:由"挂牌栋数"反推"一二期分界"=推定)
  3. 与既有档案冲突时不要私自改 —— 并列两说,给出验证路径(例:地图标"孟新路" vs 档案"群建里")
  4. 反向验算最有力:拿官方已备案数据(如各栋总套数)反推图上数字,吻合即互证(例:96 套=24×4 ⇒ 坐实 25F)

12. 能力边界(必须对用户说清,不要过度承诺)

形态 可提取 说明
PDF ✅ 有条件 有文本层且非乱码才行;否则转图片读
PPT / PPTX ✅ 高 按页抽文本,零依赖,效果最好
Word / Excel ✅ 高 同上
CAD(.dwg/.dxf) ⚠️ 需转 走 万象-工程建设标准核查 技能的 DWG 解析段
.skp/.rvt/.3dm ❌ 需在源软件导出 PDF/图片
图片 ⚠️ 中 需读图;小字要切块放大
zip ✅ 列清单 rar/7z 无标准库支持
视频号转发视频 ⚠️ 分两层 封面 + 封面标题 ✅ 可读(Thumb 真 JPEG + OCR,见 §3.2.2);<br>视频本体 / 字幕 / 链接 ❌ 读不到(微信不落视频本体,元数据在加密库)。实测 9/19 窗口媒体文件命中 0
微信「笔记」卡片 ❌ 正文 正文在加密 SQLite,仅能取其中图片
聊天文字 ❌ 在加密库,Agent 读不到

> 对恢复不了的类型,要明说"读不到"并给替代路径,不要静默失败。


13. 脚本清单

> 🔴 &lt;技能目录&gt; 怎么取(2026-09-20 实测踩坑):技能加载时头部给的 Base directory 是
> .registry\history\&lt;技能名&gt;\&lt;seq&gt;_&lt;时间&gt;\files\ 这类登记路径,那里没有 scripts\ 目录,
> 按它拼路径必然 File does not exist。实盘在 ~/.workbuddy/skills/&lt;技能名&gt;/scripts/。
> ⇒ 拿不到路径时先用 Glob 搜 **/ocr_cards.ps1 找出真身,别硬套头部那个目录。
> (本机实测:$env:USERPROFILE\.workbuddy\skills\omni-wechat-fetch\scripts\ocr_cards.ps1)

── 通用取件(文件 / 图片 / 笔记 / 封面)────────────────────────
scripts/locate.py      # 定位:ini 找根 + 账号活跃度 + 时间窗扫描 + md5 去重
scripts/extract.py     # 提取:只读复制 + 零依赖解析 + COM 兜底 + 编码探测 + 乱码闸门
scripts/digest.py      # 摘要:压缩 + 要点抽取 + 脱敏扫描 + 确认卡渲染
scripts/harvest.py     # 编排:一键跑完四步并打印确认卡
scripts/ocr_cards.ps1  # ★ 卡片封面 OCR:WinRT Windows.Media.Ocr,零第三方依赖

── 视频号卡片「内容层」专用(见 §3.2.4)──────────────────────
scripts/wxchannels_status.py   # ★★ 开工前体检:进程/窗口/尺寸/播放器残留/数据根/产物(2026-09-21 新增)
scripts/wxchannels_keyprobe.py # ★★ 密钥探测:按「与 URL 的字节距离」列出邻近数字串(2026-09-21 新增)
scripts/wxchannels_fetch.py    # ★★ 探尺寸+下载:`Range: 0-0` 拿真实总长,**超阈值判污染不下载**(2026-09-21 新增)
scripts/wxchannels_unpack.py   # ★★ 解密+验箱:**自动反推 ENCLEN**,逐个候选试解(2026-09-21 新增)
scripts/wxchannels_record.py   # ★ 录制:点卡片 → 录屏+系统声 → **自动判切条并关播放器**
scripts/wxchannels_guardian.py # ★ 常驻守卫:非录制中自动关播放器(兜住被强杀的情况)
scripts/wxchannels_mad_cal.py  # 标定工具:从一段已知录像标出「切条」的帧差/音量阈值
scripts/wxchannels_scan.py     # 扫微信进程内存,抓带完整鉴权的 stodownload URL(--shots/--gap/--out)
scripts/wxchannels_decode.js   # WxIsaac64 解密(**ENCLEN 由 unpack.py 自动传入**,别手填全长度)
scripts/trykey.js              # 单 key 试解,只输出解密后头 16 字节 hex(不落盘)
scripts/trykeys_batch.js       # ★ 不落盘批量试 key:一次加载 wasm 试完整 key 池,只输出命中 key
scripts/xorrange.js            # 有界实验:对指定字节区间做 XOR(用于验证&quot;某段是否加密&quot;)
scripts/wasm_video_decode.js   # 官方 wasm 载荷(被上面几个 js 引用)
scripts/wasm_video_decode.wasm

> ⚠️ 旧版这里写「ENCLEN 传全长度」——那是错判据,已于 2026-09-21 推翻。
> 加密只覆盖头部 ftyp+moov,free+mdat 本来明文;传全长度会把正确的 mdat 用 XOR 破坏。
> 现在统一走 wxchannels_unpack.py,它自己从密文反推(见 §3.2.4「⑤ 解密」)。

13.1 主流水线(一条链走完 · 每步都有判据,不过就别往下走)

> 为什么要有这张表:全流程的失败几乎都不是"技术不会",而是跳步——没体检就动手、
> 拿到流就交付、没关播放器就换下一张。顺序不可跳,判据不过不往下走。

步 动作 命令 / 手法 判据(不过就停) 不过怎么办
0 体检 python &lt;技能目录&gt;/scripts/wxchannels_status.py --dir &lt;产物目录&gt; 退出码 0,无阻断项 按提示逐项处理:启动微信/恢复窗口/关残留
1 定位卡片 会话区触摸拖动滚动 + 截图核对 目标卡可见,且坐标落在卡片内(截图核过) 重新滚动定位;坐标错=点击全落空
2 播放 wxchannels_record.py &lt;tag&gt; &lt;滚动次数&gt; &lt;RX&gt; &lt;RY&gt; &lt;最大秒&gt; &lt;预热秒&gt; 播放器出现,或有音频信号 改用 wxchannels_keyprobe.py --tap RX,RY 单独点一次再扫
3 探 URL + 密钥 wxchannels_keyprobe.py --prefix &lt;enc前12位&gt; --tap RX,RY 拿到目标 URL 且有候选 key(dist 升序) 多扫几轮(--shots);修正 --prefix 重定位
4 下载 wxchannels_fetch.py &lt;candkeys.json&gt;(Range: 0-0 先探尺寸) Content-Range 给真实总长;>80MB 判推荐流污染 换候选,别下
5 解密 wxchannels_unpack.py &lt;密文&gt; --keys &lt;候选&gt; 退出码 0,箱链 ftyp→moov→free→mdat 换候选 key/回第 3 步重扫
6 验收 ffmpeg 比「解码时长 vs Duration」+抽 1 帧对封面 时长吻合 且 画面归属正确 时长不等 ⇒ 是窗口流,转 D 路线;画面不对 ⇒ 污染,换候选
7 转写 faster-whisper(§3.2.5) 段数 ≥2 且有实质内容 只有片头一句 ⇒ 内容层不成立,如实写
8 收尾 finally 兜底 + 常驻守卫 播放器残留 = 0 手动 PostMessageW(WM_CLOSE),回读复验

路线分工(第 2 步之前先判):

路线 何时走 产物 代价
E 内存直取 默认首选;要"可验证归属的干净本体" 解密 mp4(可能是"按需窗口流") 快,但可能拿不全
D 录屏 + 系统声 E 判为截断流/E 失败/要完整全片 录屏 mkv(含 UI,时长=真实时长) 慢(≈视频时长),需音频通道

> 判「E 拿不全」的唯一硬证据(2026-09-21 实测):E 解出的文件 stsz 样本表只写了前 11 秒、且无音轨,
> 而 mvhd 声明的是 253 秒 ⇒ 该资产只覆盖播放缓冲窗口,不是全片。此时必须转 D,别硬交付。

E 路线一键链(视频本体 → 内容):

python &lt;技能目录&gt;/scripts/wxchannels_status.py --dir &lt;产物目录&gt;          # 0 体检,退出码必须 0
# 1 定位 + 2 播放:滚动会话到目标卡(触摸拖动)→ 点开(见 §3.2.4 / wxchannels_record.py)
python &lt;技能目录&gt;/scripts/wxchannels_keyprobe.py --prefix &lt;enc前12位&gt; --tap RX,RY   # 3 拿 URL+候选key
python &lt;技能目录&gt;/scripts/wxchannels_fetch.py candkeys.json --max-mb 80             # 4 探尺寸+下载
python &lt;技能目录&gt;/scripts/wxchannels_unpack.py &lt;密文mp4&gt; --keys &quot;k1,k2,k3&quot;          # 5 自动定 ENCLEN+验箱
# 6 ffmpeg 比时长 + 抽帧验归属 → 7 faster-whisper 转写(§3.2.5)→ 8 关播放器

> 速查卡:references/视频号卡片提取速查卡.md —— 动手前先看它(分层选择 / 能拿什么 / 五步判据 / 止损线)。

卡片封面 OCR 单独用法(配合 §3.2.2):

powershell -NoProfile -ExecutionPolicy Bypass `
  -File &lt;技能目录&gt;/scripts/ocr_cards.ps1 -InDir &lt;封面目录&gt; -OutFile &lt;输出.txt&gt;
  • 建议先放大 3× 再 OCR(封面字小,原图直接认会掉字)。
  • 输出 LANG=zh-Hans-CN + 每张一段,无字输出 (no text)。
  • OCR 只是辅助:Agent 自己看图往往比 OCR 更准(OCR 会把「墊」认成「史」这类),两者交叉印证再落笔。

一键运行:

python &lt;技能目录&gt;/scripts/harvest.py &lt;窗口小时&gt; &lt;输出目录&gt; [--max N] [--kind pdf,ppt] [--no-com]
  • --kind 可只取指定类型(pdf,ppt,word,excel,cad,image,archive,video,text)
  • --no-com 跳过 WPS/Office 转换(纯零依赖,更快)
  • --accounts N 最多扫 N 个活跃账号(默认 3)
  • --budget N 扫描预算秒数(默认 90)
  • 产出:raw/(复制的原件)+ 确认卡.md + manifest.json

14. 坑清单

14.0 视频号取卡专项坑(2026-09-21 全部实测 · 优先看这段)

坑 症状 解法
🔴 播放器由 WeChatAppEx.exe 承载 按 Weixin.exe 过滤进程 ⇒ 播放器既找不到也不置顶,只录到声音 进程集合=Weixin + WeChatAppEx + WeChat
🔴 只枚举「可见」窗口 接播瞬间窗口瞬时隐藏 ⇒ 误判"已关闭"提前停录;清场也漏掉它 枚举含不可见;连续 3 次找不到才算关闭
🔴 正常路径不关播放器 自动接播下一条,录像/录音/内存扫描一起污染 判据「音频 RMS 骤降 + 画面帧差突增」=切条 ⇒ 当场关;finally 兜底;常驻守卫
🔴 脚本被强杀 ⇒ finally 不执行 残留播放器继续播 靠常驻守卫(非录制中、15 分钟心跳内自动关)兜住
🔴 微信窗口被最小化(rect 为负值 / -32000) 所有点击静默落空,界面像"没反应" 动手前先读 rect;恢复后还要校验尺寸(见下条)
⚠️ 只校验位置、不校验尺寸 窗口恢复成 296×388 ⇒ 坐标全错、点空 恢复后校验 W&gt;500 and H&gt;500,不达标重试
⚠️ 坐标算错(落在卡片外侧空白) 点击无任何反应,界面零变化 用大图+十字标注核对落点;卡片位置会随布局变
⚠️ 微信被其他设备挤下线 主窗消失,提示"此客户端已退出登录";重启微信还可能要求重新扫码 硬阻断,必须用户介入;不要反复重启(会触发二次登录)
⚠️ 置顶后又被 IDE 抢前台 点击落到别的窗口 点击前一刻再强制置前一次,并回读 GetForegroundWindow()
⚠️ 拿「朝向」当归属筛子 把竖版/横版当污染判据 ⇒ 误杀真卡 朝向不作筛子;归属只能抽帧看画面
⚠️ 拿「NAL 走链计数」判完整性 已完整可播的文件也只走 1 个 NAL ⇒ 判据无区分度 改用 ffmpeg「解码时长 vs 容器 Duration」
⚠️ 把 mvhd 声明时长当实际时长 声明 253 秒但只有 11 秒可解码 两个都要读:stsz 样本表长度 ≈ 实际;两者差很大 ⇒ 是按需窗口流,转 D 路线

14.1 通用取件坑

坑 现象 解法
数据根不在 C 盘 默认路径下 0 文件 读 ini 拿真实盘符(§2.2)
md5 对全量文件算 SIGTERM 无输出 只在时间窗候选上算(§4)
全盘 walk 超时 SIGTERM,无输出 改成"只列有改动的目录"+深度剪枝(§4)
中文 stdout 乱码 定位→瀹氫綅 reconfigure(utf-8)(§7.2)
TXT 读成乱码 全篇问号/方块 编码探测(§7.1)
PDF 乱码当正文 摘要全是 2&#x27;4*9) 质量闸门(§8)
~$xxx.docx 被当文档 抽出乱码、白跑一轮 过滤 ~$ / .dwl / .tmp / .bak
以为笔记里有正文 目录里只有图片 正文加密,让用户口述
把副本当不同文件 文件数翻倍 MD5 去重(§3.1)
用序号判最新 (1) 反而更旧 看 mtime
缩略图读不清 字糊成一片 切块+2~7× 放大(§9)
微信「文件传输助手」无独立目录 找不到 附件按会话 hash 存于 msg/attach/&lt;hash&gt;/,靠 mtime 定位
bash 缺 coreutils tail/head/cat/dirname → Exit 127;2026-09-19 起连 ls 都没有 别在 bash 里做文件操作;改用 Python 或 PowerShell
在 python -c 里用反引号 文本被 bash 吃掉 脚本先落盘为 .py 再执行
在 Python 源码里写 \n 转义 经工具写入后变成真实换行 → SyntaxError 改用三引号 / chr(10)
bash shim 报 cd: null directory 命令整体 SIGTERM、输出为空、看不出错因 直接用 PowerShell 调 python.exe,别走 bash
PowerShell *&gt; 重定向 写出 UTF-16 → Read 报 "binary file" 读不了 用 2&gt;&amp;1 \| Out-File -Encoding utf8,或让 Python 自己 open(..., encoding=&quot;utf-8&quot;) 写日志
PS 5.1 回显中文乱码 日志里 文件传输助手 → 鏂囦欢浼犺緭鍔╂墜 不影响 ASCII 关键信息(路径/时间/大小);要中文就 Python 内 reconfigure(utf-8) 自己写文件
时间窗扫描按父目录 mtime 剪枝 漏文件(实测 9 张只扫出 7 张) 对 cache/YYYY-MM/Message 这种小规模目录直接全 walk,别提前剪枝
用 % 格式化生成 HTML CSS 里的 % 触发 ValueError: unsupported format character 用 .replace(&quot;__PLACEHOLDER__&quot;, ...) 占位替换
把「所有会话」当成「某个会话」 上一轮 23 张卡片其实跨了 5 个会话 先用 §3.2.1 反解 hash 锁会话,再谈"读全"

15. 交付话术(收尾必做)

输出确认卡后,明确列出三个待确认项:
1. 命中的文件是否就是目标那批?
2. 未提取项是否要走替代方案(读图 / CAD / 转图片)?
3. 下一步动作:归类归档 / 生成台账 / 出结构化文档 / 其他?

> 在用户给出选择之前,不要动手做任何后续动作。


常见误用与常见问题(FAQ)

常见误用(反模式)

误用 后果 正解
猜盘符、枚举用户名去找数据根 90% 的失败在这一步 读 ini,不猜盘符;用 glob 按 config\*.ini 枚举,不要枚举用户名
一上来就调业务命令 授权纪律被绕 授权由宿主管理 —— 第一条命令先用只读的状态探测
没取回就描述内容 编造 没取回就不许描述 —— 不要根据标签猜它的内容
在线条目未取回却声称「归档已完整摘要」 虚假完整 任何在线条目未取回时,不得声称「归档已完整摘要」
静默失败 用户误以为是空的 对恢复不了的类型要明说「读不到」并给替代路径,不要静默失败
重复试已证伪的路 浪费时间 不重复试已证伪的路:裸 URL、_b.dat、磁盘找视频 —— 三次已证伪,别再试
自动重启用户的微信 高风险 任何情况下都不要自动重启用户的微信
从转录文本里自行推导在线引用 漏项、错项 宿主给出的那份清单是权威的 —— 不要自行推导,也不要漏掉其中任何一条
与既有档案冲突时私自改 篡改记录 并列两说,给出验证路径(例:地图标「孟新路」vs 档案「群建里」)
上传/分享/参赛产出里带项目名 违规 凡发现即主动列出,并明确「任何要上传/分享/参赛的产出中均不得出现」

常见问题

  • Q:先问清什么? A:见「1. 先问清楚三件事(能省一半时间)」。
  • Q:四条铁律是什么? A:见「0. 四条铁律(违反即失败)」;资源纪律见「0.1」。
  • Q:提取路线怎么选? A:先看「提取规则表」,再决定走哪条 —— 避免无效折腾。
  • Q:什么内容落在哪? A:见「3. 目录结构:什么内容落在哪」—— 真·文件/聊天图片与附件/卡片封面/笔记(最容易漏)。
  • Q:能直接回答「博主讲了什么」吗? A:封面层足以判断「要不要点开看」,但回答不了「视频里说了什么」 —— 对用户必须这么讲清楚。
  • Q:授权纪律有哪几条? A:三条,全是踩过的,见「授权纪律」。

附:融合说明

本技能由两部技能融合(2026-09-18):
- wechat-doc-digest —— 提供解析链(零依赖 zip-XML、编码探测、乱码闸门、脱敏扫描、摘要确认卡)与 4 个脚本
- wechat-local-file-harvest —— 提供落点知识(NoteCache 笔记缓存、目录类型图谱、读图放大量化经验、实证/推定分离)

删除的重复内容:两份技能各自写了一遍「数据根定位」(重叠约 80%),已合并为第 2 节;「性能实测」与「时间窗扫描」两处重复叙述合并为第 4 节。

常见问题

5 问
答案由本站依据条目字段整理
万象-微信文件与视频号取件怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_de2353f3/omni-wechat-fetch。安装方式为未标注。装完刷新技能列表或重开客户端。

万象-微信文件与视频号取件支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

万象-微信文件与视频号取件权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

万象-微信文件与视频号取件收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

万象-微信文件与视频号取件用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。