baoyu-youtube-transcript
- Use it when:
- You want the words of a YouTube video, or its thumbnail, saved as a file.
- It does:
- Fetches captions with its bundled script through YouTube's InnerTube API, falling back to yt-dlp when YouTube blocks it.
- You get:
- transcript.md with timestamped paragraphs, or transcript.srt, plus meta.json and imgs/cover.jpg, under youtube-transcript/<channel>/<title>/.
- Speakers:
- By default a subagent labels who is speaking, from the title, channel, description and conversation cues, and splits the text into chapters.
- Languages:
- Lists the available transcripts when you name no language, takes a language order, and can translate.
- Caches:
- Raw data per video, so reformatting it or asking only for the cover doesn't fetch it again.
- Needs:
- Bun or npx, plus yt-dlp as a fallback, which the agent sets up itself if it's missing; no API key or browser.
When YouTube blocks its requests, it falls back to yt-dlp, and the agent installs yt-dlp without asking if it's missing.
TL;DR
It works with manual and auto-generated captions and takes watch, youtu.be, embed and shorts links or bare video IDs, several at once. Chapters come from the timestamps in the video's description; without them, the text is grouped into paragraphs. For speaker identification, which it uses by default, the script saves a raw file with the metadata and the transcript in SRT form, then a subagent, which can be a cheaper model, rewrites it with speaker labels, short paragraphs and timestamps. Sentences are split on punctuation, including Chinese, Japanese and Korean, with timestamps shared out by length. When YouTube flags it as a bot, the script retries other client identities, then yt-dlp; passing your browser's cookies to yt-dlp is the last resort. It can skip auto-generated or manual transcripts, and --refresh ignores the cache.
Summarizes the skill at ca703c2.
npx skills add https://github.com/jimliu/baoyu-skills --skill baoyu-youtube-transcript skills.sh pageSource on GitHubAll skills from jimliu/baoyu-skills
- Total Downloads
- 22,400 on skills.sh, Nov 9, 2026
- Repo stars
- 27,397 jimliu/baoyu-skills
- First seen
- Mar 22, 2026 on skills.sh
Weekly values
| Week to | Installs |
|---|---|
| Sep 21 | 355 |
| Sep 28 | 193 |
| Oct 5 | 182 |
| Oct 12 | 243 |
| Oct 19 | 272 |
| Oct 26 | 297 |
| Nov 2 | 326 |
| Nov 9 | 411 |
| Category |
Drive browsers, scrape pages and search the web. Everything for building software: planning, coding, debugging, design, frameworks, cloud, agents and skills. |
|---|---|
| Type |
Operates a CLI, API, app or bundled script to get something done. |
| Effect |
Its own steps create or change files, git state or local tools. |
| Needs |
A specific command-line tool or desktop app must be installed, such as gh, agent-browser, LibreOffice, Obsidian or a vendor CLI. Relies on the agent being able to spawn subagents. |
| Publisher |
Everyone else. Unverified vendor claims default to community. |
| Topics | |
| Stack |
SKILL.md
From jimliu/baoyu-skills at ca703c2. Checked daily, last changed Nov 6, 2026.
Frontmatter
name: baoyu-youtube-transcript
description: 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字幕", "YouTube封面", "视频封面", "video thumbnail", "video cover image", or provides a YouTube URL and wants the transcript/subtitle text or cover image extracted.
version: 1.1.0
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-youtube-transcript
requires:
anyBins:
- bun
- npxYouTube Transcript
Works with manual and auto-generated transcripts. No API key or browser: uses YouTube's InnerTube API, falling back to yt-dlp when YouTube blocks the direct path. First run also fetches metadata and cover image and caches raw data for fast re-formatting.
Script Directory
{baseDir} = this SKILL.md's directory. ${BUN_X} = bun if installed; else npx -y bun if npx available; else suggest installing bun. Replace {baseDir} and ${BUN_X} with actual values.
| Script | Purpose |
|---|---|
scripts/main.ts |
Transcript download CLI |
Usage
${BUN_X} {baseDir}/scripts/main.ts <youtube-url-or-id> # markdown with timestamps (English)
${BUN_X} {baseDir}/scripts/main.ts <url> --languages zh,en,ja # language priority
${BUN_X} {baseDir}/scripts/main.ts <url> --chapters --speakers
${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
| 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> |
text (.md: frontmatter incl. description, title, summary, optional TOC/cover/timestamps/chapters/speakers) or srt |
text |
--translate <code> |
Translate to language code | |
--list |
List available transcripts (stdout only, no file) | |
--timestamps |
[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 cache | |
-o, --output <path> |
Output file path | auto-generated |
--output-dir <dir> |
Base output directory | youtube-transcript |
Input: https://www.youtube.com/watch?v=ID, https://youtu.be/ID, https://www.youtube.com/embed/ID, https://www.youtube.com/shorts/ID, or bare video ID.
Optional env: YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER — passed to yt-dlp --cookies-from-browser during fallback (e.g. chrome, safari, firefox, chrome:Profile 1).
Output Directory
youtube-transcript/
├── .index.json # Video ID → directory path (cache lookup)
└── {channel-slug}/{title-full-slug}/ # channel name / full title, kebab-case
├── meta.json # title, channel, description, duration, chapters, cover path, language info
├── transcript-raw.json # raw API snippets `{ text, start, duration }[]`
├── transcript-sentences.json # `{ text, start: "HH:mm:ss", end: "HH:mm:ss" }[]`
├── imgs/
│ └── cover.jpg # Video thumbnail
├── transcript.md # from transcript-sentences.json
└── transcript.srt # from transcript-raw.json (--format srt)
transcript-sentences.json splits on sentence-ending punctuation (.?!…。?! etc.), merges across snippets (CJK-aware), and allocates timestamps proportionally by character length.
Caching & Fallback
- Repeat runs for the same video use the cache (no network).
--refreshforces re-fetch; requesting a different language refreshes automatically. - Any run caches
meta.jsonandimgs/cover.jpg, so cover/metadata-only requests just need one run. - On anti-bot / blocked responses the script retries alternate client identities, then
yt-dlp. Ifyt-dlpis needed but missing, the agent decides how to make it available and continues — don't push the install decision to the user.
Workflow
- No language specified → run
--listfirst to show options - Always single-quote the URL (zsh globs
?→ "no matches found"):'https://www.youtube.com/watch?v=ID' - Default:
--chapters --speakersfor the richest output - The script saves cache + output and prints the file path
--speakers→ post-process per Speaker Identification below
Chapters (--chapters)
Parses chapter timestamps from the description (e.g., 0:00 Introduction), segments by chapter, groups snippets into paragraphs, saves .md with a Table of Contents. No further processing. No chapter timestamps → grouped paragraphs without chapter headings.
Speaker Identification (--speakers)
Implies --chapters. The script saves a raw .md with YAML frontmatter (title, channel, date, cover, description, language), the video description, the description's chapter list (if any), and the transcript in SRT format.
Spawn a sub-agent (a cheaper model like Sonnet is fine) to:
- Read the saved
.mdand{baseDir}/prompts/speaker-transcript.md - Process the transcript per the prompt: identify speakers from metadata (title → guest, channel → host, description → names) and conversation cues; segment into chapters (description chapters, else topic shifts); format with
**Speaker Name:**labels, 2-4 sentence paragraphs,[HH:MM:SS → HH:MM:SS]timestamps - Overwrite the
.mdwith the result, keeping the YAML frontmatter
Error Cases
| Error | Meaning |
|---|---|
| Transcripts disabled | Video has no captions at all |
| No transcript found | Requested language not available |
| Video unavailable | Deleted, private, or region-locked |
| IP blocked | Too many requests, try again later |
| Age restricted | Login required for age verification |
| bot detected | Script retries alternate clients, then yt-dlp; resolve missing fallback tooling yourself; if it still fails try YOUTUBE_TRANSCRIPT_COOKIES_FROM_BROWSER=safari (or your browser) |