视频信息提取 → Word 文档 + Excel 大纲
用户刷短视频看到好内容,随手甩过来一条链接(常常是带口令的整段分享文案),
本 skill 负责把它变成能存档、能转发的结构化文档。
可复制示例指令(给用户的三条起手式)
> 用户不知道该怎么开口时,直接把下面任一条发给他复制。
① 纯链接(最常用)
帮我整理这条视频:https://www.bilibili.com/video/BV1xx411c7mD
② 带口令的整段分享文案(抖音/快手常见)
复制打开抖音,看看【XXX】的作品 https://v.douyin.com/xxxxxx/ 帮我提取一下内容
③ 手机转发到「文件传输助手」(视频号、快手走这条)
我把视频发到文件传输助手了,你处理一下最新的那个
一句话流程
链接/分享文案 ──run.py──▶ 元数据 + 字幕/转写 ──▶ 自动基础大纲 ──▶ .docx + .xlsx
│
└─(Agent 想做得更好)─▶ 改写 outline.json ──▶ run.py --render-only
两步走,先保证有、再追求好:
run.py "<链接>"—— 一条命令直接出可用文档(含自动时间轴),不需要 Agent 参与也能用。- Agent 读
result.json理解内容 → 改写outline.json→run.py --render-only升级成品。
脚本只做确定性提取,语义结构化由 Agent 完成 —— 这样"核心观点""金句""启发"的质量取决于模型理解,而不是关键词规则。但没有 Agent 时,用户也不至于拿到空壳。
输出长什么样(用户拿到手的就是这两个文件)
Word 文档 <视频标题>.docx —— 七段结构:
| 段落 | 内容 |
|---|---|
| 封面信息表 | 标题 / 作者 / 平台 / 发布日期 / 时长 / 互动数据 / 内容来源 |
| 一句话概括 | 这条视频到底讲了什么,一句话说清,不写"介绍了…" |
| 核心观点 | 3–8 条可独立成立的判断 |
| 时间轴大纲 | 时间 | 主题 | 要点 三列表格,带真实时间戳 |
| 金句 | 原话摘录,不改写 |
| 可执行启发 | 面向用户本人的行动项 |
| 全文转写 | 附录(逐字稿) |
Excel 大纲 <视频标题>.xlsx —— 四张表:① 概览 / ② 内容大纲 / ③ 观点与启发 / ④ 金句与标签
文件落在 <当前目录>/视频信息整理/。产出后必须用 present_files 一次性呈现这两个文件,并明确告诉用户文件所在目录。
环境(本机已就绪)
> 路径一律用 $HOME 形式书写,换机器、换用户名都不用改。
> 脚本内部已用 sys.executable 和 os.path.expanduser("~"),不写死任何机器路径。
PY="$HOME/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
S="$HOME/.workbuddy/skills/video-info-extract/scripts"
| 组件 | 位置 / 说明 |
|---|---|
| Python | $HOME/.workbuddy/binaries/python/envs/default/Scripts/python.exe(Windows 平台托管解释器) |
| yt-dlp | 已装(2026.08.19),平台解析 / 元数据 / 字幕 / 音频 |
| faster-whisper | 已装,无字幕视频本地转写;用 av 解码,不需要独立 ffmpeg |
| zhconv | 已装,转写文本繁 → 简(Whisper 中文输出常为繁体,必须转) |
| python-docx / XlsxWriter | 已装,产出 Word / Excel |
| 转写模型 | $HOME/.workbuddy/models/faster-whisper-small(裸 CT2 目录,脚本自动优先命中) |
| 术语词表 | <skill>/hotwords.txt,每行一个词,# 注释;显著降低专业词错字率 |
| 模型镜像 | HF_ENDPOINT=https://hf-mirror.com 且必须 HF_HUB_DISABLE_XET=1(见坑 1) |
自检:"$PY" "$S/run.py" --doctor(人话报告,缺依赖自动装、缺模型自动下)
依赖清单:requirements.txt
安装到别的机器
整套 skill 是自包含的,拷贝目录即可,不需要改任何代码:
# 用户级(推荐,所有项目可用)
cp -r video-info-extract ~/.workbuddy/skills/
# 项目级(只在该项目生效,可随项目一起共享)
cp -r video-info-extract <项目目录>/.workbuddy/skills/
拷贝后第一次运行 run.py 会自动补依赖 + 自动下模型,用户不需要做任何事。
详细分发说明见 安装说明.md。
平台支持矩阵
| 平台 | 支持 | 内容来源 |
|---|---|---|
| B站 / bilibili | ✅ 完整 | 元数据 + UP 字幕 + 弹幕 + 音频转写 |
| 抖音 / douyin | ✅ | 元数据 + 视频简介 + 音频转写 |
| 小红书 / xiaohongshu | ✅ | 元数据 + 音频转写 |
| YouTube | ✅ 完整 | 元数据 + 官方/自动字幕 + 音频 |
| 微信视频号 | ⚠️ 部分 | 预览页提取(文案+元数据+封面,自动)+ 同源文字版检索(命中率高);语音需本地文件 |
| 快手 / kuaishou | ⚠️ 无 extractor | 本地文件通道(见下节) |
| 本地文件 | ✅ | 同名字幕,或直接解码音轨转写 |
| 微信文件传输助手 | ✅ | 手机随手转发 → PC 落盘 → extract.py wechat(见下节) |
详见 references/platforms.md。遇到不支持的平台不要空转 —— 直接走降级方案并说明原因。
手机投递通道:微信「文件传输助手」(首选)
手机想「随手把视频丢过来」,最顺的路是微信自带的文件传输助手 ——
不需要任何连接器,因为微信 PC 端会把聊天里下载过的文件原样落盘:
<微信数据目录>\<wxid_xxx>\msg\video\YYYY-MM\<hash>.mp4 聊天视频(真 mp4)
<微信数据目录>\<wxid_xxx>\msg\file\YYYY-MM\<原始文件名> 聊天文件(保留原名)
本机实测账号目录:D:\xwechat_files\wxid_pwegnzfvyv5322_731d
(数据根候选写在 wechat_inbox.py 的 ROOT_CANDIDATES,新旧版路径都覆盖)
"$PY" "$S/wechat_inbox.py" # 列出近 2 个月收到的媒体文件
"$PY" "$S/wechat_inbox.py" --latest 1 --path-only
"$PY" "$S/extract.py" wechat # 直接处理收件箱里最新一个
"$PY" "$S/extract.py" wechat --dry-run # 先看会挑中哪个文件
extract.py 的 input 写成 wechat / 微信 / @wechat 即自动取最新媒体文件。
前提与边界(必须遵守)
- 视频号卡片分享过去不会落盘(那只是一条消息)。必须是真实的视频/文件。
- 电脑端要完成下载(点开播放一次)磁盘上才会出现文件。
- 微信目录只读:src_origin == "wechat" 时产物强制写到工作目录
.video_extract/wechat,绝不写回微信数据目录(会被微信清理或污染)。
- 本通道只列文件 + 只读用户明确指定的那个媒体文件,
不解析聊天数据库、不读聊天记录、不批量读取历史私密视频。
只处理用户当下要求处理的那一个文件。
坑:扫不到文件 ≠ 用户没发(「只收到封面」)
这是最容易误判的一步,务必先查再回话。
微信 PC 端收到视频消息时,先落一张封面缩略图,原片 mp4 要等点开播放/手动下载才写盘。
所以 scan() 扫不到任何媒体文件时,磁盘上其实可能已经躺着封面:
<账号>\msg\video\YYYY-MM\<hash>_thumb.jpg ← 有它、没同名 .mp4 ⇒ 视频本体没下载
<账号>\cache\YYYY-MM\Message\<chat>\Thumb\*.jpg ← 聊天里的封面(文件名内嵌 epoch)
<账号>\cache\YYYY-MM\Message\<chat>\Bubble\*_b.dat ← 气泡图,同样只有封面
判定口径:拿到用户「我发了」的反馈后,若 scan() 为空,必须再跑一次 pending 探测,
不要直接回「没找到」。两者的结论完全不同:
"$PY" "$S/wechat_inbox.py" --pending --pending-days 1 # 探测「封面到了、原片没到」
"$PY" "$S/wechat_inbox.py" --covers "<OUTDIR>" --pending-days 1 # 导出封面,用于辨认发了什么
导出封面后直接用多模态看一眼,就能说出「你发的是不是这条:<封面上的标题>」——
比空口说「没收到」有用得多,也避免用户反复重发。
给用户的三条出路(按省事程度排序)
1. 改用文件通道:手机微信 → 文件传输助手 → 「+」→ 文件 → 选那个视频。
以文件(而非视频消息)发送时,PC 端会直接把原文件下到 msg/file/。
2. PC 端点开播放 + 另存:在电脑微信里把该视频完整播放一次触发下载,
再右键「另存为」到桌面,然后重跑 scan()。
3. 换成有链接的同源平台:同一条内容若在抖音/B站/小红书也发过,发那条链接最省事 ——
能拿到完整视频 + 字幕 + 时间轴,不必录屏。
> 视频号内容没有「保存视频」入口,且转发到聊天是卡片,本来就不产生 mp4。
> 视频号场景下只有 录屏 一条实路:录屏文件同样走上面的「文件通道」投递。
微信视频号:三级降级(文案 → 同源文字版 → 视频文件)
视频号没有视频内容接口,但预览页能拿到文案和元数据 —— 这条路已经自动跑通。
拿到文案后优先做同源文字版检索,命中率很高,往往能直接补全全部内容。
一级(自动):预览页提取
https://weixin.qq.com/sph/XXXX → 301 → channels.weixin.qq.com/finder-preview/pages/sph?id=XXXX。
该页是 JS 单页应用,不需要登录,用本机 Edge headless --dump-dom 渲染后解析即可
(实现见 scripts/sph.py):
| ✅ 能拿到 | ❌ 拿不到 |
|---|---|
| 文案(含话题标签) | 视频本体 / 音频 |
| 作者、发布日期 | 逐句转写、时间轴大纲 |
| 互动数据(点赞/转发/推荐/评论) | 视频时长 |
封面图(finder.video.qq.com,是图片不是视频流) |
预览页会弹出「可前往微信观看此内容」——看到这个弹窗就等于音频确定拿不到,
不要再往下试。extract.py 已自动识别视频号链接并走这条路,结果里 partial: true、
transcript_source 为「无」。
不要再去试 channels.weixin.qq.com/web/pages/feed,它返回
{"desc":"非法请求","errCode":10012},必须微信登录态。
也不要再深挖前端 JS(已试到底,结论是死路):feed.*.js 里确实存在
h264VideoInfo.videoUrl / h265VideoInfo.videoUrl 字段,说明数据结构里有视频地址,
但服务端在预览页场景下根本不注入它;/finder-preview/api/* 一律返回
{"errCode":-1,"errMsg":"permission verification failed"}(401)。
接口模块 mmfinderopenwebapisvr.*.js 里也没有硬编码 endpoint,且引入了
crypto-browserify 做请求签名。这条路需要登录态 + 签名,不划算。
二级(自动,往往最有效):同源文字版检索 ⭐
这是视频号场景下最容易被忽略、但命中率极高的一招。
视频号爆款里有一大类是「搬运 + 口播」型内容:视频本身没有原创信息,
只是把一篇已经存在的长文/公众号文章/知乎答案/小红书笔记,用口播讲一遍。
这类视频的标题和文案就是那篇原文的浓缩。
所以拿到 title 和 description 之后,先做一次 Web 搜索,用标题里的
关键词(去掉「3亿人围观」「震惊」这类情绪词,保留实体词)去找原文:
# 用 WebSearch 工具,query 取「标题关键词 + 作者名」
# 例:"把薪资和工作经历喂给AI 提示词 隐藏变现机会 人工雨林"
命中后直接把原文的完整内容取回来补全大纲——常常能拿到比转写更完整的东西
(逐条清单、原文措辞、案例数据),因为原文本来就是逐字可复制的。
实测案例:视频号《3亿人围观的提示词:把薪资和工作经历喂给AI》
→ 搜到同源长文《和 AI 对话,找准人生规划》,完整收录了视频里讲的
7 段提示词原文 + 三个案例(外卖骑手/PPT 小王/10 年 HR),
信息量远超「只能拿到文案」的一级提取。
必须在产出里写清楚来源边界:这属于同源内容还原,不是视频口播逐字稿,
措辞可能与视频有出入;把 meta.note 和 transcript_note 都填上这句说明。
不要伪装成转写结果。
三级(用户给文件):拿视频语音
要逐句大纲与时间轴(或视频是纯原创口播、搜不到同源文字),只能请用户给视频文件,
走本地文件通道:
"$PY" "$S/extract.py" "D:/微信视频号/某视频.mp4" -o "<工作目录>"
- 自动识别容器/音频格式(mp4/mkv/mov/avi/flv/webm/ts/m4v + mp3/m4a/wav/flac/ogg/opus/amr…)。
- 标题取自文件名,自动剥掉
_1080p/_720p/_hd等下载后缀。 - 若视频旁有同名
.srt/.vtt/.json字幕,直接采用,秒级完成且零识别误差。 - 否则用 PyAV 直接解码视频内的音轨做转写;绝不修改或删除用户的源文件
(只有脚本自己下载的临时音频才会被清理)。 - 默认输出到源文件同级的
extract_out/。 - 无音轨的文件会提前警告,不会白跑一遍 ASR。
怎么让用户拿到文件(按推荐顺序):
1. 微信 PC 端打开视频号 → 播放页 右键 / 更多 → 保存视频;
2. 视频号 → 分享 → 保存到相册,再从手机传到电脑;
3. 导不出来就录屏,录屏文件同样能转写;
4. 桌面端 WeChat Files\...\Finder\ 缓存目录下常留有看过的视频缓存。
> 注意:视频号普遍没有「保存视频」入口,用户常反馈「保存不了,只能分享链接」。
> 遇到这种情况先走二级(同源文字版检索),不要卡在三级的文件获取上。
快手
快手同样没有 extractor,只有本地文件通道这一条路。
对用户可以直接说:链接我能自动抓到文案和热度数据,但视频里的语音拿不到;要完整内容请把视频文件发我。
标准工作流
> 优先用 run.py 一键入口(步骤 0)。只有需要精细控制时才拆成下面的 1→3 步。
步骤 0|一键(推荐,面向非技术用户)
PY="$HOME/.workbuddy/binaries/python/envs/default/Scripts/python.exe"
S="$HOME/.workbuddy/skills/video-info-extract/scripts"
"$PY" "$S/run.py" "<链接 / 分享文案 / 视频文件 / wechat>"
一条命令做完:环境自检(缺依赖自动装、缺模型自动下)→ 提取 → 自动生成基础大纲 → 渲染 Word+Excel。
- 输出位置固定,用户好找:
<当前目录>/视频信息整理/<视频标题>.docx / .xlsx - 中间文件:
<当前目录>/.video_extract/<短标识>/(含outline.json,可改后重渲染) - Agent 写好
outline.json后重出文档:"$PY" "$S/run.py" --render-only - 环境体检:
"$PY" "$S/run.py" --doctor(人话报告,缺什么自动补)
关键设计:即使 Agent 完全不做语义结构化,run.py 也会用转写分段自动生成一份
带时间轴的基础大纲,用户拿到的是一份能直接读的文档,而不是空壳。
Agent 之后再优化 outline.json 重渲染即可 —— 先保证有,再追求好。
步骤 1|提取(需要精细控制时)
"$PY" "$S/extract.py" "<链接或整段分享文案>" -o "<工作目录>"
- 输入可以是纯链接,也可以是
7.68 复制打开抖音,看看【xxx】https://v.douyin.com/xxxx/ ...这种整段口令,脚本会自己抠 URL。 - 需要登录态时加
--cookies-from-browser chrome(或msedge)。 - 长视频怕慢:
--no-asr只拿元数据+字幕;--max-duration 1800限制转写时长。 - 专业名词多的视频加
--hotwords "词1,词2,词3",或维护hotwords.txt(见下节)。 - 产物:
result.json(主)、meta.json、segments.json、transcript.txt、transcript.srt。 - 脚本最后一行输出
__RESULT__{...},直接读它判断成败与来源:
transcript_source是字幕(zh-CN)还是语音转写(faster-whisper:small)。
步骤 2|结构化(Agent 亲自做,不要写规则脚本)
读 result.json → 理解内容 → 写 outline.json。字段规范见 references/outline-schema.md。
硬要求:
- one_liner:一句话说清这条视频到底讲了什么,不写"介绍了…"这种废话。
- key_points:3–8 条,每条是一个可独立成立的判断,不是"第一部分讲了X"。
- outline:必须带时间戳,时间取 segments 里的真实起点;合并碎句,每段 30 s ~ 3 min 有意义的粒度。
- quotes:尽量用原话,不要改写成自己的话;只放真正有信息量或表达力的。
- takeaways:面向用户本人(产品/研发/管理视角)的可执行项,允许为空。
- 原文没有的信息不要编。数据缺失就留空。
步骤 3|渲染
"$PY" "$S/render.py" --data "<工作目录>/outline.json" --outdir "<输出目录>" \
--name "<视频标题>" --transcript "<工作目录>/transcript.txt"
- Word:封面信息表 → 一句话概括 → 摘要 → 核心观点 → 时间轴大纲(表格)→ 金句 → 启发 → 标签 → 转写全文附录。
- Excel:
① 概览/② 内容大纲/③ 观点与启发/④ 金句与标签。 - 产出两个文件后用
present_files一次性呈现,并告诉用户文件落在哪个目录。
步骤 4|交付(可选)
- 本地保存:默认就是本地,把绝对路径给用户。
- 微信/云端传输:按用户要求走腾讯文档(
tencent-docsskill),把 .docx/.xlsx 传上去再给链接。
输出质量:两件必须做的事
这两件事直接决定内容从业者"能不能用",每次都要确认。
一律转简体:Whisper 对中文音频经常输出繁体
实测同一条汽车视频,转写初稿是「驅動橋由主檢宿器…」,整篇不能直接用。
extract.py 已在 normalize_segs() 里统一做 zhconv 繁→简,
字幕通道同样过一遍(港澳台源、部分 UP 主自制字幕也是繁体)。
依赖 zhconv(纯 Python,无负担)。缺失时静默跳过,不阻断主流程。
专业词加术语表:对垂直内容效果极明显
同一条视频,加不加词表差别是"能不能用"级别:
| 转写结果 | |
|---|---|
| 不加词表 | 驱动桥由「主檢宿器」「插宿器」、「万象」传动装置传来的「转距」… |
| 加了词表 | 驱动桥由「主减速器」「差速器」、「万向」传动装置传来的转矩… |
词表位置:<skill>/hotwords.txt(每行一个词,# 注释)。
也可以通过 --hotwords "电驱桥,主减速器,差速器" 临时传入。
维护方式:跑一条视频 → 看哪里错了 → 把正确写法补进 hotwords.txt → 下次就准。
这是一件一次投入、长期受益的事,值得在正式使用前先把用户所在领域的词表填好。
必踩的坑
坑 0:转写默认是繁体 / 专业词全是同音错字
见上一节「输出质量」。这两个坑不修,产出对内容从业者就是废稿。
extract.py 已内置繁→简;术语准确率靠 hotwords.txt。
坑 1:hf-xet 导致模型下载 401
HF_ENDPOINT=https://hf-mirror.com 只代理了常规 HTTPS 通道,hf-xet 会绕过镜像直连
cas-server.xethub.hf.co,表现是 401 Unauthorized 或 File reconstruction error。
必须设 HF_HUB_DISABLE_XET=1。脚本里已经写死了,手工下载时别忘。
坑 2:hf-mirror 会间歇性 502
snapshot_download 一次性拉全部文件,中途 502 就整体失败,且不保留进度。
对策:直接 curl 单文件 + -C - 断点续传,落到裸 CT2 目录
models/faster-whisper-<name>/,脚本会优先命中它,不再碰镜像。
B="https://hf-mirror.com/Systran/faster-whisper-small/resolve/main"
for f in config.json tokenizer.json vocabulary.txt model.bin; do
curl -L --retry 5 --retry-all-errors -C - -o "$D/$f" "$B/$f"
done
必需文件只有 4 个:config.json、tokenizer.json、vocabulary.txt、model.bin。
坑 3:pip 装 yt-dlp 要用阿里云源
清华源在本机对 yt-dlp 返回 No matching distribution found(实测)。
用 -i https://mirrors.aliyun.com/pypi/simple/。
坑 4:不要指望 B站一定有字幕
--list-subs 若只列出 danmaku(弹幕),说明 UP 没传字幕,弹幕不是内容文本,
必须走音频转写。脚本会自动判断,别手工跳过 ASR。
坑 5:VAD 会把「非对话类」音频整段判成静音
vad_filter=True 在纯音乐 / 连续演唱 / 背景嘈杂的内容上会输出 0 段,
而且只花 1 秒就"成功"返回,极易被误判为"这视频没内容"。
实测同一条音频:vad=True → 0 段(0.9 s);vad=False → 40 段(56 s)。
脚本已经内置自动兜底:VAD 结果为空时自动关掉 VAD 重跑一遍。
看到日志里出现 VAD 过滤后为空…关闭 VAD 重试 是正常的,不是报错。
坑 6:长视频 ASR 很慢
实测 CPU + small + int8 约 3.5–4× 实时(212 s 音频 ≈ 56 s 转写)。
1 小时视频 ≈ 15 分钟,已经接近前台超时上限。
- >20 min 的视频先告知用户预计耗时。
- >60 min 建议
--no-asr只出元数据+字幕,或--model base换速度。
转写质量提示
- 默认
--lang zh。中英混杂内容保留zh,纯英文改--lang en。 - 出现明显错别字属正常(专有名词、型号、人名最易错)——整理时按上下文纠正,但不要改金句原话,必要时在
transcript_note里注明"转写可能有误"。 --model small是中文质量/速度的平衡点;追求准确可换medium(更慢、需另下模型)。