AgentSkillsCN

youtube

管理您的YouTube频道——上传、列出、编辑元数据、安排/取消视频发布、设置缩略图、下载私人视频、获取字幕、生成AI章节摘要以及发表评论(配备Chrome自动化脚本以实现置顶)。适用于被要求上传至YouTube、安排视频发布、编辑视频元数据、下载私人YouTube视频、获取字幕、生成章节或发表/置顶评论的情况。

SKILL.md
--- frontmatter
name: youtube
description: Manage your YouTube channel — upload, list, edit metadata, schedule/unschedule videos, set thumbnails, download your own private videos, get transcripts, generate AI chapter summaries, and post comments (with a Chrome-automation playbook for pinning). Use when asked to upload to YouTube, schedule a video, edit video metadata, download a private YouTube video, get a transcript, generate chapters, or post/pin a comment.

YouTube Channel Management

Use the youtube CLI tool to manage your YouTube channel: upload videos, list uploads, edit metadata, schedule/unschedule publication, set thumbnails, download your own videos (including private ones), get transcripts, and generate AI chapter summaries.

Architecture

Three separate systems:

  1. YouTube Data API v3 + OAuth 2.0 — upload, list, update, schedule, thumbnails
  2. yt-dlp + browser cookies — download your own videos (including private)
  3. youtube_transcript_api + Gemini — transcripts (fetches existing captions) and AI chapter generation

The YouTube Data API does not have a download endpoint for uploaded video files. Download is handled separately via yt-dlp with authenticated cookies. Transcripts are fetched from YouTube's existing captions (no AI needed). Chapter generation uses Google Gemini.

Setup

1. OAuth Credentials (Required for API operations)

Create OAuth 2.0 credentials in the Google Cloud Console:

  1. Create a project (or use an existing one)
  2. Enable the YouTube Data API v3
  3. Create OAuth 2.0 Client ID (type: Desktop app)
  4. Download the client secret JSON

Provide credentials via one of:

bash
# Option A: Place the downloaded JSON file at the default path
cp ~/Downloads/client_secret_*.json ~/.youtube_client_secret.json

# Option B: Set env vars
export YOUTUBE_CLIENT_ID="your_client_id"
export YOUTUBE_CLIENT_SECRET="your_client_secret"

# Option C: Point to your JSON file
export YOUTUBE_CLIENT_SECRETS_FILE="/path/to/client_secret.json"

Then authenticate:

bash
youtube auth

This opens a browser for Google login and saves the token to ~/.youtube_oauth_token.json.

2. yt-dlp (Required for download only)

bash
pip install yt-dlp
# or
brew install yt-dlp

Commands

CommandDescription
youtube authAuthenticate via OAuth 2.0 (opens browser)
youtube uploadUpload a video with metadata
youtube listList your uploaded videos
youtube updateEdit metadata of an existing video
youtube scheduleSchedule a private video for future publication
youtube unscheduleRevert a scheduled video to private draft
youtube rescheduleChange the scheduled publish time
youtube set-thumbnailSet or replace a video thumbnail
youtube downloadDownload a video using yt-dlp (supports private videos)
youtube transcribeGet transcript of a YouTube video (fetches existing captions)
youtube chaptersGenerate AI chapter summaries using Gemini
youtube commentPost a top-level comment on a video (API cannot pin — see Chrome playbook below)

Not supported: youtube delete — deletion is explicitly excluded. Pinning comments is also not supported by the YouTube Data API; it must be done in Studio UI (see the Chrome automation playbook below).

Note: transcribe and chapters do NOT require YouTube OAuth. transcribe works with any public video. chapters requires GEMINI_API_KEY.

Usage

Upload a Video

bash
# Upload as private (default)
youtube upload --file video.mp4 --title "My Video" --description "Description here"

# Upload with tags and schedule
youtube upload --file video.mp4 --title "My Video" --tags "tag1, tag2" --publish-at 2026-04-10T16:00:00Z

# Upload as public
youtube upload --file video.mp4 --title "My Video" --privacy public -v

List Uploads

bash
# List recent uploads as a table
youtube list

# List more videos
youtube list -n 50

# Output as JSON
youtube list --json

# Verbose mode (shows tags, category)
youtube list -v

Update Metadata

bash
# Update title only
youtube update --id VIDEO_ID --title "New Title"

# Update multiple fields
youtube update --id VIDEO_ID --title "New Title" --description "New desc" --tags "a, b, c"

# Change privacy
youtube update --id VIDEO_ID --privacy unlisted

# Change category
youtube update --id VIDEO_ID --category 28

Safe updates: The tool always fetches the current video first, merges your changes, and sends a complete payload — preserving required fields like title and categoryId.

Schedule / Unschedule / Reschedule

bash
# Schedule a private video
youtube schedule --id VIDEO_ID --publish-at 2026-04-10T16:00:00Z

# Unschedule back to private draft
youtube unschedule --id VIDEO_ID

# Reschedule to a new time
youtube reschedule --id VIDEO_ID --publish-at 2026-04-11T16:00:00Z

Scheduling rules: publishAt only works on private videos that have never been published. You cannot reschedule a previously-public video.

Set Thumbnail

bash
youtube set-thumbnail --id VIDEO_ID --file thumbnail.jpg

Download Videos

By default, youtube download automatically extracts cookies from Chrome for authentication. This means you just need to be logged into YouTube in Chrome — no manual cookie export needed.

bash
# Download a video (auto-extracts Chrome cookies by default)
youtube download --id VIDEO_ID

# Download by URL
youtube download --url "https://youtu.be/VIDEO_ID"

# Save to specific path
youtube download --id VIDEO_ID -o ~/Downloads/video.mp4

# Use Firefox instead of Chrome
youtube download --id VIDEO_ID --cookies-from-browser firefox

# Specify a custom Chrome profile path
youtube download --id VIDEO_ID --cookies-from-browser "chrome:/path/to/profile"

# Use a cookies.txt file instead
youtube download --id VIDEO_ID --cookies ~/cookies.txt

# Skip cookie extraction (public videos only)
youtube download --id VIDEO_ID --no-cookies

# Choose format
youtube download --id VIDEO_ID -f "bestvideo+bestaudio"

How it works: yt-dlp reads cookies directly from Chrome's cookie database on disk. You must be logged into YouTube in Chrome. No browser window is opened — it reads the stored cookies programmatically. For private videos, the Chrome session must be logged into the account that owns the video.

Transcribe Videos

Fetches existing YouTube captions/subtitles — no AI or OAuth needed. For private/unplayable videos, automatically downloads via yt-dlp (with Chrome cookies) and transcribes locally with Whisper.

bash
# Get transcript by URL
youtube transcribe "https://youtu.be/VIDEO_ID"

# Get transcript by video ID
youtube transcribe VIDEO_ID

# Timestamps in seconds format
youtube transcribe "https://youtu.be/VIDEO_ID" --seconds

# Transcribe a local video file (uses Whisper — supports mp4, webm, mkv, etc.)
youtube transcribe video.mp4

# Private videos work too (auto-downloads with Chrome cookies, then transcribes locally)
youtube transcribe "https://youtu.be/PRIVATE_VIDEO_ID"

# Save to file
youtube transcribe "https://youtu.be/VIDEO_ID" > transcript.txt

Post a Comment

Posts a top-level comment on a video as the authenticated channel. Uses commentThreads.insert with the youtube.force-ssl scope (already included in the OAuth token).

bash
youtube comment --id VIDEO_ID --text "Your comment text here"

Prints the Thread ID, Comment ID, and a Studio deep link for pinning.

Pinning is NOT available via the API — it's a Studio-UI-only action. Use the Chrome automation playbook below after posting.

Pin a Comment via Chrome Automation

The YouTube Data API exposes no pin endpoint, so pinning requires driving Studio's UI. This playbook is verified end-to-end — follow it to avoid fishing for selectors.

Prerequisites: claude-in-chrome MCP connected and logged into the target YouTube channel in Chrome.

Steps:

  1. Navigate to https://studio.youtube.com/video/<VIDEO_ID>/comments in a fresh tab (create one with tabs_create_mcp — never clobber an existing tab).
  2. Clear the "Response status: Unresponded" filter chip. Studio hides the channel owner's own comments under this filter by default, so your just-posted comment will NOT appear until you clear it.
    • find query: "Response status filter chip with X to clear" — click the returned ref for the Remove (X) sub-element, not the chip itself.
  3. Screenshot to confirm your comment from @<your-handle> is now visible (labeled e.g. "1 minute ago").
  4. Open the kebab (three-dot) menu on YOUR comment row.
    • find query: "three-dot kebab action menu button on the <your-handle> comment row".
  5. Click "Pin" from the dropdown.
    • find query: "Pin menu item in the action menu dropdown".
    • ⚠️ Known quirk: the find-based click on the Pin menu item sometimes re-opens the dropdown instead of activating the item. If the confirmation dialog doesn't appear, fall back to a coordinate click on the visible "Pin" text — take a screenshot, read the coords, and computer.left_click there. This has been the consistent failure mode across multiple runs.
  6. Click "Pin" in the "Pin this comment?" confirmation dialog.
    • find query: "Pin button in the \"Pin this comment?\" confirmation dialog".
  7. Verify via screenshot — the comment should move to the top and show "📌 Pinned by @<your-handle>".

Parallelization: multiple subagents can pin comments on different videos in parallel. Each agent must create its own fresh tab (tabs_create_mcp) and only operate on that tabId — agents sharing a tab will thrash. Each video has its own independent pinned slot, so there's no cross-video contention.

Generate Chapters

Uses Google Gemini to generate chapter summaries with timestamps.

bash
# Generate chapters for a YouTube video
youtube chapters "https://youtu.be/VIDEO_ID"

# Generate chapters for a local MP4
youtube chapters video.mp4

Requires: GEMINI_API_KEY environment variable. Get one at https://aistudio.google.com/apikey

Options Reference

Global Options

OptionShortDescription
--verbose-vShow progress and debug info

Upload Options

OptionShortDescription
--file-fPath to video file (required)
--title-tVideo title (required)
--description-dVideo description
--tagsComma-separated tags
--categoryYouTube category ID (default: 22)
--privacy-ppublic, private, unlisted (default: private)
--publish-atISO 8601 timestamp for scheduling

Update Options

OptionShortDescription
--idVideo ID (required)
--title-tNew title
--description-dNew description
--tagsNew comma-separated tags (replaces existing)
--categoryNew category ID
--privacy-pNew privacy status

Comment Options

OptionShortDescription
--idVideo ID (required)
--text-tComment text (required)

Download Options

OptionShortDescription
--idYouTube video ID
--url-uYouTube video URL
--output-oOutput file path
--cookiesPath to cookies.txt file
--cookies-from-browserBrowser name or path (default: chrome). Examples: chrome, firefox, chrome:/path/to/profile
--format-fyt-dlp format string
--no-cookiesSkip automatic cookie extraction

Environment Variables

VariableDescription
YOUTUBE_CLIENT_IDOAuth 2.0 client ID
YOUTUBE_CLIENT_SECRETOAuth 2.0 client secret
YOUTUBE_CLIENT_SECRETS_FILEPath to client secret JSON (default: ~/.youtube_client_secret.json)
YOUTUBE_TOKEN_FILEPath to stored OAuth token (default: ~/.youtube_oauth_token.json)
GEMINI_API_KEYGoogle Gemini API key (required only for youtube chapters)

Requirements

  • The hamel package must be installed: pip install hamel
  • For download: yt-dlp must be installed separately
  • For chapters: GEMINI_API_KEY environment variable must be set
  • For local MP4 transcription: openai-whisper and ffmpeg are needed

Troubleshooting

"No OAuth credentials found": Set YOUTUBE_CLIENT_ID and YOUTUBE_CLIENT_SECRET env vars (or place a client_secret JSON file at ~/.youtube_client_secret.json), then run youtube auth.

"Token refresh failed": Your OAuth token has expired. Run youtube auth again to re-authenticate.

"yt-dlp not found": Install with pip install yt-dlp or brew install yt-dlp.

"Video not found or not accessible": Check the video ID is correct and that your authenticated account has access.

"Could not find browser cookies database": Chrome is not at the default location. Specify the profile path: --cookies-from-browser 'chrome:/path/to/profile', or use Firefox: --cookies-from-browser firefox.

"Authentication required for this video": You need to be logged into YouTube in Chrome. Open Chrome, go to youtube.com, sign in, then retry the download.

Scheduling fails: Only private videos that have never been published can be scheduled. If the video was previously public, scheduling will not work.

Complete Setup Walkthrough

If you're starting from scratch on a new machine:

  1. Install the package: pip install hamel
  2. Install yt-dlp (for downloads): pip install yt-dlp
  3. Create OAuth credentials:
  4. Set environment variables:
    bash
    export YOUTUBE_CLIENT_ID='your-client-id.apps.googleusercontent.com'
    export YOUTUBE_CLIENT_SECRET='your-client-secret'
    
  5. Authenticate: youtube auth (opens browser for one-time Google login)
  6. Verify: youtube list (should show your uploads)
  7. For downloads: Make sure you're logged into YouTube in Chrome, then youtube download --id VIDEO_ID
  8. For transcripts: youtube transcribe "https://youtu.be/VIDEO_ID" (no extra setup needed)
  9. For chapters: Set GEMINI_API_KEY env var, then youtube chapters "https://youtu.be/VIDEO_ID"