{"slug":"baoyu-youtube-transcript","title":"YouTube \u5b57\u5e55\u63d0\u53d6","description":"\u6309\u94fe\u63a5\u6216\u89c6\u9891 ID \u4e0b\u8f7d YouTube \u5b57\u5e55\u4e0e\u5c01\u9762\uff0c\u652f\u6301\u591a\u8bed\u8a00\u3002","category":"\u7d20\u6750\u4e0e\u6548\u7387","tags":["YouTube","\u5b57\u5e55","\u7d20\u6750"],"author":"\u5b9d\u7389","source_url":"https://github.com/JimLiu/baoyu-skills/blob/main/skills/baoyu-youtube-transcript/SKILL.md","license":"MIT","status":"published","verification":"source_reviewed","verification_notes":"\u6765\u6e90 JimLiu/baoyu-skills\uff08skills/baoyu-youtube-transcript/SKILL.md\uff09\uff0c\u672c\u5730\u6253\u5305\u4e0a\u4f20\uff1b\u672a\u6267\u884c\u5305\u5185\u811a\u672c\u3002","revision":"c284b0523b7741bf82b678862d367ca6","created_at":"2026-10-28T08:05:07+00:00","updated_at":"2026-10-28T08:05:16+00:00","source_repo":"","source_path":"","source_commit":"","source_updated_at":"","stars":0,"proxy_score":null,"score":null,"grade":null,"dimensions":{},"evaluation":{},"installs":0,"platforms":[],"formats":[],"category_slug":"workflow","category_name":"\u7d20\u6750\u4e0e\u6548\u7387","usage_guide":{},"read_url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript","skill_url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/SKILL.md","download_url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/download","install_url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/install","files":[{"path":"SKILL.md","bytes":9704,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/SKILL.md"},{"path":"prompts/speaker-transcript.md","bytes":4695,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/prompts/speaker-transcript.md"},{"path":"scripts/main.test.ts","bytes":5644,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/main.test.ts"},{"path":"scripts/main.ts","bytes":8568,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/main.ts"},{"path":"scripts/shared.ts","bytes":3455,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/shared.ts"},{"path":"scripts/storage.ts","bytes":1925,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/storage.ts"},{"path":"scripts/transcript.ts","bytes":13144,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/transcript.ts"},{"path":"scripts/types.ts","bytes":2407,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/types.ts"},{"path":"scripts/youtube.ts","bytes":20270,"url":"https://shiliuai.cn/api/v2/skills/baoyu-youtube-transcript/files/scripts/youtube.ts"}],"content":"---\nname: baoyu-youtube-transcript\ndescription: Downloads YouTube video transcripts/subtitles and cover images by URL or video ID. Supports multiple languages, translation, chapters, and speaker identification. Caches raw data for fast re-formatting. Use when user asks to \"get YouTube transcript\", \"download subtitles\", \"get captions\", \"YouTube\u5b57\u5e55\", \"YouTube\u5c01\u9762\", \"\u89c6\u9891\u5c01\u9762\", \"video thumbnail\", \"video cover image\", or provides a YouTube URL and wants the transcript/subtitle text or cover image extracted.\nversion: 1.1.0\nmetadata:\n  openclaw:\n    homepage: https://github.com/JimLiu/baoyu-skills#baoyu-youtube-transcript\n    requires:\n      anyBins:\n        - bun\n        - npx\n---\n\n# YouTube Transcript\n\nDownloads transcripts (subtitles/captions) from YouTube videos. Works with both manually created and auto-generated transcripts. No API key or browser required \u2014 uses YouTube's InnerTube API directly and automatically falls back to `yt-dlp` when YouTube blocks the direct API path.\n\nFetches video metadata and cover image on first run, caches raw data for fast re-formatting.\n\n## Script Directory\n\nScripts in `scripts/` subdirectory. `{baseDir}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed \u2192 `bun`; if `npx` available \u2192 `npx -y bun`; else suggest installing bun. Replace `{baseDir}` and `${BUN_X}` with actual values.\n\n| Script | Purpose |\n|--------|---------|\n| `scripts/main.ts` | Transcript download CLI |\n\n## Usage\n\n```bash\n# Default: markdown with timestamps (English)\n${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id>\n\n# Specify languages (priority order)\n${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja\n\n# Without timestamps\n${BUN_X} {baseDir}/scripts/main.ts <url> --no-timestamps\n\n# With chapter segmentation\n${BUN_X} {baseDir}/scripts/main.ts <url> --chapters\n\n# With speaker identification (requires AI post-processing)\n${BUN_X} {baseDir}/scripts/main.ts <url> --speakers\n\n# SRT subtitle file\n${BUN_X} {baseDir}/scripts/main.ts <url> --format srt\n\n# Translate transcript\n${BUN_X} {baseDir}/scripts/main.ts <url> --translate zh-Hans\n\n# List available transcripts\n${BUN_X} {baseDir}/scripts/main.ts <url> --list\n\n# Force re-fetch (ignore cache)\n${BUN_X} {baseDir}/scripts/main.ts <url> --refresh\n```\n\n## Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| `<url-or-id>` | YouTube URL or video ID (multiple allowed) | Required |\n| `--languages <codes>` | Language codes, comma-separated, in priority order | `en` |\n| `--format <fmt>` | Output format: `text`, `srt` | `text` |\n| `--translate <code>` | Translate to specified language code | |\n| `--list` | List available transcripts instead of fetching | |\n| `--timestamps` | Include `[HH:MM:SS \u2192 HH:MM:SS]` timestamps per paragraph | on |\n| `--no-timestamps` | Disable timestamps | |\n| `--chapters` | Chapter segmentation from video description | |\n| `--speakers` | Raw transcript with metadata for speaker identification | |\n| `--exclude-generated` | Skip auto-generated transcripts | |\n| `--exclude-manually-created` | Skip manually created transcripts | |\n| `--refresh` | Force re-fetch, ignore cached data | |\n| `-o, --output <path>` | Save to specific file path | auto-generated |\n| `--output-dir <dir>` | Base output directory | `youtube-transcript` |\n\n## Optional Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER` | Passed to `yt-dlp --cookies-from-browser` during fallback, e.g. `chrome`, `safari`, `firefox`, or `chrome:Profile 1` |\n\n## Input Formats\n\nAccepts any of these as video input:\n- Full URL: `https://www.youtube.com/watch?v=dQw4w9WgXcQ`\n- Short URL: `https://youtu.be/dQw4w9WgXcQ`\n- Embed URL: `https://www.youtube.com/embed/dQw4w9WgXcQ`\n- Shorts URL: `https://www.youtube.com/shorts/dQw4w9WgXcQ`\n- Video ID: `dQw4w9WgXcQ`\n\n## Output Formats\n\n| Format | Extension | Description |\n|--------|-----------|-------------|\n| `text` | `.md` | Markdown with frontmatter (incl. `description`), title heading, summary, optional TOC/cover/timestamps/chapters/speakers |\n| `srt` | `.srt` | SubRip subtitle format for video players |\n\n## Output Directory\n\n```\nyoutube-transcript/\n\u251c\u2500\u2500 .index.json                          # Video ID \u2192 directory path mapping (for cache lookup)\n\u2514\u2500\u2500 {channel-slug}/{title-full-slug}/\n    \u251c\u2500\u2500 meta.json                        # Video metadata (title, channel, description, duration, chapters, etc.)\n    \u251c\u2500\u2500 transcript-raw.json              # Raw transcript snippets from YouTube API (cached)\n    \u251c\u2500\u2500 transcript-sentences.json        # Sentence-segmented transcript (split by punctuation, merged across snippets)\n    \u251c\u2500\u2500 imgs/\n    \u2502   \u2514\u2500\u2500 cover.jpg                    # Video thumbnail\n    \u251c\u2500\u2500 transcript.md                    # Markdown transcript (generated from sentences)\n    \u2514\u2500\u2500 transcript.srt                   # SRT subtitle (generated from raw snippets, if --format srt)\n```\n\n- `{channel-slug}`: Channel name in kebab-case\n- `{title-full-slug}`: Full video title in kebab-case\n\nThe `--list` mode outputs to stdout only (no file saved).\n\n## Caching\n\nOn first fetch, the script saves:\n- `meta.json` \u2014 video metadata, chapters, cover image path, language info\n- `transcript-raw.json` \u2014 raw transcript snippets from YouTube API (`{ text, start, duration }[]`)\n- `transcript-sentences.json` \u2014 sentence-segmented transcript (`{ text, start: \"HH:mm:ss\", end: \"HH:mm:ss\" }[]`), split by sentence-ending punctuation (`.?!\u2026\u3002\uff1f\uff01` etc.), timestamps proportionally allocated by character length, CJK-aware text merging\n- `imgs/cover.jpg` \u2014 video thumbnail\n\nSubsequent 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.\n\nWhen 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.\n\nSRT output (`--format srt`) is generated from `transcript-raw.json`. Text/markdown output uses `transcript-sentences.json` for natural sentence boundaries.\n\n## Workflow\n\nWhen user provides a YouTube URL and wants the transcript:\n\n1. Run with `--list` first if the user hasn't specified a language, to show available options\n2. **Always single-quote the URL** when running the script \u2014 zsh treats `?` as a glob wildcard, so an unquoted YouTube URL causes \"no matches found\": use `'https://www.youtube.com/watch?v=ID'`\n3. Default: run with `--chapters --speakers` for the richest output (chapters + speaker identification)\n3. The script auto-saves cached data + output file and prints the file path\n4. For `--speakers` mode: after the script saves the raw file, follow the speaker identification workflow below to post-process with speaker labels\n\nWhen user only wants a cover image or metadata, running the script with any option will also cache `meta.json` and `imgs/cover.jpg`.\n\nWhen re-formatting the same video (e.g., first text then SRT), the cached data is reused \u2014 no re-fetch needed.\n\n## Chapter & Speaker Workflow\n\n### Chapters (`--chapters`)\n\nThe 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.\n\nIf no chapter timestamps exist in the description, the transcript is output as grouped paragraphs without chapter headings.\n\n### Speaker Identification (`--speakers`)\n\nSpeaker identification requires AI processing. The script outputs a raw `.md` file containing:\n- YAML frontmatter with video metadata (title, channel, date, cover, description, language)\n- Video description (for speaker name extraction)\n- Chapter list from description (if available)\n- Raw transcript in SRT format (pre-computed start/end timestamps, token-efficient)\n\nAfter the script saves the raw file, spawn a sub-agent (use a cheaper model like Sonnet for cost efficiency) to process speaker identification:\n\n1. Read the saved `.md` file\n2. Read the prompt template at `{baseDir}/prompts/speaker-transcript.md`\n3. Process the raw transcript following the prompt:\n   - Identify speakers using video metadata (title \u2192 guest, channel \u2192 host, description \u2192 names)\n   - Detect speaker turns from conversation flow, question-answer patterns, and contextual cues\n   - Segment into chapters (use description chapters if available, else create from topic shifts)\n   - Format with `**Speaker Name:**` labels, paragraph grouping (2-4 sentences), and `[HH:MM:SS \u2192 HH:MM:SS]` timestamps\n4. Overwrite the `.md` file with the processed transcript (keep the YAML frontmatter)\n\nWhen `--speakers` is used, `--chapters` is implied \u2014 the processed output always includes chapter segmentation.\n\n## Error Cases\n\n| Error | Meaning |\n|-------|---------|\n| Transcripts disabled | Video has no captions at all |\n| No transcript found | Requested language not available |\n| Video unavailable | Video deleted, private, or region-locked |\n| IP blocked | Too many requests, try again later |\n| Age restricted | Video requires login for age verification |\n| 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) |\n","usage":"\u8bfb\u53d6 SKILL.md\uff0c\u5e76\u6309\u9700\u8bfb\u53d6\u914d\u5957\u6587\u4ef6\uff1b\u4e0b\u8f7d ZIP \u83b7\u53d6\u5b8c\u6574\u5305\u3002\u6280\u80fd\u662f\u4efb\u52a1\u65b9\u6cd5\uff0c\u4e0d\u6388\u4e88\u65b0\u589e\u8d26\u6237\u3001\u4ed8\u8d39\u6216\u7cfb\u7edf\u6743\u9650\u3002"}
