内容翻译
- 作者仓库星标 21,713
- 叉子 2,492
- 作者更新于 2026年6月13日 05:00
- 作者仓库 baoyu-skills
- 领域
- 设计与多媒体
- 兼容 Agent
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- 信任分
- 92 / 100 · 已通过审计
- 作者 / 版本 / 许可
- @JimLiu · v1.1.0 · 未声明 license
- Token 消耗评级
- 低消耗
- 接入复杂程度
- 需简单配置
- 是否需要外部 API Key
- 需要 · Vendor-specific
- 兼容的系统
- macOS · Linux · Windows
- 底层运行要求
- Bun
- 文件与系统权限
-
- 只读
- 允许写入 / 修改
- Shell 执行
- 读取环境变量
- 网络行为
- 允许外网请求
- 安装命令数
- 26 条
档案由构建时根据 SKILL.md 与安装命令自动衍生,可能与作者实际意图存在差异。
需要注意: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: baoyu-youtube-transcript
description: Downloads YouTube video transcripts/subtitles and cover images by URL or video ID. Supports mult…
category: 设计与多媒体
runtime: Bun
---
# baoyu-youtube-transcript 输出预览
## PART A: 任务判断
- 适用问题:视觉内容、演示材料、信息图或设计交付。
- 输入要求:目标材料、限制条件、期望输出和验收方式。
- 证据边界:围绕“Script Directory / Usage / Options”读取原文规则,不把推断写成作者承诺。
## PART B: 执行结果
- **01** 任务判断:确认你的需求是否属于视觉内容、演示材料、信息图或设计交付,并标出输入、限制和预期结果。
- **02** 执行计划:优先按“Script Directory / Usage / Options”拆成步骤,说明每一步会读取什么、修改什么、产出什么。
- **03** 交付结果:给出可复制的命令、文件改动、检查清单或内容草稿,并说明如何继续迭代。
- **04** 风险边界:结合 读取文件、写入/修改文件、执行终端命令、读取环境变量、会按任务需要访问外部网络、需要准备 Vendor-specific API Key 给出执行前确认项。
## Running Rules
- 读取文件、写入/修改文件、执行终端命令、读取环境变量;会按任务需要访问外部网络;需要准备 Vendor-specific API Key。
- 先小样例验证,再放大到真实任务。
- 交付时同时给结果、检查口径和下一步迭代建议。 原文没有稳定的斜杠命令要求。安装验证后通常全局生效,直接在对话里点名这个 Skill 并描述任务即可。
告诉 Agent 目标文件或材料、期望结果、不可改范围、是否允许联网或执行命令。本 Skill 的权限画像是:读取文件、写入/修改文件、执行终端命令、读取环境变量。
先用一个小任务确认它会围绕“Script Directory / Usage / Options”工作;涉及文件或命令时,先看 diff、日志、预览或测试结果。
检查最终产物是否包含明确结果、必要证据和下一步动作;如果输出泛泛而谈,就补充输入、边界和验收标准后重跑。
---
name: baoyu-youtube-transcript
description: Downloads YouTube video transcripts/subtitles and cover images by URL or video ID. Supports mult…
category: 设计与多媒体
source: JimLiu/baoyu-skills
---
# baoyu-youtube-transcript
## 什么时候使用
- 给 YouTube 链接就把字幕和封面下载下来整理成可用文本——原始时间戳保留 适合处理界面、视觉、封面、信息图或演示材料交付,核心价值是把输入、判断、执行、验证和交付边界固定下来,避免 Agent 泛泛回答。 把任务拆成可执行、可检查…
- 面向视觉内容、演示材料、信息图或设计交付,优先处理能明确输入、步骤和验收标准的工作。
## 需要提供什么
- 目标材料、目录范围、期望结果和不可改动内容。
- 是否允许联网、执行命令、读写文件或调用外部服务。
## 执行规则
- 围绕「Script Directory / Usage / Options」组织步骤,不把推断写成作者事实。
- 读取文件、写入/修改文件、执行终端命令、读取环境变量;会按任务需要访问外部网络;需要准备 Vendor-specific API Key。
- 先跑小样例,确认结果可检查后再扩大任务范围。
## 输出要求
- 给出最终产物、关键证据、验证方式和下一步动作。
- 信息不足时标记 unknown,不编造命令、平台或依赖。 作者原文负责流程事实;仓库文件负责来源和命令;流狐只补充适用场景、限制和质量判断。
skill "baoyu-youtube-transcript" {
输入层 -> 用户目标 + 目标文件 + 禁止范围 + 验收标准
上下文层 -> Script Directory / Usage / Options
规则层 -> SKILL.md 触发条件 / 执行顺序 / 输出格式
运行层 -> Bun | 读取文件、写入/修改文件、执行终端命令、读取环境变量 | 会按任务需要访问外部网络
安全层 -> 需要准备 Vendor-specific API Key + 小任务验证 + diff / 日志复核
输出层 -> 可复制结果 + 检查清单 + 下一步迭代
} YouTube 字幕
下载 YouTube 视频的字幕(subtitles/captions)。支持手动创建和自动生成的字幕。无需 API 密钥或浏览器——直接使用 YouTube 的 InnerTube API,当 YouTube 阻止直接 API 路径时,会自动回退到 yt-dlp。
首次运行时获取视频元数据和封面图片,缓存原始数据以便快速重新格式化。
脚本目录
脚本位于 scripts/ 子目录中。{baseDir} = 此 SKILL.md 的目录路径。解析 ${BUN_X} 运行时:如果安装了 bun → bun;如果 npx 可用 → npx -y bun;否则建议安装 bun。将 {baseDir} 和 ${BUN_X} 替换为实际值。
| 脚本 | 用途 |
|---|---|
scripts/main.ts |
字幕下载 CLI |
用法
# 默认:带时间戳的 Markdown (英文)
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>
# 指定语言(优先级顺序)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja
# 不带时间戳
${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps
# 带章节分割
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters
# 带说话人识别(需要 AI 后处理)
${BUN_X} {baseDir}/scripts/main.ts <url> --speakers
# SRT 字幕文件
${BUN_X} {baseDir}/scripts/main.ts <url> --format srt
# 翻译字幕
${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans
# 列出可用字幕
${BUN_X} {baseDir}/scripts/main.ts <url> --list
# 强制重新获取(忽略缓存)
${BUN_X} {baseDir}/scripts/main.ts <url> --refresh
选项
| 选项 | 描述 | 默认值 |
|---|---|---|
<url-or-id> |
YouTube URL 或视频 ID(允许多个) | 必填 |
--languages <codes> |
语言代码,逗号分隔,按优先级顺序 | en |
--format <fmt> |
输出格式:text, srt |
text |
--translate <code> |
翻译到指定语言代码 | |
--list |
列出可用字幕而不是获取 | |
--timestamps |
每段包含 [HH:MM:SS → HH:MM:SS] 时间戳 |
开启 |
--no-timestamps |
禁用时间戳 | |
--chapters |
从视频描述中获取章节分割 | |
--speakers |
带有元数据的原始字幕,用于说话人识别 | |
--exclude-generated |
跳过自动生成的字幕 | |
--exclude-manually-created |
跳过手动创建的字幕 | |
--refresh |
强制重新获取,忽略缓存数据 | |
-o, --output <path> |
保存到特定文件路径 | 自动生成 |
--output-dir <dir> |
基本输出目录 | youtube-transcript |
可选环境变量
| 变量 | 描述 |
|---|---|
YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER |
在回退时传递给 yt-dlp --cookies-from-browser,例如 chrome, safari, firefox, 或 chrome:Profile 1 |
输入格式
接受以下任何一种作为视频输入:
- 完整 URL:
https://www.youtube.com/watch?v=dQw4w9WgXcQ - 短 URL:
https://youtu.be/dQw4w9WgXcQ - 嵌入 URL:
https://www.youtube.com/embed/dQw4w9WgXcQ - Shorts URL:
https://www.youtube.com/shorts/dQw4w9WgXcQ - 视频 ID:
dQw4w9WgXcQ
输出格式
| 格式 | 扩展名 | 描述 |
|---|---|---|
text |
.md |
带有 frontmatter(包括 description)、标题、摘要、可选的目录/封面/时间戳/章节/说话人的 Markdown |
srt |
.srt |
适用于视频播放器的 SubRip 字幕格式 |
输出目录
youtube-transcript/
├── .index.json # 视频 ID → 目录路径映射(用于缓存查找)
└── {channel-slug}/{title-full-slug}/
├── meta.json # 视频元数据(标题、频道、描述、时长、章节等)
├── transcript-raw.json # 来自 YouTube API 的原始字幕片段(已缓存)
├── transcript-sentences.json # 句子分割的字幕(按标点符号分割,跨片段合并)
├── imgs/
│ └── cover.jpg # 视频缩略图
├── transcript.md # Markdown 字幕(从句子生成)
└── transcript.srt # SRT 字幕(从原始片段生成,如果 --format srt)
{channel-slug}:频道名称,采用 kebab-case 格式{title-full-slug}:完整视频标题,采用 kebab-case 格式
--list 模式仅输出到标准输出(不保存文件)。
缓存
首次获取时,脚本会保存:
meta.json— 视频元数据、章节、封面图片路径、语言信息transcript-raw.json— 来自 YouTube API 的原始字幕片段 ({ text, start, duration }[])transcript-sentences.json— 句子分割的字幕 ({ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]),按句末标点符号(.?!…。?!等)分割,时间戳按字符长度按比例分配,支持 CJK 文本合并imgs/cover.jpg— 视频缩略图
同一视频后续运行将使用缓存数据(无需网络调用)。使用 --refresh 强制重新获取。如果请求不同的语言,缓存会自动刷新。
当 YouTube 在直接 InnerTube 路径上返回反机器人/阻止响应时,脚本会使用备用客户端身份重试,如果可用,则回退到 yt-dlp。如果需要回退但 yt-dlp 不可用,Agent 应该决定如何使 yt-dlp 可用并继续,而不是将安装决定推给用户。
SRT 输出 (--format srt) 从 transcript-raw.json 生成。文本/Markdown 输出使用 transcript-sentences.json 来实现自然的句子边界。
工作流程
当用户提供 YouTube URL 并想要字幕时:
- 如果用户未指定语言,请先使用
--list运行,以显示可用选项 - 运行脚本时始终用单引号引用 URL——zsh 将
?视为全局通配符,因此未引用的 YouTube URL 会导致“未找到匹配项”:使用'https://www.youtube.com/watch?v=ID' - 默认:使用
--chapters --speakers运行以获得最丰富的输出(章节 + 说话人识别) - 脚本会自动保存缓存数据 + 输出文件并打印文件路径
- 对于
--speakers模式:脚本保存原始文件后,按照下面的说话人识别工作流程进行后处理,添加说话人标签
当用户只想要封面图片或元数据时,使用任何选项运行脚本也会缓存 meta.json 和 imgs/cover.jpg。
重新格式化同一视频时(例如,先文本后 SRT),会重用缓存数据——无需重新获取。
章节和说话人工作流程
章节 (--chapters)
脚本从视频描述中解析章节时间戳(例如,0:00 Introduction),按章节边界分割字幕,将片段分组为可读的段落,并保存为带有目录的 .md 文件。无需进一步处理。
如果描述中没有章节时间戳,字幕将输出为分组段落,不带章节标题。
说话人识别 (--speakers)
说话人识别需要 AI 处理。脚本输出一个原始的 .md 文件,其中包含:
- 带有视频元数据(标题、频道、日期、封面、描述、语言)的 YAML frontmatter
- 视频描述(用于提取说话人姓名)
- 描述中的章节列表(如果可用)
- SRT 格式的原始字幕(预计算的开始/结束时间戳,token 效率高)
脚本保存原始文件后,启动一个子 Agent(使用更便宜的模型,如 Sonnet,以节省成本)来处理说话人识别:
- 读取保存的
.md文件 - 读取
{baseDir}/prompts/speaker-transcript.md处的提示词模板 - 按照提示词处理原始字幕:
- 使用视频元数据(标题 → 嘉宾,频道 → 主持人,描述 → 姓名)识别说话人
- 从对话流程、问答模式和上下文线索中检测说话人轮次
- 分割成章节(如果描述中有章节则使用,否则根据主题转换创建)
- 格式化为
**说话人姓名:**标签、段落分组(2-4 句话)和[HH:MM:SS → HH:MM:SS]时间戳
- 用处理后的字幕覆盖
.md文件(保留 YAML frontmatter)
当使用 --speakers 时,--chapters 是隐含的——处理后的输出始终包含章节分割。
错误情况
| 错误 | 含义 |
|---|---|
| Transcripts disabled | 视频完全没有字幕 |
| No transcript found | 请求的语言不可用 |
| Video unavailable | 视频已删除、私有或区域限制 |
| IP blocked | 请求过多,请稍后重试 |
| Age restricted | 视频需要登录进行年龄验证 |
| bot detected | 脚本会重试备用客户端,然后是 yt-dlp;如果回退工具缺失,Agent 应该自行解决,否则如果仍然失败,请尝试 YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari(或您的浏览器) |
YouTube Transcript
Downloads transcripts (subtitles/captions) from YouTube videos. Works with both manually created and auto-generated transcripts. No API key or browser required — uses YouTube's InnerTube API directly and automatically falls back to yt-dlp when YouTube blocks the direct API path.
Fetches video metadata and cover image on first run, caches raw data for fast re-formatting.
Script Directory
Scripts in scripts/ subdirectory. {baseDir} = this SKILL.md's directory path. Resolve ${BUN_X} runtime: if bun installed → bun; if npx available → npx -y bun; else suggest installing bun. Replace {baseDir} and ${BUN_X} with actual values.
| Script | Purpose |
|---|---|
scripts/main.ts |
Transcript download CLI |
Usage
# Default: markdown with timestamps (English)
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>
# Specify languages (priority order)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja
# Without timestamps
${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps
# With chapter segmentation
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters
# With speaker identification (requires AI post-processing)
${BUN_X} {baseDir}/scripts/main.ts <url> --speakers
# SRT subtitle file
${BUN_X} {baseDir}/scripts/main.ts <url> --format srt
# Translate transcript
${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans
# List available transcripts
${BUN_X} {baseDir}/scripts/main.ts <url> --list
# Force re-fetch (ignore cache)
${BUN_X} {baseDir}/scripts/main.ts <url> --refresh
Options
| Option | Description | Default |
|---|---|---|
<url-or-id> |
YouTube URL or video ID (multiple allowed) | Required |
--languages <codes> |
Language codes, comma-separated, in priority order | en |
--format <fmt> |
Output format: text, srt |
text |
--translate <code> |
Translate to specified language code | |
--list |
List available transcripts instead of fetching | |
--timestamps |
Include [HH:MM:SS → HH:MM:SS] timestamps per paragraph |
on |
--no-timestamps |
Disable timestamps | |
--chapters |
Chapter segmentation from video description | |
--speakers |
Raw transcript with metadata for speaker identification | |
--exclude-generated |
Skip auto-generated transcripts | |
--exclude-manually-created |
Skip manually created transcripts | |
--refresh |
Force re-fetch, ignore cached data | |
-o, --output <path> |
Save to specific file path | auto-generated |
--output-dir <dir> |
Base output directory | youtube-transcript |
Optional Environment Variables
| Variable | Description |
|---|---|
YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER |
Passed to yt-dlp --cookies-from-browser during fallback, e.g. chrome, safari, firefox, or chrome:Profile 1 |
Input Formats
Accepts any of these as video input:
- Full URL:
https://www.youtube.com/watch?v=dQw4w9WgXcQ - Short URL:
https://youtu.be/dQw4w9WgXcQ - Embed URL:
https://www.youtube.com/embed/dQw4w9WgXcQ - Shorts URL:
https://www.youtube.com/shorts/dQw4w9WgXcQ - Video ID:
dQw4w9WgXcQ
Output Formats
| Format | Extension | Description |
|---|---|---|
text |
.md |
Markdown with frontmatter (incl. description), title heading, summary, optional TOC/cover/timestamps/chapters/speakers |
srt |
.srt |
SubRip subtitle format for video players |
Output Directory
youtube-transcript/
├── .index.json # Video ID → directory path mapping (for cache lookup)
└── {channel-slug}/{title-full-slug}/
├── meta.json # Video metadata (title, channel, description, duration, chapters, etc.)
├── transcript-raw.json # Raw transcript snippets from YouTube API (cached)
├── transcript-sentences.json # Sentence-segmented transcript (split by punctuation, merged across snippets)
├── imgs/
│ └── cover.jpg # Video thumbnail
├── transcript.md # Markdown transcript (generated from sentences)
└── transcript.srt # SRT subtitle (generated from raw snippets, if --format srt)
{channel-slug}: Channel name in kebab-case{title-full-slug}: Full video title in kebab-case
The --list mode outputs to stdout only (no file saved).
Caching
On first fetch, the script saves:
meta.json— video metadata, chapters, cover image path, language infotranscript-raw.json— raw transcript snippets from YouTube API ({ text, start, duration }[])transcript-sentences.json— sentence-segmented transcript ({ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]), split by sentence-ending punctuation (.?!…。?!etc.), timestamps proportionally allocated by character length, CJK-aware text mergingimgs/cover.jpg— video thumbnail
Subsequent runs for the same video use cached data (no network calls). Use --refresh to force re-fetch. If a different language is requested, the cache is automatically refreshed.
When YouTube returns anti-bot / blocked responses on the direct InnerTube path, the script retries with alternate client identities and then falls back to yt-dlp if available. If fallback is needed but yt-dlp is unavailable, the agent should decide how to make yt-dlp available and continue rather than pushing the installation decision to the user.
SRT output (--format srt) is generated from transcript-raw.json. Text/markdown output uses transcript-sentences.json for natural sentence boundaries.
Workflow
When user provides a YouTube URL and wants the transcript:
- Run with
--listfirst if the user hasn't specified a language, to show available options - Always single-quote the URL when running the script — zsh treats
?as a glob wildcard, so an unquoted YouTube URL causes "no matches found": use'https://www.youtube.com/watch?v=ID' - Default: run with
--chapters --speakersfor the richest output (chapters + speaker identification) - The script auto-saves cached data + output file and prints the file path
- For
--speakersmode: after the script saves the raw file, follow the speaker identification workflow below to post-process with speaker labels
When user only wants a cover image or metadata, running the script with any option will also cache meta.json and imgs/cover.jpg.
When re-formatting the same video (e.g., first text then SRT), the cached data is reused — no re-fetch needed.
Chapter & Speaker Workflow
Chapters (--chapters)
The script parses chapter timestamps from the video description (e.g., 0:00 Introduction), segments the transcript by chapter boundaries, groups snippets into readable paragraphs, and saves as .md with a Table of Contents. No further processing needed.
If no chapter timestamps exist in the description, the transcript is output as grouped paragraphs without chapter headings.
Speaker Identification (--speakers)
Speaker identification requires AI processing. The script outputs a raw .md file containing:
- YAML frontmatter with video metadata (title, channel, date, cover, description, language)
- Video description (for speaker name extraction)
- Chapter list from description (if available)
- Raw transcript in SRT format (pre-computed start/end timestamps, token-efficient)
After the script saves the raw file, spawn a sub-agent (use a cheaper model like Sonnet for cost efficiency) to process speaker identification:
- Read the saved
.mdfile - Read the prompt template at
{baseDir}/prompts/speaker-transcript.md - Process the raw transcript following the prompt:
- Identify speakers using video metadata (title → guest, channel → host, description → names)
- Detect speaker turns from conversation flow, question-answer patterns, and contextual cues
- Segment into chapters (use description chapters if available, else create from topic shifts)
- Format with
**Speaker Name:**labels, paragraph grouping (2-4 sentences), and[HH:MM:SS → HH:MM:SS]timestamps
- Overwrite the
.mdfile with the processed transcript (keep the YAML frontmatter)
When --speakers is used, --chapters is implied — the processed output always includes chapter segmentation.
Error Cases
| Error | Meaning |
|---|---|
| Transcripts disabled | Video has no captions at all |
| No transcript found | Requested language not available |
| Video unavailable | Video deleted, private, or region-locked |
| IP blocked | Too many requests, try again later |
| Age restricted | Video requires login for age verification |
| bot detected | The script retries alternate clients and then yt-dlp; if fallback tooling is missing, the agent should resolve that itself, otherwise if it still fails try YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari (or your browser) |
先判断是否适合
作者设计意图
作者的方法与取舍
边界和复核