diff --git a/skills/using-yt-tools/SKILL.md b/skills/using-yt-tools/SKILL.md index ecccac5..3f30d05 100644 --- a/skills/using-yt-tools/SKILL.md +++ b/skills/using-yt-tools/SKILL.md @@ -1,182 +1,55 @@ --- 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 — другие тулзы. +version: 0.4.0 +description: DEPRECATED — this skill has migrated to the `OpeItcLoc03/yt-tools` Claude Code plugin (canonical source). To restore yt-tools functionality, install the plugin via `/plugin marketplace add OpeItcLoc03/claude-plugins` followed by `/plugin install yt-tools@opeitcloc03-claude-plugins`. The plugin's bundled SessionStart hook auto-runs `pipx install yt-tools`, and its bundled skill (full English, mixed RU/EN triggers) takes over from this stub. Once the plugin is installed, this `claude-skills/skills/using-yt-tools/` directory becomes redundant and can be deleted. This stub intentionally declares **no trigger phrases** to avoid double-activation with the plugin's skill — it remains inert until invoked by name. --- -# using-yt-tools +# using-yt-tools — deprecated stub -Iterative-watching YouTube для агента: clean-markdown транскрипт с `[mm:ss]`-якорями → агент решает, какие моменты интересны → targeted frame extraction по таймкодам → агент видит кадры через `Read`. Альтернативный flow — если юзер уже назвал таймкоды, идём прямо за кадрами без транскрипта. Для музыкальных URL — третий flow с FFT-анализом (BPM, key, chord progression, спектр) через `yt-listen`. +This skill has migrated to the **`OpeItcLoc03/yt-tools` Claude Code plugin**. +It is no longer maintained in the `claude-skills` repository — all future +changes (CLI flag updates, new flows, bug fixes, version bumps) ship with +the plugin distribution. -## When to use +## Why the move -Три различных flow, выбор по user intent: +Bundling the skill into a self-contained plugin (Python CLI + skill + hooks ++ LICENSE in one repo) lets one user-action install everything: the +plugin's `SessionStart` hook auto-runs `pipx install yt-tools` and probes +`ffmpeg`, and the bundled skill activates the same three flows +(iterative-watch / targeted-frames / audio-analysis) without any separate +`claude-skills` install step. See the design rationale in +`OpeItcLoc03/common/.wiki/concepts/yt-tools-distribution.md`. -**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». +## How to install the replacement -**Flow B — targeted-frames** (specific moments): -- Юзер уже назвал конкретные таймкоды; транскрипт — лишняя работа. -- Шаги: extract frames at given timestamps → Read frames. -- Trigger phrases: «покажи кадр на N», «посмотри момент N», «что показано на N», «show frame at N». +```text +/plugin marketplace add OpeItcLoc03/claude-plugins +/plugin install yt-tools@opeitcloc03-claude-plugins +``` -**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). +The first session after install will run the plugin's `SessionStart` hook +to install the PyPI `yt-tools` package and probe `ffmpeg`. From there the +plugin's bundled skill (canonical English version, mixed RU/EN triggers) +takes over. -Все три 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). +## What to do with this stub -## 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). +After `/plugin install yt-tools@opeitcloc03-claude-plugins` reports +success on your machine — delete this directory: ```bash -# 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 --timestamps 1:23,4:56 +rm -rf ~/projects/claude-skills/skills/using-yt-tools/ ``` -```powershell -# 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 --timestamps 1:23,4:56 -``` +This stub has no trigger phrases, so it remains inert and will not +double-activate alongside the plugin's skill. It exists only as a sign +post for anyone still looking for the old location. -Если оба нашлись напрямую на PATH (`Get-Command` вернул что-то) — pre-pend не нужен, зови как обычно. +## Source pointers -## 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 пишут в `/yt-cache//` по умолчанию (Flow C — в `audio/` поддиректорию). - -## Steps - -### Flow A — iterative-watch - -``` -0. Резолв yt-frames + ffmpeg per Prerequisites → Locating binaries; собрать PATH-prepend если резолв через fallback -1. yt-transcript → ./yt-cache//transcript.md -2. Read transcript.md, find [mm:ss] anchors that match the question -3. yt-frames --timestamps 1:23,4:56,… → ./yt-cache//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 артефакта (`/transcript.md` или `/watch.md`). -- `yt-frames` — **N строк** формата `Wrote: `, одна на каждый извлечённый кадр. 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 --timestamps 1:23,4:56,… → ./yt-cache//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 --timestamps T1,T2,... → ./yt-cache//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: ` 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 под `/yt-cache//`: - - `transcript.md` (Flow A) - - `source.mp4` (≤720p, оба flow если без `--no-cache-source`) - - `frames/frame_.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 напрямую). -- **Не пиши результаты в произвольные пути.** По умолчанию `/yt-cache//`; явный `--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 из текстовых полей, не из «как выглядит картинка». +- Plugin repository: +- Marketplace catalog: +- Bundled canonical SKILL: `skills/using-yt-tools/SKILL.md` in the plugin repo +- PyPI: (live once Phase 4 publishes) +- Design rationale: `OpeItcLoc03/common/.wiki/concepts/yt-tools-distribution.md`