youtube-toolkit

$npx mdskill add wquguru/skills/youtube-toolkit

Download and process YouTube videos with subtitles and watermarks.

  • Users need to download YouTube videos and convert formats or extract audio.
  • Depends on yt-dlp for downloading and ffmpeg with libass for processing.
  • Chooses best-quality streams and translates subtitles based on user request.
  • Runs scripts to download, convert, and burn subtitles with a watermark.

SKILL.md

.github/skills/youtube-toolkitView on GitHub ↗
---
name: youtube-toolkit
description: Download YouTube videos with yt-dlp and post-process them with ffmpeg — fetch best-quality video/audio, convert formats, extract audio, and burn in translated (e.g. Chinese) subtitles with a translator watermark. Covers cross-environment tool installation (macOS-focused) including the ffmpeg-full / libass gotcha. Triggers on "youtube 视频下载处理".
license: MIT
allowed-tools: "Read,Write,Edit,Bash"
version: "1.0.0"
---

# YouTube Toolkit

Download and process YouTube videos: grab best-quality streams, convert/extract, and burn in translated subtitles + a watermark. macOS-first, with Linux notes.

Two helper scripts do the deterministic work; the agent does the judgement work (choosing formats, translating subtitles). Read the relevant `references/` file before a non-trivial task instead of guessing flags.

## ⚠️ Pick the right ffmpeg first (the #1 gotcha)

Homebrew's **lean `ffmpeg`** formula ships **without libass/libfreetype**, so it has **no `subtitles` and no `drawtext` filter** — subtitle burn-in and watermarks fail with `No option name` / `Error parsing filterchain`. Verify before relying on it:

```bash
ffmpeg -hide_banner -filters 2>/dev/null | grep -E ' subtitles | drawtext ' || echo "NO subtitle/drawtext support"
```

If missing, install the full build (keg-only, **does not touch your `ffmpeg`**):

```bash
brew install ffmpeg-full     # binary at /opt/homebrew/opt/ffmpeg-full/bin/ffmpeg
```

`scripts/burn-subs.sh` auto-detects an ffmpeg with libass, preferring `ffmpeg-full`. Plain download/convert work fine with the lean `ffmpeg`.

## Install tools

One shot: `bash scripts/install-tools.sh` (detects OS; installs yt-dlp, an ffmpeg with libass, and optionally the `deno` JS runtime). Or do it manually — details and Linux/conda variants in `references/installation-and-recipes.md`.

> yt-dlp prints `No supported JavaScript runtime` and falls back to the Android client. It usually still works; install `deno` (`brew install deno`) to silence it and unlock all formats.

## Common tasks

### Download (best quality)

```bash
yt-dlp -o "~/Downloads/%(title)s [%(id)s].%(ext)s" "<URL>"
```

Best video+audio merge to mp4, audio-only mp3, playlists, cookies, sections — see the recipes in `references/installation-and-recipes.md`.

### Convert / extract

Re-encode webm (often AV1+Opus, not universally playable) to H.264+AAC mp4:

```bash
ffmpeg -i in.webm -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k -movflags +faststart out.mp4
```

More recipes (remux without re-encode, trim, extract audio) in references.

### Burn in translated subtitles + watermark  ← marquee workflow

Produces a hard-subbed mp4 with a translator watermark (e.g. `@handle 翻译`). Full detail in `references/translate-and-burn.md`; the loop is:

1. **List + fetch source subtitles** (translate from the *original* language, not YouTube's machine-translated track, for quality worthy of a translator credit):
   ```bash
   yt-dlp --list-subs --skip-download "<URL>"
   yt-dlp --write-auto-subs --sub-langs en --convert-subs srt --skip-download -o "subs_%(id)s.%(ext)s" "<URL>"
   ```
2. **Re-segment + translate.** YouTube auto-captions are word-by-word *rolling* cues with **overlapping timestamps** — burning them as-is double-stacks lines. Re-segment into whole sentences (start = first cue's start, end = next sentence's start) and translate each into a clean `.zh.srt`. The agent does this; see `references/translate-and-burn.md` for the method.
3. **Burn it in:**
   ```bash
   bash scripts/burn-subs.sh -i in.webm -s subs_ID.zh.srt -w "@handle 翻译" -o out_zh.mp4
   ```
   Encode from the **highest-quality source** (the original webm), not an already-compressed mp4, to avoid a second generation loss. Preview a single frame first (`-copyts -ss T … -frames:v 1`, see references) before the full run.

## Gotchas (learned the hard way)

| Symptom | Cause → Fix |
|---|---|
| `No option name` / filterchain parse error on `-vf subtitles=…` | Lean Homebrew `ffmpeg` lacks libass → use `ffmpeg-full` |
| `force_style='…,…'` breaks `-vf` parsing | Commas in `force_style` confuse the parser → convert SRT→ASS and edit the `Style:` line instead (what `burn-subs.sh` does) |
| Two subtitle lines stack / overlap | Source is rolling auto-captions → re-segment into non-overlapping sentences |
| Subtitle missing in preview frame | `-ss` before `-i` resets PTS → add `-copyts` for preview seeks |
| AV1+Opus `.mp4` won't play in QuickTime | Re-encode to H.264+AAC (`+faststart`) |
| Chinese subtitles render as boxes | Pick a CJK font; macOS has `Hiragino Sans GB.ttc`, `STHeiti *.ttc`, `Songti.ttc`, `Arial Unicode.ttf` (no `PingFang.ttc` at the legacy path) |

## References

- `references/installation-and-recipes.md` — cross-env install (brew/pip/conda/apt), yt-dlp & ffmpeg recipe cookbook.
- `references/translate-and-burn.md` — subtitle re-segmentation, translation, ASS styling, preview/encode details.
- `scripts/install-tools.sh` — installs yt-dlp + libass-enabled ffmpeg (+ optional deno).
- `scripts/burn-subs.sh` — burns an SRT/ASS subtitle + optional watermark into a video.

More from wquguru/skills

SkillDescription
agent-compat-syncKeep repository-level Claude and Codex agent instructions compatible by creating safe symlinks between CLAUDE.md and AGENTS.md, and between .claude/skills/* and .agents/skills/*. Use when a repository should work with both Claude and Codex, when one agent instruction file exists but the other is missing, when migrating agent skills between .claude and .agents directories, or when asked to improve Claude/Codex compatibility for a repo.
clean-my-loopAudit and clean the persistent context that feeds a recurring autonomous agent loop — memory files and indexes, scheduled-task / automation prompts, and CLAUDE.md / AGENTS.md — so the loop stops degrading into a self-reinforcing echo chamber. Works for Claude Code /loop crons and Codex automations.
english-swe-daily>
fable-5-best-practiceRoute Claude tiers, effort, and subagents for Fable-led work, and handle Fable-specific prompting, long-running execution, API behavior, refusals, and fallback.
free-my-cpuSafely audit and reduce CPU, load average, I/O wait, and Docker container resource pressure on macOS and Ubuntu/Linux hosts, especially remote production-like servers over SSH. Use when a host feels slow, load average is high, monitoring shows CPU spikes, Docker containers are suspected of consuming CPU, a service dashboard times out, or the user asks for a repeatable CPU optimization workflow.
free-my-diskSafely audit and reclaim disk space on macOS and Ubuntu/Linux hosts, including remote servers over SSH. Use when the user says their Mac, Linux box, VPS, or server disk is full, asks what can be safely deleted, wants to clean caches, developer artifacts, Docker storage, apt/Homebrew/npm/pnpm/yarn/pip/uv caches, journal/log files, Xcode data, editor extensions, node_modules, Trash, crontab/systemd timer disk checks, or asks for a repeatable free-space cleanup workflow.
gpt-5-6-best-practiceRoute GPT-5.6 tiers, reasoning effort, and subagents to minimize accepted-result cost subject to an explicit quality floor.
grafana-best-practiceReview, improve, organize, deploy, and verify Grafana dashboards, provisioned alert rules, and the Telegraf→InfluxDB→Grafana monitoring stack. Use when working on Grafana dashboards, dashboard folders, tags, legends, panel readability, Flux/InfluxDB query correctness or performance, Prometheus/Telegraf dimensions, Telegraf JSON/HTTP scraping, anonymous access, dashboard/alert provisioning, Grafana Docker deployments, high CPU or memory caused by dashboard queries, provisioned alert rules and Flux alert conditions, contact points and Telegram/notification delivery, or requests like "review this dashboard", "optimize Grafana panels", "why is this dashboard slow / using CPU", "fix legends", "move dashboards into a folder", "add tags", "set up Grafana alerting", "alert won't fire / won't deliver", "fix Telegram alerts", "route alerts to a Telegram topic/thread (message_thread_id)", "bump/upgrade the Grafana version", "deploy and verify dashboards", or "Grafana best practices".
pi-setupThis skill should be used when the user wants to install or configure Pi Agent (@earendil-works/pi-coding-agent) with DeepSeek (built-in), Ant-Ling Ring-2.6-1T (single-model custom provider), and ZenMux (multi-model OpenAI-compatible aggregator including Gemini 3.5 Flash, Claude, GPT), including auth, models.json, settings.json, a curated extension set, and known-pitfall fixes. Triggers on "配置 pi"、"setup pi agent"、"pi 装一下"、"配 ring/deepseek/gemini/zenmux 到 pi".
skills-finderFind Agent Skills on skills.sh and adopt only the ones that pass a security audit. Use when the user wants to discover, search for, evaluate, or install a third-party skill ("find a skill for X", "is this skill safe to install", "search skills.sh", "what skill should I use for Y"). Always runs the skills.sh security audit before recommending or installing anything, and refuses to adopt skills that fail the audit.