视频笔记 VidNotes(视频转文字 + 学习笔记)
何时使用
- 用户发来一个视频文件(.mp4/.mkv/.mov/.webm/.avi 等)或视频链接(B站/YouTube 等),希望获取其中文字内容。
- 触发词:学这个视频、提取字幕、视频转文字、视频逐字稿、把视频变成笔记、看视频、这视频讲了啥。
- 合集/播放列表:提供
scripts/collection.py,一条命令把整个合集逐集处理成字幕稿+笔记并自动合并总笔记。内置集间限速 + 重试退避(规避 B站短时限流,见踩坑 #11),中断可续跑。详见下方「合集 / 播放列表批量处理」。
本质说明
视频对文本模型不是直接可读对象,必须先转成文字(字幕/转写稿)或图片(关键帧)。本 skill 走"文字"路线:
字幕自动优先级链 —— 网络字幕(B站/AI,需登录) → 内嵌字幕 → 语音转写。能拿到字幕就零误差,拿不到就跑 whisper。理解视频靠这份文字稿,不是"看画面"。
前置依赖(路径全部可移植,分发无需改代码)
- ffmpeg:脚本自动定位,顺序为
bin/ffmpeg.exe(skill 自带)→ 本机历史路径 → imageio-ffmpeg 自带二进制。分发版把 ffmpeg.exe 放bin/即可。 - Python venv(含 faster-whisper / imageio-ffmpeg / soundfile / hanziconv / jieba / yt-dlp):调用时用该 venv 的 python。下文以
<VENV_PYTHON>指代。 - 模型:默认
models/small(精度高,推荐);--fast用models/tiny(快速)。均可本地化,无需联网。 - GPU 加速(可选):本机装好 CUDA 12 运行时(如
pip install nvidia-cublas-cu12 nvidia-cuda-runtime-cu12 nvidia-cudnn-cu12 nvidia-cuda-nvrtc-cu12),脚本自动检测并走 GPU;无则回退 CPU。
工作流
- 解析输入
- 本地文件:直接用路径。
- URL:若已装yt-dlp,自动下载/取字幕;未装则提示用户提供本地文件。 - 字幕自动优先级链
- URL 输入:先尝试取 B站/平台字幕(登录态下可拿到官方/AI 字幕,零误差);取不到再下载音视频。
- 本地视频:先抽内嵌字幕;没有再抽音轨。
- 抽到字幕则直接转写完成,跳过 whisper。 - 无字幕 -> 语音转写
- 抽音轨:ffmpeg -i in.mp4 -vn -ac 1 -ar 16000 audio_16k.wav
- whisper 转写(默认 small 模型,繁体自动转简体,VAD 去静音),产出三件套:transcript.srt(带时间轴)、transcript.txt(纯文本)、transcript.md(分段)
- 自动生成学习笔记(接 notes.py)
- 产出notes.md:时间线大纲 + 关键词/术语(jieba)+ 可选 LLM 深化摘要。
- 未配置 LLM 时仅做骨架,仍可直接复习。
命令速查(均用 venv 的 python 执行)
- 一站式(默认 small,自动笔记,URL 或本地均可):
<VENV_PYTHON> scripts/transcribe.py --input <视频/音频/URL> --out-dir ./notes --lang zh - 快速档(tiny,更快但精度略低):
<VENV_PYTHON> scripts/transcribe.py --input in.mp4 --out-dir ./notes --fast - B站登录取字幕(见下章):
<VENV_PYTHON> scripts/transcribe.py --input <B站URL> --out-dir ./notes --cookies cookies.txt - 保留下载的临时视频(默认转完即删):加
--keep-video - 不生成笔记:加
--no-notes - 仅用已抓好的字幕出笔记(字幕抓取与转写解耦,适合合集分批 / 失败重试 / 离线复用):
<VENV_PYTHON> scripts/transcribe.py --subtitle ./p3/video.ai-zh.srt --out-dir ./p3_notes
指定一个已存在的 srt/vtt,跳过下载与 whisper 转写,仅做"字幕→学习笔记"。文件不存在会 [ERROR] 显式退出。
B站登录 / Cookie 取字幕(精度最高路径)
B站字幕 API 需登录态。两种方式:
1. --cookies-from-browser edge(推荐但受限):脚本读 Edge 本地 cookie。
⚠️ 已实测:Windows 新版 Edge 用 App-Bound Encryption,Python 进程用 DPAPI 解密会失败(Failed to decrypt with DPAPI)。本机暂不可用。
2. --cookies cookies.txt(最可靠):在 Edge 装 Cookie-Editor 插件 → 打开 bilibili.com 登录页 → 导出该站 cookie 为 Netscape/文本格式 → 存成 cookies.txt → 传给 --cookies。
此方式明文、绕开 DPAPI,实测稳定。文件含登录凭证,不要外传、用完即删。
- 拿到字幕即零误差;若该视频本就无字幕轨(UP主未传、B站未生成 AI 字幕),登录也取不到,自动回退语音转写。
合集 / 播放列表批量处理(collection.py)
整集合集/播放列表(B站分P教程、YouTube playlist 等)一键逐集出笔记,并合并成一份总笔记。
脚本会自动:①先集中抓每集字幕(带集间限速 + 重试退避,规避 B站短时限流);②有字幕的集用 --subtitle 直接出笔记(快、英文例句保真);③只有彻底抓不到字幕的集才回退 whisper 转写;④已生成的集会跳过,中断可续跑。
- 基本用法(B站合集需登录,传 cookie):
<VENV_PYTHON> scripts/collection.py \ --url "https://www.bilibili.com/video/BVxxxx/" \ --out-dir ./notes \ --cookies cookies.txt \ --lang zh - 只补跑失败的某几集(断点续跑 / 限流恢复后补抓):
<VENV_PYTHON> scripts/collection.py \ --url "https://www.bilibili.com/video/BVxxxx/" \ --out-dir ./notes --cookies cookies.txt \ --only 17,18 - 不合并总笔记:加
--no-merge。 - ⚠️ cookie 用完请手动删除(脚本不会擅自删你的文件)。若遇 B站短时限流导致某集字幕抓取失败,等限流窗口过了(约 10 分钟,按会话计)用
--only <集号>重跑那几集即可。 - 输出结构:
./notes/p1/…pN/每集一个目录(含transcript.*+notes.md),根目录生成总笔记.md。
GPU 加速
- 脚本
enable_cuda()会把 venv 内nvidia/*/bin加入 PATH,再检测cublas64_*.dll决定走cuda还是cpu。 - 安装运行时(一次性):
<VENV_PYTHON> -m pip install nvidia-cublas-cu12 nvidia-cuda-runtime-cu12 nvidia-cudnn-cu12 nvidia-cuda-nvrtc-cu12 - 若 CUDA 加载失败(如 cuDNN 版本不符),脚本自动回退 CPU 并
[WARN]提示,不影响结果。 - 可用环境变量
VIDNOTES_DEVICE=cpu|cuda强制指定。
模型与网络
- 模型已可本地化(
models/tiny随包;models/small见下),默认无需联网。 - 拉取 small 模型(约 460MB,走 hf-mirror 镜像,代理可达):
BASE="https://hf-mirror.com/Systran/faster-whisper-small/resolve/main" DIR="models/small"; mkdir -p "$DIR" for f in config.json model.bin tokenizer.json vocabulary.txt; do curl -L --retry 3 -o "$DIR/$f" "$BASE/$f"; done
之后可省略--model,脚本默认即 small。
分发与上架
- 所有路径已相对化/自动探测,直接打包
video-to-notes/目录即可分发。 - 离线即跑版:
bin/ffmpeg.exe+models/tiny/已随包,他人pip install依赖后即可用 tiny 模型离线运行。 - 上架 SkillHub 等市场:SKILL.md frontmatter(name/slug/displayName/version 等)即展示信息。
常见问题 / 踩坑记录(开发者实测,避免重蹈覆辙)
本技能在 Win11 + GTX1650 + Edge 登录态下实测踩过以下坑,均已修复并内置防护;列出供排错与二次开发参考。
1. 模型下载:huggingface.co 直连 502 / GitHub TLS 失败
- 现象:
curl https://huggingface.co/...返回 502,拉 GitHub 报 TLS handshake failed。 - 原因:出网走代理,部分域名被挡。
- 解决:模型权重改走镜像
https://hf-mirror.com/Systran/faster-whisper-<model>/resolve/main,手动下载四件套(config.json / model.bin / tokenizer.json / vocabulary.txt)放进models/<model>/。脚本已默认优先读本地models/,无需联网。
2. PyAV 19 移除 metadata_errors 参数 → faster-whisper 导入即崩
- 现象:
import faster_whisper直接 TypeError,报metadata_errors未知参数。 - 原因:PyAV 19 删掉了
av.open(..., metadata_errors=...),faster-whisper 仍在调用。 - 解决:脚本在导入 faster_whisper 之前猴子补丁
av.open自动弹出该参数(已内置)。也可锁av<19,但补丁更省事。
3. CUDA 路径算错 → GPU 不生效(回退 CPU)
- 现象:
enable_cuda()找不到 cuBLAS,始终走 CPU。 - 原因:venv 内层目录层数算错(多套一层 Scripts)。
- 解决:正确路径是
<venv>/Lib/site-packages/nvidia/<pkg>/bin,脚本已修正,加入 PATH 后由cublas64_*.dll实测决定是否启用 GPU。
4. Windows 新版 Edge --cookies-from-browser edge 解密失败
- 现象:
yt-dlp --cookies-from-browser edge报Failed to decrypt with DPAPI。 - 原因:Win11 新版 Edge 启用 App-Bound Encryption,外部进程用 DPAPI 解不出 cookie。
- 解决(最稳):Edge 装 Cookie-Editor 插件 → 打开 bilibili.com(已登录)→ 点插件"导出"→ 选 Netscape 格式 / 存为文件 → 把文件传给
--cookies cookies.txt。不要用--cookies-from-browser(本机实测不可用)。
5. 记事本保存 cookie 带 UTF-8 BOM → yt-dlp 不认
- 现象:cookie 文件有内容,yt-dlp 仍拿不到登录态。
- 原因:Windows 记事本另存为 UTF-8 会加 BOM(
),yt-dlp 解析失败。 - 解决:用 VS Code / 任意编辑器存为 UTF-8 无 BOM,或
python -c "open('cookies.txt','w',encoding='utf-8').write(txt)"。脚本不读 cookie 内容,只透传给 yt-dlp。
6. SRT 时间戳 float("00:00:00.000") 崩溃
- 现象:解析某些字幕时
ValueError: could not convert string to float。 - 原因:旧代码直接
float(timestamp),而 SRT 是HH:MM:SS,mmm格式。 - 解决:用
_ts_to_sec()解析(HH:MM:SS,mmm/.mmm/MM:SS.mmm都兼容),已内置。
7. 字幕误选 bug:把 whisper 产物当字幕源
- 现象:目录既有真字幕又有历史
transcript.srt时,按字母序取到transcript.srt,出现"两份一模一样"的假象。 - 解决:
_pick_subtitle()排除transcript.*自身产物、优先ai-zh/最新修改的字幕,已内置。
8. B站 AI 字幕不是"零误差"金标准
- 现象:以为取到 B站字幕就 100% 准确,实测 AI 字幕也会错(如"富婆"→"父婆")。
- 认知:B站官方/AI 字幕的价值是比 whisper 更准 + 快得多(省去转写),但本身仍有识别误差,重要文本建议人工复核。
9. SkillHub 发布 403 → 未实名
- 现象:
publish返回 403 Forbidden。 - 解决:先去平台完成实名认证,再发布。
10. Cookie-Editor "导出到剪贴板"只复制了提示语
- 现象:点了导出,剪贴板里是一句
Cookies exported to clipboard as Netscape format,并非真正的 cookie。 - 解决:用插件的 "导出为文件"(或确认剪贴板是真正的 Netscape 文本:以
# Netscape HTTP Cookie File开头、每行含bilibili.com ... SESSDATA=...),再传给--cookies。
11. B站短时限流(频控)——批量抓字幕被临时拦
- 现象:带 cookie 登录态短时间内高频请求字幕(例如脚本循环抓 18 集),约 10 分钟内反复请求会触发 B站临时频控,表现为取字幕静默失败、自动回退 whisper 转写(白跑还拿不到准确字幕)。
- 诊断特征:隔开几分钟、单独跑一次又能成功;不是 cookie 失效、不是命令错(实测隔开窗口后即可拿到
ai-zh.srt)。 - 解决(批量/合集场景):①集与集之间加延时(建议 3–5 秒);②失败退避重试(如 20/40/60 秒);③复用已抓到的字幕(用
--subtitle直接喂已下载的字幕,跳过重复抓取)。单次使用一般遇不到。 - 脚本现会在取字幕失败时打印
[WARN] 取字幕失败(可能 B站短时限流 / ...)并暴露 yt-dlp 末行错误,便于区分"限流"还是"真无字幕"。
12. 字幕抓取与转写"解耦"——新增 --subtitle 参数
- 背景:早期把"抓字幕"和"做笔记"绑死在一次运行里;一旦取字幕失败就静默回退 whisper,用户拿到的是中文音译的英文例句、还不知道出了错。
- 解决:新增
--subtitle <file.srt|.vtt>参数,直接吃一个已抓好的字幕文件,跳过下载与转写、仅做"字幕→学习笔记"。配合"先批量抓字幕、再逐集--subtitle出笔记"的流程,把两支彻底分开,避免重复下载/转写、也便于对失败集单独重试。 - 用法见「命令速查」最后一条。
13. 超长音频 VAD 内存溢出(OOM)——分段转写兜底
- 现象:10 小时录播类视频,开
vad_filter=True被整段判为非语音返回空;早期回退逻辑直接vad_filter=False整段重转,faster-whisper 一次性把整段 STFT,np.fft.rfft要分配 ~5.4 GiB 数组直接_ArrayMemoryError崩掉。 - 根因:faster-whisper 无 VAD 时不分块,整段音频进 STFT 撑爆内存。
- 解决(v1.2.1):
transcribe()在 VAD 返回空(或捕获MemoryError)时,改走chunked_transcribe()——用 ffmpeg 按 30 分钟一段切片、逐段vad_filter=False转写、再把时间戳偏回原坐标合并。普通短视频不受影响(VAD 命中即直接出结果),仅超长/无语音轨视频走分段兜底。
版本历史
- 1.2.1(2026-10-07):修复超长音频 VAD 回退 OOM——改为分段切片转写兜底(
chunked_transcribe)。 - 1.2.0(2026-10-07):新增
collection.py合集/播放列表批量处理(集间限速 + 重试退避 + 断点续跑 + 自动合并总笔记)。 - 1.1.3(2026-10-07):
--subtitle解耦字幕与笔记;取字幕失败显式[WARN]并暴露 yt-dlp 末行(不再静默回退 whisper);补 B站短时限流踩坑。 - 1.1.2(2026-10-07):补充开发者实测踩坑文档(#1–#11)。
- 1.1.1 / 1.1.0:初始可用版(字幕优先级链 + whisper + 自动笔记)。
安全与隐私须知(发布前必读)
- 本技能纯本地运行:转写/字幕解析全在用户本机完成,脚本不向任何外部服务器回传数据(除用户主动用
--cookies访问 B站/yt-dlp 本身是正常网页请求外,无任何"回调/上报"到作者本人)。 - 绝不随包分发你的凭证:
cookies.txt、SKILLHUB_TOKEN(skh_...) 等敏感文件不要放进 skill 目录。已核验当前发布包不含任何 cookie / key / 个人路径。 - cookie 用完即删:
cookies.txt含 B站登录态,仅供本机本次使用;用完建议退出 B站登录使 SESSDATA 失效,切勿把它打包分享。 - 代码不含硬编码个人路径:早期版本残留的
C:/Users/<user>/...本地路径已移除,改为相对/自动探测,避免泄露本机用户名。 - 视频默认下载到本机工作目录、转完即删(
--keep-video可保留),不传到任何地方。
重装依赖
python3 -m venv .venv
.venv/Scripts/pip install faster-whisper imageio-ffmpeg soundfile hanziconv jieba yt-dlp
# 取得 ffmpeg 二进制(脚本也可自动用 imageio-ffmpeg 自带的,无需这一步)
python -c "import imageio_ffmpeg,shutil,os;exe=imageio_ffmpeg.get_ffmpeg_exe();os.makedirs('bin',exist_ok=True);shutil.copy(exe,'bin/ffmpeg.exe')"
# 可选 GPU
.venv/Scripts/pip install nvidia-cublas-cu12 nvidia-cuda-runtime-cu12 nvidia-cudnn-cu12 nvidia-cuda-nvrtc-cu12