baoyu-youtube-transcript实战:把视频字幕变成可检索笔记
看完视频再凭记忆写笔记,最容易遗漏时间点、原话和章节边界。baoyu-youtube-transcript 直接从 YouTube InnerTube 获取字幕,必要时回退到 yt-dlp,将原始片段缓存下来,再生成带时间戳的 Markdown 或 SRT。
本文基于固定提交源码核对;案例是操作示例,不是实际登录、抓取或账号测试。未执行安装、网络请求和模型后处理。
一、适用场景与边界
适合公开视频的字幕归档、课程检索、访谈初稿、播客引用和后续翻译。输入可以是完整观看地址、短链接、嵌入地址、Shorts 地址或视频 ID。默认输出文本 Markdown,适合放入 Obsidian;需要导入播放器时选择 SRT。
它依赖视频本身暴露字幕轨道。字幕被关闭、地区限制、视频私有、年龄验证、IP 被阻断,都可能失败。自动生成字幕不是人工校对稿,口音、专有名词、多人轮流讲话尤其需要复核。--speakers 只产生带元数据的原始稿,真正的说话人识别仍需 Agent 读取提示模板后进行 AI 后处理,不能把参数当作声纹识别。
翻译字幕与翻译文章也要分开看:--translate 请求 YouTube 可用的目标语言字幕轨道,结果不等于高质量出版翻译;翻译风格、术语表和审校应交给文章翻译。涉及版权时,只应在合理用途和许可范围内保存、引用和发布。
二、前置依赖与按需安装
需要 Node.js 环境,能够运行 npx bun;脚本默认示例使用 Bun。仓库 README 提供安装入口,本系列另核实 skills CLI 1.7.2 的按需选择参数:
1 | npx skills add jimliu/baoyu-skills --skill baoyu-youtube-transcript --agent codex |
按需安装或项目级放置 baoyu-youtube-transcript 完整目录。最新安装不等于固定快照,严格复现本文应使用文末固定提交的源码。运行脚本使用它目录内的 scripts/main.ts。如果直接调用 Bun 不可用,可先让 Agent 检查 bun;SKILL 明确允许用 npx -y bun 解析运行时:
1 | npx -y bun "{baseDir}/scripts/main.ts" "https://www.youtube.com/watch?v=VIDEO_ID" |
源码还核实了回退路径:被 YouTube 阻断时会寻找 yt-dlp,也支持通过 uvx --from yt-dlp yt-dlp 调用;缺失时应由 Agent说明需要何种工具,不能把“脚本自动回退”误写成永远无需安装。若用户授权从浏览器读取 Cookie,可设置 YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER,其值示例可为 chrome、safari、firefox 或 chrome:Profile 1。不要在请求中复制 Cookie 内容。
三、输入与输出
最小输入是视频 URL 或 ID。源码接受多个视频输入,但每个任务仍要逐个验收。主要选项如下:
| 需求 | 已核实选项 | 结果 |
|---|---|---|
| 指定字幕语言优先级 | --languages zh,en,ja |
按顺序请求语言 |
| 查看可用字幕 | --list |
只输出列表,不保存文件 |
| 保留时间戳 | 默认开启 | Markdown 段落含时间范围 |
| 删除时间戳 | --no-timestamps |
纯阅读稿 |
| 章节切分 | --chapters |
按视频描述章节组织 |
| 导出播放器字幕 | --format srt |
输出 .srt |
| 请求目标语言轨道 | --translate zh-Hans |
重新取该语言字幕 |
| 重新抓取 | --refresh |
忽略缓存 |
| 指定目录 | --output-dir DIR |
默认 youtube-transcript |
| 指定文件 | -o PATH |
覆盖默认输出文件路径 |
首次运行会缓存 meta.json、transcript-raw.json、按句切分的 transcript-sentences.json 和 imgs/cover.jpg。输出目录按频道和完整标题生成,并维护 .index.json 便于下次定位。同一视频再次换格式通常不需重抓;改变语言会触发刷新,并可能覆盖同一目录的字幕缓存与输出。要同时保留双语证据,应先备份原目录或为不同语言指定不同的输出根目录。不要把缓存当作最终发布文章,里面可能包含完整字幕与封面文件。
四、可复制的自然语言 Agent 请求
1 | 请使用 baoyu-youtube-transcript 处理这个视频:[完整YouTube URL]。 |
访谈需要后处理时:
1 | 请在字幕下载完成后读取生成的原始 Markdown 和技能目录里的 |
五、操作案例:访谈视频整理为研究笔记
假设你要整理一段公开的 AI 访谈,目标是中文阅读稿,但希望保留英文原声证据。这里演示流程,视频和结果均为操作示例。
- 列出轨道。 先使用
--list,确认存在英文人工字幕或自动字幕。若用户没指定语言,不应直接默认英文后宣称这是最佳轨道。 - 初次生成。 用
--languages en --chapters --speakers生成 Markdown。--speakers会输出元数据、描述、章节和 SRT 式原始字幕,章节来自视频描述时优先使用描述边界。 - 验证缓存。 检查
meta.json的标题、频道、语言与视频相符,打开transcript-raw.json确认片段有text/start/duration,再读生成稿。没有字幕时停止,不用视频描述填充“逐字稿”。 - 说话人后处理。 按提示模板:先从标题、频道和描述找嘉宾,再从主持人问答和自我介绍确认。若后文才揭示姓名,要统一替换前面的标签。每段只留一个
[HH:MM:SS → HH:MM:SS]时间范围。 - 生成中文版本。 如果确有中文字幕轨道,可重新运行
--languages zh-Hans;若只有英文轨道,先保留英文稿,再用翻译按术语表翻译,避免把字幕轨道翻译和出版级翻译混为一谈。 - 进入 Obsidian。 将
transcript.md与imgs/cover.jpg一并放入资料目录,必要时再创建自己的摘要页,通过块引用链接到时间点。Hexo 发布前应清理个人版权备注、检查封面路径并确认转载范围。
六、章节、语言与缓存配置
本技能没有像其他技能那样要求 EXTEND.md。核心偏好通过命令选项表达:--languages、--format、--chapters、--speakers、--translate、--output 和 --output-dir。语言代码必须以 --list 实际结果为准,不要仅凭常见缩写猜测 zh-Hans 是否存在。
章节解析依赖视频描述中的时间戳,例如 0:00 Introduction。没有章节时仍会按句分段,但不会凭空声称原视频有章节。缓存按视频 ID 与频道/标题目录关联;同视频请求其他语言会自动刷新。要复现旧文件,保留当时的 meta.json、原始片段和生成参数记录。
SRT 由原始片段生成,时间边界适合播放器;Markdown 使用句子分段并对 CJK 文本做合并。两者不是同一个分段结果,因此不要用 SRT 的块数去反推 Markdown 段落数。封面只在首次抓取 metadata 时写入 imgs/cover.jpg;它不是内容完整性的证明。
七、验收清单
- [ ] URL 或视频 ID 解析正确,标题和频道对应目标视频。
- [ ] 实际语言与
--list或 metadata 一致。 - [ ] 无字幕、受限或阻断时明确报告,而非用描述冒充字幕。
- [ ] Markdown 时间戳格式统一,SRT 时间轴可被播放器接受。
- [ ] 章节只来自视频描述或明确的主题切分。
- [ ] 说话人标签保留原文,不将推断标签写成事实。
- [ ] 缓存文件与最终稿同目录,封面路径存在时可打开。
- [ ] 进 Obsidian 后内部链接、资源引用和 YAML 没有污染;Hexo 发布前完成版权审查。
八、排错
提示 bot detected。 脚本会尝试备用客户端和 yt-dlp。检查 yt-dlp 或 uvx 是否可用;必要时在用户明确授权下设置浏览器 Cookie 来源。频繁请求可能触发 IP 限制,应等待而不是无限重试。
No transcript found。 先用 --list 查看语言,再尝试其他可用代码。--exclude-generated 与 --exclude-manually-created 不能同时使用,因为会排除全部轨道。
输出像机器切句。 Markdown 以字幕片段按标点和字符长度分配时间;这是格式化策略,不是人工听写。需要高风险引用时,回到视频或原始 SRT 复核。
--speakers 仍没有姓名。 这是预期边界:该选项要求后续 AI 读取 prompts/speaker-transcript.md,且不能为不确定的声音强行命名。
九、相关技能与固定来源
- 网页转 Markdown:网页正文或视频页面描述抓取。
- 文章翻译:对已核验的字幕做术语一致翻译。
- Markdown 排版:整理自己的二次笔记而不改原字幕。
- Markdown 转 HTML:把整理稿输出为含样式的 HTML。
固定源码提交:1567581c26ec29f4216c6e6835415bf30343b0e3。





