Skills jimliu baoyu-skills

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
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 Downloads
411
+16% over the 8 weeks to Nov 9
Weekly values
Week toInstalls
Sep 21355
Sep 28193
Oct 5182
Oct 12243
Oct 19272
Oct 26297
Nov 2326
Nov 9411
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
        - npx

YouTube 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). --refresh forces re-fetch; requesting a different language refreshes automatically.
  • Any run caches meta.json and imgs/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. If yt-dlp is needed but missing, the agent decides how to make it available and continues — don't push the install decision to the user.

Workflow

  1. No language specified → run --list first to show options
  2. Always single-quote the URL (zsh globs ? → "no matches found"): 'https://www.youtube.com/watch?v=ID'
  3. Default: --chapters --speakers for the richest output
  4. The script saves cache + output and prints the file path
  5. --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:

  1. Read the saved .md and {baseDir}/prompts/speaker-transcript.md
  2. 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
  3. Overwrite the .md with 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)