Help us improve
Share bugs, ideas, or general feedback.
From ai-brain-starter
Ingests YouTube video or channel transcripts using yt-dlp, cleans them, and saves as queryable markdown files in External Inputs/YouTube. Triggered by /ingest-youtube <url-or-channel> [--days N] or ingest/transcribe requests.
npx claudepluginhub adelaidasofia/ai-brain-starterHow this skill is triggered — by the user, by Claude, or both
Slash command
/ai-brain-starter:ingest-youtubeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Ingests YouTube transcripts into the vault as markdown the graphify pipeline can read and the rest of the AI Brain Starter substrate (decision log, session-close cascade, hooks) can act on.
Pull a YouTube video transcript into a queryable markdown vault with yt-dlp subtitle discovery, VTT cleanup, metadata frontmatter, and capture-seed stubs.
Extracts YouTube video transcripts and metadata, then creates a vault note with synthesized content. Triggers on any YouTube URL or phrases like "summarize this video."
Downloads YouTube video transcripts as timestamped text files via youtube-transcript-api. Use for extracting transcripts from videos for analysis, documentation, or content review.
Share bugs, ideas, or general feedback.
Ingests YouTube transcripts into the vault as markdown the graphify pipeline can read and the rest of the AI Brain Starter substrate (decision log, session-close cascade, hooks) can act on.
Same pattern as ingest-slack, ingest-whatsapp, ingest-notion, ingest-linear, ingest-github, ingest-gmail. Adding YouTube means a new normalizer, not a new architecture.
/ingest-youtube <url> for a single video/ingest-youtube <channel-handle> [--days N] for a channel's recent uploadsDo NOT use for:
yt-dlp directly with -f best)yt-dlp --write-auto-sub directly and pipe to stdout)@channelname) → channel mode (last N days, default 14).yt-dlp is installed. If not, attempt brew install yt-dlp (macOS) or pip3 install --user yt-dlp and surface the install path. Abort if neither works.yt-dlp --list-subs <url> to enumerate available subtitles.yt-dlp --write-sub --sub-lang <lang> --skip-download. Default language preference: en,es (so non-English content is captured in its original language without forcing English).yt-dlp --print-json --skip-download.External Inputs/YouTube/<channel-slug>/<YYYY-MM-DD>-<video-slug>.md.⚙️ Meta/Captures/<YYYY-MM-DD>-youtube-<channel-slug>-<video-id>.md so the seed lands in the captures aggregator./note-todos or /repurpose-talk.The skill is a thin orchestrator. The actual ingestion runs in Python at ~/.claude/skills/ingest-youtube/ingest.py.
When invoked:
--days N (channel mode only, default 14), --lang <code> (override default en,es).ingest.py. The script handles yt-dlp calls, VTT cleanup, vault write, and seed stub creation.yt-dlp --flat-playlist --print-json --dateafter <date> https://www.youtube.com/<channel>. Pass each video URL to ingest.py in sequence.The vault file at External Inputs/YouTube/<channel-slug>/<YYYY-MM-DD>-<video-slug>.md has frontmatter:
---
type: external-input
source: youtube
video_id: <11-char ID>
url: https://www.youtube.com/watch?v=<id>
channel: <channel-name>
channel_url: https://www.youtube.com/<handle>
title: <video title>
upload_date: <YYYY-MM-DD>
duration_seconds: <int>
language: <ISO code>
subtitle_source: manual | auto | whisper
word_count: <int>
ingested_at: <ISO 8601 timestamp>
---
Body is the cleaned transcript as paragraph prose. If the source had speaker labels, format as **<speaker>:** <text> per turn.
Capture seed stubs at ⚙️ Meta/Captures/<date>-youtube-<channel-slug>-<video-id>.md carry frontmatter that matches the existing capture schema so the captures aggregator picks them up cleanly.
Re-ingesting the same video URL overwrites the same vault file (the path is deterministic from channel-slug + upload-date + video-slug). The seed stub filenames hash the video_id, so the same source video produces the same stub filename across re-runs. Re-runs refresh, never duplicate.
A successful run produces:
External Inputs/YouTube/<channel>/<date>-<title>.md with valid frontmatter and clean prose body⚙️ Meta/Captures/<date>-youtube-<channel>-<video-id>.mdWrote N words to <path>. Language: <code>. Subtitle source: <source>. Seeds at: <paths>.If the video has no available subtitles and Whisper is not installed locally, write a stub file with subtitle_source: none and a note in the body explaining the gap, so re-runs are still idempotent and the absence is recorded.
If yt-dlp --list-subs returns no manual or auto subtitles AND whisper-cpp is installed locally, fall back to:
yt-dlp -x --audio-format mp3 -o <tmp>/<video-id>.mp3 <url> to download audiowhisper-cli <tmp>/<video-id>.mp3 --model ggml-large-v3.bin --output-vtt to transcribeWhisper fallback is OFF by default for cost reasons. Enable per-call with --whisper. Local Whisper has zero per-minute cost but takes ~real-time on CPU.
ingest-slack separatelyrepurpose-talk after ingestnote-todos after ingestgraphify on External Inputs/YouTube/ directly