Files
claude-skills/skills/using-yt-tools/SKILL.md

19 KiB
Raw Blame History

name: using-yt-tools version: 0.3.2 description: Three flows for YouTube content. Iterative-watch (summary/exploration): transcript with [mm:ss] anchors → pick moments → extract frames. Targeted-frames (specific timestamps): extract frames directly, no transcript. Audio-analysis (music FFT): per timestamp spectrogram + numeric digest (BPM, key, chord progression, harmonic content) via yt-listen. Triggers: "что в ролике", "о чём видео", "video summary", "youtube transcript", "покажи кадр на N", "послушай момент N", "BPM/тональность видео", "спектрограмма", "listen to fragment", "analyze audio", или любой youtube.com URL. CLI в ~/projects/.common/lib/yt-tools/. YouTube-only; для Vimeo/Twitch/local — другие тулзы.

using-yt-tools

Iterative-watching YouTube для агента: clean-markdown транскрипт с [mm:ss]-якорями → агент решает, какие моменты интересны → targeted frame extraction по таймкодам → агент видит кадры через Read. Альтернативный flow — если юзер уже назвал таймкоды, идём прямо за кадрами без транскрипта. Для музыкальных URL — третий flow с FFT-анализом (BPM, key, chord progression, спектр) через yt-listen.

When to use

Три различных flow, выбор по user intent:

Flow A — iterative-watch (exploration / summary):

  • Юзер спрашивает что в ролике, хочет summary, хочет узнать о чём видео.
  • Шаги: fetch transcript → read → pick interesting moments → extract those frames → Read frames.
  • Trigger phrases: «что в этом ролике», «о чём ролик», «расшифровка YouTube», «video summary», «youtube transcript», «watch this video».

Flow B — targeted-frames (specific moments):

  • Юзер уже назвал конкретные таймкоды; транскрипт — лишняя работа.
  • Шаги: extract frames at given timestamps → Read frames.
  • Trigger phrases: «покажи кадр на N», «посмотри момент N», «что показано на N», «show frame at N».

Flow C — audio-analysis (music FFT):

  • Юзер просит музыкальный разбор: BPM, тональность, гармония, chord progression, спектр, harmonic content.
  • Шаги: yt-listen URL --timestamps T1,T2,... → per timestamp 3 артефакта (clip.wav + spectrum.png + features.md) → Read обоих (PNG vision + .md числа).
  • Trigger phrases: «послушай момент N в », «какой BPM», «тональность видео», «гармония», «спектрограмма», «что в музыке на T», «listen to fragment», «analyze audio».
  • Если есть captions — yt-transcript опциональный (контекст), но НЕ для lyrics-из-music (см. What NOT to do).

Все три flow предполагают, что yt-tools CLI установлен из ~/projects/.common/lib/yt-tools/ (project-local venv). Бинари могут не быть на PATH текущей сессии — это норма, особенно после свежего winget install. Никогда не abort'ить по голому Get-Command yt-frames / which yt-frames — сначала прогнать резолв (см. Prerequisites → Locating binaries).

Prerequisites

Locating binaries

Скил ничего не предполагает про активный PATH. Step 0 каждого flow — резолв путей для yt-frames/yt-transcript и ffmpeg (+ yt-dlp, поставляется в том же venv). Если резолвится через fallback — используй PATH-prepend в каждом вызове (см. Invoke pattern ниже). Abort'ить только если бинаря нет ни на PATH, ни в известных install-локациях.

yt-tools CLI (любая из локаций даёт все пять: yt-frames, yt-transcript, yt-listen, yt-watch, yt-tools + бонусом yt-dlp):

  1. PATH: Get-Command yt-frames (pwsh) / command -v yt-frames (bash). Для Flow C — probe также yt-listen (присутствует с pyproject 0.2.0+; если только yt-frames находится, а yt-listen нет — машина на старом 0.1.x, нужен pipx reinstall yt-tools / pull + reinstall).
  2. pipx-shim (recommended install — см. install-hint ниже):
    • Windows: ~/.local/bin/yt-frames.exe (+ yt-listen.exe)
    • Linux/macOS: ~/.local/bin/yt-frames (+ yt-listen)
  3. Legacy project-venv (для машин до миграции на pipx):
    • Windows: ~/projects/.common/lib/yt-tools/.venv/Scripts/yt-frames.exe
    • Linux/macOS: ~/projects/.common/lib/yt-tools/.venv/bin/yt-frames
  4. Если ни одна локация не сработала — install hint, потом стоп. НЕ воссоздавай старый venv даже если пустой .venv/ отсутствует — это означает машина либо на pipx (probe #2 должен был сработать; если нет — у юзера pipx ensurepath не пройден, скажи запустить), либо вообще без yt-tools (свежая инсталляция per README):
    python -m pip install --user pipx
    python -m pipx ensurepath              # one-time; restart shell after
    python -m pipx install --editable ~/projects/.common/lib/yt-tools
    
    Полный README — ~/projects/.common/lib/yt-tools/README.md.

ffmpeg:

  1. PATH: Get-Command ffmpeg / command -v ffmpeg
  2. Windows winget cache (версия плавающая, глобь): ~/AppData/Local/Microsoft/WinGet/Packages/Gyan.FFmpeg_Microsoft.Winget.Source_*/ffmpeg-*-full_build/bin/ffmpeg.exe
  3. macOS Homebrew: /opt/homebrew/bin/ffmpeg (Apple Silicon) или /usr/local/bin/ffmpeg (Intel)
  4. Linux: /usr/bin/ffmpeg (apt) или /usr/local/bin/ffmpeg
  5. Если ни одна локация — install hint per-ОС (winget install Gyan.FFmpeg / brew install ffmpeg / apt install ffmpeg); стоп. Не проси юзера restart'ить CC — продолжай резолв-логику в той же сессии после установки, либо подскажи, что новой сессии PATH подхватится сам.

Invoke pattern

yt-frames сам спавнит yt-dlp и ffmpeg через subprocess.run([..., "ffmpeg", ...]) — full-path к самому yt-frames.exe не хватит, нужен PATH-prepend, чтобы child процессы тоже их видели.

$YTBIN подставляй той локацией, где нашёл yt-frames на шаге probe (~/.local/bin/ если pipx-shim, или .venv/Scripts/|/bin/ если legacy venv).

# bash / git-bash — после резолва через fallback
FFDIR=$(dirname "$(ls ~/AppData/Local/Microsoft/WinGet/Packages/Gyan.FFmpeg_*/ffmpeg-*-full_build/bin/ffmpeg.exe 2>/dev/null | head -1)")
YTBIN=~/.local/bin                       # pipx-shim (recommended); legacy: ~/projects/.common/lib/yt-tools/.venv/{Scripts,bin}
PATH="$FFDIR:$YTBIN:$PATH" yt-frames <url> --timestamps 1:23,4:56
# pwsh — glob по плавающей версии ffmpeg
$ff = (Get-ChildItem "$HOME\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_*\ffmpeg-*-full_build\bin\ffmpeg.exe" -ErrorAction SilentlyContinue | Select-Object -First 1).DirectoryName
$ytbin = "$HOME\.local\bin"              # pipx-shim (recommended); legacy: "$HOME\projects\.common\lib\yt-tools\.venv\Scripts"
$env:PATH = "$ff;$ytbin;" + $env:PATH
yt-frames <url> --timestamps 1:23,4:56

Если оба нашлись напрямую на PATH (Get-Command вернул что-то) — pre-pend не нужен, зови как обычно.

Inputs

Flow Required Optional
A — iterative-watch YouTube URL или bare 11-char video id --lang ru,en для non-English subs; --out PATH
B — targeted-frames YouTube URL + timestamps (mm:ss, h:mm:ss, или bare seconds: 123 → 2:03) --no-cache-source (stream вместо кеша source.mp4); --out DIR
C — audio-analysis YouTube URL + timestamps (как у B) --duration 30s (default 30s, lower bound для beat-tracking); --mode interval --interval 60s (bulk sampling); --no-wav / --no-spectrogram (default ON); --linear (STFT вместо mel); --chroma (bonus chromagram PNG); --sample-rate 22050; --no-cache-source; --out DIR

Все три flow пишут в <cwd>/yt-cache/<video-id>/ по умолчанию (Flow C — в audio/ поддиректорию).

Steps

Flow A — iterative-watch

0. Резолв yt-frames + ffmpeg per Prerequisites → Locating binaries; собрать PATH-prepend если резолв через fallback
1. yt-transcript <url>                        → ./yt-cache/<vid>/transcript.md
2. Read transcript.md, find [mm:ss] anchors that match the question
3. yt-frames <url> --timestamps 1:23,4:56,…   → ./yt-cache/<vid>/frames/frame_*.jpg
4. Read each frame_*.jpg via the vision tool
5. Answer the user, citing both transcript paragraph and frame contents

Stdout contract per CLI (бери последнюю строку, формат зависит от CLI):

  • yt-transcript, yt-watch — одна строка на stdout: bare absolute path артефакта (<abs>/transcript.md или <abs>/watch.md).
  • yt-framesN строк формата Wrote: <abs path>, одна на каждый извлечённый кадр. Strip префикс "Wrote: " чтобы получить путь. Дизайн осознан: per-line output чтобы caller'ы пайпили / скрейпили без парсинга summary в конце.

Warnings и errors уходят в stderr (warning: …, error: …); stdout остаётся машинно-парсимым.

Flow B — targeted-frames

0. Резолв yt-frames + ffmpeg per Prerequisites → Locating binaries; собрать PATH-prepend если резолв через fallback
1. Parse user's timestamps (mm:ss / h:mm:ss / bare seconds — все работают)
2. yt-frames <url> --timestamps 1:23,4:56,…   → ./yt-cache/<vid>/frames/frame_*.jpg
3. Read each frame_*.jpg
4. Answer the user, referencing each frame by its [mm:ss] label

Без transcript fetch. Если потом юзер спросит «что говорилось в тот момент?», переключайся на Flow A на том же URL — source.mp4 cache переиспользуется, повторного download нет.

Flow C — audio-analysis

0. Резолв yt-listen + ffmpeg per Prerequisites → Locating binaries; собрать PATH-prepend если резолв через fallback
1. Parse timestamps (mm:ss / h:mm:ss / bare seconds — как у Flow B)
2. yt-listen <url> --timestamps T1,T2,...    → ./yt-cache/<vid>/audio/{clip,spectrum,features}_TTTT.{wav,png,md}
3. Read **обоих** per timestamp: features_TTTT.md (числа — BPM, key, chord progression, spectral features, peak frequencies, harmonic/percussive split) + spectrum_TTTT.png (vision)
4. Reasoning по BPM/key/chord/spectral. Цитируй конкретные числа из features.md; spectrum-PNG — supplementary signal, не основной (см. What NOT to do)

Stdout-контракт yt-listen — одна строка Wrote: <abs path> per artifact (3 на каждый таймкод: wav, png, md), как у yt-frames.

source.mp4 cache переиспользуется между Flow A/B/C на одном URL — никаких повторных downloads. Default duration 30s (lower bound для beat-tracking); --duration override доступен. Для bulk-sampling музыкального ролика — --mode interval --interval 60s вместо явных таймкодов.

Failure modes

Все failures abort cleanly; никогда не оставляй наполовину готовое состояние.

Symptom Cause Action
yt-transcript / yt-frames not on PATH Не yt-tools отсутствуют, а PATH сессии не подхватил pipx-shim dir или venv не активен Прогнать всю probe-цепочку (PATH → ~/.local/bin/ → legacy venv). Abort и install-hint только если ни одна локация ничего не дала. НЕ воссоздавай venv по install-hint, если pipx-shim есть — это означает PATH-проблема, а не отсутствие пакета (см. What NOT to do)
yt-dlp not found on PATH (от child процесса) yt-dlp есть в той же install-локации, что и yt-frames, но PATH-prepend не собран Пересобери PATH-prepend (Prerequisites → Invoke pattern) — $YTBIN указать на ту же папку где нашёлся yt-frames
ffmpeg not found on PATH (от child процесса) ffmpeg установлен, но в winget-кэше/Homebrew/etc., не на PATH сессии Прогнать ffmpeg-резолв per Prerequisites, prepend в PATH. Abort только если ни одна локация не нашла бинаря — install per ОС. Не требовать restart CC session — резолв решает
yt-dlp source download failed (exit N) | stderr: … Network / private / age-gated / region-locked / malformed URL Выведи captured stderr verbatim; не retry
yt-dlp --dump-json failed То же, но на metadata step То же
Subtitles disabled от youtube-transcript-api Канал отключил CC Для Flow A это fatal — скажи юзеру, предложи Flow B с явными таймкодами если уместно
Юзер дал не-YouTube URL (Vimeo / Twitch / local mp4) Out of scope Стоп; скажи что скил YouTube-only

Side effects

  • Writes под <cwd>/yt-cache/<video-id>/:
    • transcript.md (Flow A)
    • source.mp4 (≤720p, оба flow если без --no-cache-source)
    • frames/frame_<mmss>.jpg per extracted frame
  • Network: yt-dlp вытягивает metadata + опционально source.mp4; youtube-transcript-api вытягивает subs
  • Никакого внешнего state не мутируется — чисто local-fs side effects
  • source.mp4 может быть ~50-200 MB на 720p / 10-минутный ролик; кеш переиспользуется между запусками. Warning: cumulative — 20 роликов = 1-4 GB на диске.

Cache hygiene: yt-tools cache list показывает usage, yt-tools cache prune --older-than 7d чистит.

What NOT to do

  • Не воссоздавай удалённый venv по install-hint. Если ~/projects/.common/lib/yt-tools/.venv/ не существует — сначала проверь ~/.local/bin/yt-frames.exe (pipx-shim). Пустой .venv/ ≠ «yt-tools не установлен»: машина могла мигрировать на pipx и старый venv осознанно снести. Install-hint в скиле — для полностью свежей машины (без pipx, без venv). Воссоздание venv поверх работающего pipx-инсталла — destructive cleanup paradox (тратит ~200MB+ и создаёт две параллельные инсталляции). Если pipx-shim существует, но Get-Command yt-frames пуст — нужен pipx ensurepath + restart shell, не новый venv.
  • Не запускай Flow A когда юзер уже дал таймкоды. «Посмотри 1:23 и 4:56» → сразу Flow B. Fetching transcript first — чистая трата.
  • Не bulk-extract «на всякий случай». Flow A берёт кадры из транскрипта, Flow B — из явного user input. Никогда --mode interval --interval 5s «to be safe».
  • Не используй yt-watch как default Flow A renderer. yt-watch комбинирует transcript + scene-frames в один doc — тяжелее (требует ffmpeg scene-detect pass на source.mp4). Бери только когда юзер хочет один self-contained document.
  • Не shell-quote URLs в одну command строку. Используй CLI list-form (он уже list-form в subprocess.run); YouTube URLs содержат ? и &, которые ломают naive quoting.
  • Не retry на yt-dlp failures. Failure здесь значит видео реально недоступно (private / region / age) или у юзера broken auth. Retries — трата токенов.
  • Не пересказывай / не переводи transcript в свой ответ молча. Артефакт — для твоего reasoning; цитируй с [mm:ss]-якорем когда приводишь пассаж.
  • Не вызывай скил на non-YouTube URL. Vimeo / Twitch / TikTok / local mp4 — out of scope. Бери другие тулзы (или yt-dlp напрямую).
  • Не пиши результаты в произвольные пути. По умолчанию <cwd>/yt-cache/<vid>/; явный --out только если юзер просил.
  • Не вызывай Whisper на смешанной музыке. Юзер просит lyrics из музыкального ролика → это не yt-listen. Whisper на mixed music без source-separation = мусор (подтверждено arXiv 2506.15514). Скажи юзеру, что lyrics из music — отдельный pipeline (Demucs/Spleeter source-separation + Whisper поверх isolated vocals), out of scope текущего yt-tools. Не пытайся подсунуть yt-transcript как замену — YouTube auto-subs для музыки обычно нет, и yt-listen НЕ имеет Whisper-флага даже опционально.
  • Не интерпретируй spectrum_*.png без features_*.md в паре. VLM-сигнал на audio спектрограммах ограничен (~50-60% accuracy на ESC-10, vs 72.5% human; Dixit et al. arXiv 2411.12058). Числовой digest из features.md — primary канал; spectrum-PNG — supplementary visual cue. Когда читаешь PNG — всегда читай и .md того же таймкода; цитируй BPM/key/chord/spectral из текстовых полей, не из «как выглядит картинка».