视频转写 + 学习总结管线
一句话:给一条视频链接(或本地视频/音频文件),产出文档——中文视频 逐字稿.md + 学习总结.md;外语原声再加一份 中文译稿.md(总结帮读者 5 分钟掌握视频精华)。
输入三种都支持:
- 链接(B站/抖音/头条/YouTube 等):自动下载 → 转写
- 本地文件(mp4/mov/mp3/m4a/wav/flac 等,直接给路径):免下载,直接抽音轨 → 转写,更快
- 微信转发的视频(不是链接、就是一段视频):本质也是落盘的 mp4,按下面"微信转发视频定位法"找到文件后走本地文件流程
微信转发视频定位法(用户说"微信发来的视频/别人转我的视频"但没给路径时):
- 微信视频缓存的常见落盘位置(按顺序探测):
- 微信 4.x:<盘>:/xwechat_files/<wxid_*>/msg/video/<yyyy-MM>/*.mp4(用户实机在D:/xwechat_files/,多个账号目录都要扫)
- 微信 3.x:<盘>:/WeChat Files/<wxid_*>/FileStorage/Video/<yyyy-MM>/*.mp4
- 不确定盘符就先查C:/Users/<用户>/Documents/与D:/、E:/根目录 - 定位策略:按修改时间最新的 mp4 优先(用户刚转发的必然是最新),排除
_thumb.jpg/纯.jpg;文件名是哈希看不出内容,可用修改时间+大小让用户确认 - 找到后走本地文件流程转写;找到多个候选时列出让用户挑,不要猜
核心策略(省时间的两层架构):
- 先找现成稿——很多热门视频网上已有逐字稿/实录/CC字幕,搜索+校验约 1-2 分钟,命中即免转写
- 找不到才自己转——本地 faster-whisper 批量推理,速度约为常规转写的 2 倍
交付物数量由原声语言决定:中文原声 = 逐字稿 + 学习总结(两份);外语原声 = 原声逐字稿 + 中文译稿 + 学习总结(三份)。缺任何一份,算任务未完成。
⚠️ 硬规则:全部交付物一律简体中文——逐字稿、译稿、学习总结,一个繁体字都不许有:
- 脚本已内置保险:中文转写结果自动经 opencc 繁→简转换(
V2MD_LANG=zh时还额外加简体引导 prompt),不依赖模型自觉 - 命中现成稿/官方字幕若是繁体(港台源常见):交付前必须整体 opencc t2s 转简,并在文档头注明"已由繁体转简体"
- 交付前自查:扫一遍有无繁体独有字(們來歲殘慘殺責齡類裡爲萬與讓視證),有就转掉再交付
第 0 步:环境(仅首次使用,已装好则跳过)
# 1. 建独立 venv(不污染系统 Python)
python -m venv ~/.workbuddy/binaries/python/envs/video2md311
# 2. 装依赖 —— onnxruntime 必须锁 1.19.2(见下方版本警告)
~/.workbuddy/binaries/python/envs/video2md311/Scripts/python.exe -m pip install faster-whisper "onnxruntime==1.19.2" ctranslate2==4.4.0 yt-dlp imageio-ffmpeg opencc-python-reimplemented
⚠️ 版本硬约束(Windows 段错误元凶):
onnxruntime必须 1.19.2——1.30.0 等新版本在部分 Windows 机器上触发 VAD 段错误(曾致批量推理与 VAD 全部崩溃,降级后全部正常)ctranslate24.5+ 在部分机器段错误,锁 4.4.0- 批量推理(约 2 倍速)依赖 VAD,所以 onnxruntime 版本错 = 直接退回慢速模式或崩溃
国内网络注意:模型下载自 HuggingFace,若连接失败设镜像:HF_ENDPOINT=https://hf-mirror.com。模型已缓存后运行时设 HF_HUB_OFFLINE=1 跳过联网检查。
环境变量配置(都有默认值,按需覆盖):
| 变量 | 默认 | 说明 |
|---|---|---|
V2MD_MODEL |
small | tiny/base/small/medium,中文推荐 small(CPU 可跑) |
V2MD_OUT |
./视频转写 |
输出目录 |
V2MD_LANG |
auto | 中文视频建议设 zh(自动加简体引导,避免繁体混杂) |
V2MD_BATCH |
8 | 批量推理 batch 大小;0=禁用批量走顺序模式 |
V2MD_VAD |
1 | 1=开 VAD 过滤(批量模式必须开);若仍段错误设 0 重试 |
V2MD_KEEP_VIDEO |
0 | 1=保留下载的临时文件 |
工作流程(7 步)
Step 1 元信息探测(不下载)
python scripts/video2md.py --spot "<视频URL>" --dur 1 # 只取元信息
拿到:标题、作者、时长。这三个数据是后续校验的依据,先拿到再动手。
Step 2 找现成逐字稿(按优先级三路)
- 平台 CC 字幕(最准,有就直接用):B 站等站点 yt-dlp 可取
--write-subs --sub-langs all,命中官方字幕直接转 Markdown,跳到 Step 3 校验后交付 - 全网搜索现成稿:WebSearch 搜索词组合:
-"<视频标题>" 逐字稿/"<视频标题>" 文字稿/"<视频标题>" 全文/"<视频标题>" 实录
- 名人访谈加:<人名> <活动名> transcript/<人名> 对话 全文
- 注意识别:视频简介里自带的"文字稿"链接、UP主置顶评论的图文版、公众号转载的实录 - 都没有 → 跳到 Step 5 全量转写
Step 3 校验协议(防乌龙核心,必做)
搜到候选稿 ≠ 就是这个视频。同名不同场、合集片段、AI 洗稿版都存在。两级校验:
L1 元信息比对(免费,先做):
- 标题关键词与视频标题重合
- 时长一致(±30 秒内)——删减版/精华版在这里直接现形
- 作者/主讲人一致
L2 内容抽头校验(约 1-2 分钟):
# 只下载开头 60 秒音频(约1MB,几秒下完)+转写(约30秒)+与候选稿模糊比对
python scripts/video2md.py --spot "<视频URL>" --dur 60 --compare <候选稿.md>
判定(输出 JSON 的 verdict 字段):
| similarity | verdict | 处置 |
|---|---|---|
| ≥ 0.50 | match | 命中,采用 |
| 0.25 - 0.50 | unsure | 换中段再抽一次(--start 时长/2),两处有一处 ≥0.5 即命中 |
| < 0.25 | no_match | 不采用,换下一候选或走转写 |
额外铁律:L1 时长对不上 → 直接 no_match,不做 L2;多个候选逐一校验取最高分;候选稿明显比视频短很多(>20%)→ 可能是删减版,交付时如实标注。
实测基准:同源稿 0.956 / 无关稿 0.041,区分度充足。
Step 4 命中现成稿的交付
- 逐字稿文档头注明:
> **来源**: 网络公开逐字稿(已通过开头内容校验,与原视频比对相似度 0.xx)——不要写"AI 转写" - 若是繁体(港台源常见):必须先整体转简体再交付(opencc t2s),文档头注明"已由繁体转简体"
- 照常做 Step 6(译稿,如外语)/ Step 7(学习总结)/ Step 8(交付)
Step 5 全量转写(未命中时)
# 全量转写(未命中时);本地文件直接给路径即可,免下载
# 中文视频务必设 V2MD_LANG=zh(简体引导);批量推理默认开启,约为常规速度2倍
V2MD_LANG=zh python scripts/video2md.py "<视频URL 或 本地文件路径>" [输出目录]
- yt-dlp 失败时按平台路由兜底(详见下方"平台路由"),拿到文件后参照脚本内部流程
- 速度参考:批量推理约 1x 实时或更快(CPU;常规顺序模式约 0.5x)。42 分钟视频约 20-40 分钟出稿
- 转写进程若仍段错误:
V2MD_VAD=0重跑(自动降级顺序模式)
Step 6 写中文译稿 《标题》_中文译稿.md(⚠️ 仅外语原声时必做)
- 判定:转写完成后先判断语言。中文原声 → 跳过本步;外语(英/日/韩…)→ 本步必做
- 做法:将外语逐字稿完整翻译成中文,按约 60 秒分段,段首
**[HH:MM:SS]** - 忠实度要求:翻译按原话直译,保留口头语与重复;专业术语首次出现时括注原文(如"每瓦 token 数(tokens per watt)")
- 一句话开头注:说明"由原声逐字稿全文翻译,非字幕、非官方译文"
Step 7 写学习总结 《标题》_学习总结.md(⚠️ 必做)
严格按 references/学习总结模板.md 生成,核心要求:
- 全文简体中文(硬规则,繁体字零容忍)
- 结构:一句话核心 → 适合谁看/含金量 → 内容时间轴 → 核心观点(3-6条) → 金句摘录 → 行动建议 → 存疑与补充
- 所有观点必须能在逐字稿中找到出处,引用带时间戳,禁止编造
- 含金量如实评——烂视频直说不值得看,总结的价值是帮人省时间
- 全文 600-1200 字
- 总结单独成文件,不与逐字稿混排
Step 8 交付回复
- 向用户回:一句话核心 + 3-5 句内容摘要 + 全部文件路径 + 用时(注明"找到现成稿"还是"本地转写")
- 长视频(≥5 分钟)在动手时先回执:"收到,XX 分钟视频,正在处理,预计 N 分钟出稿"
- 微信等即时通道场景:摘要即回复正文,文件路径附后
平台路由(下载兜底顺序)
| 平台 | 路由 |
|---|---|
| B站/西瓜/YouTube 等多数站点 | yt-dlp 直下(scripts/video2md.py 一步到位) |
| 抖音 | yt-dlp 已失效(API 需 a_bogus 签名)→ 浏览器流程① |
| 头条 | yt-dlp 不支持 → 浏览器流程②(音视频分离,只下音频) |
| 其他失败 | 浏览器流程①兜底 |
浏览器流程①(需 agent-browser/playwright 类工具可用):
open "<视频URL>",等待 6-8 秒自动起播eval "document.querySelector('video').currentSrc"取直链(若空先eval "document.querySelector('video').play()")- 带 UA +
Referer: <站点首页>下载全片(抖音直链含音轨,单文件) - → Step 5
浏览器流程②(头条,音视频分离流):
- 打开页面等起播(currentSrc 是 blob: 无用)
eval "JSON.stringify(performance.getEntriesByType('resource').map(r=>r.name).filter(u=>u.includes('media-audio')))"挖音频直链- 带 UA + Referer 下载音频全量(16MB 级,无需下视频)
- → Step 5
浏览器工具卡死急救:杀 agent-browser 主进程 + 用 wmic process where "name='chrome.exe'" get processid,commandline 找出带 agent-browser 标记的僵尸 chrome 子进程一并杀掉(曾见 12 个僵尸导致工具假死)。
故障排查速查
| 症状 | 处置 |
|---|---|
| 转写/VAD 段错误(Segmentation fault) | 先查 pip show onnxruntime——必须 1.19.2,新版本是元凶;装对版本后批量推理可用(约2倍速)。应急再设 V2MD_VAD=0(自动降级顺序模式) |
| 批量转写报错 | 脚本自动降级顺序模式并打 warn,可继续;或设 V2MD_BATCH=0 |
| 模型下载连接失败 | 设 HF_ENDPOINT=https://hf-mirror.com;已缓存则设 HF_HUB_OFFLINE=1 |
| yt-dlp 报 Fresh cookies / 403 | 该站点已被反爬挡住 → 走浏览器兜底流程 |
| 抖音 requests 直抓返回空壳页 | 正常(JS 挑战),requests 路线对抖音全线无效,必须真浏览器 |
| 页面 video.currentSrc 为空 | 先触发播放再取;再不行等 10 秒重试 |
| 中文转写出繁体 | 设 V2MD_LANG=zh(自动加简体引导 prompt);已产出文档可用 opencc 统一转简 |
边界与如实说明
- 逐字稿是语音转写:无原声的纯字幕视频转不出来 → 需抽帧 OCR,本技能暂不含(可按画面 OCR 方案扩展)
- 平台 CC 字幕:B站部分视频 yt-dlp 可直接取
--write-subs,有则优先用官方字幕(比转写更准,也免转写耗时) - 转写耗时:批量推理下约等于视频时长(CPU),GPU 环境可换
device='cuda'提速 10 倍+ - small 模型专有名词偶有同音错字(如"反思"→"访施"),交付时声明"未润色";对准确性要求高的场景可换
V2MD_MODEL=medium(约慢1倍)
隐私与上架说明
- 全程本地推理,音视频数据不出本机
- 本技能不收集任何用户数据,不依赖任何特定个人的 cookie/路径
- 上架市场前自查:SKILL.md 无危险指令、脚本无外传行为、无硬编码个人路径