Prerequisites: explicit table with two options (activate venv vs full-path). Steps: added step 0 (venv activation) to both Flow A and Flow B. Acceptance: agent can now invoke CLI without "command not found" error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.9 KiB
~/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 — если юзер уже назвал таймкоды, идём прямо за кадрами без транскрипта.
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 предполагают, что yt-tools CLI установлен из ~/projects/.common/lib/yt-tools/. Если yt-transcript / yt-frames отсутствуют на PATH — abort с install-hint (см. Prerequisites).
Prerequisites
CLI invocation — один из двух вариантов (выбери по ситуации):
| Вариант | Команда | Trade-off |
|---|---|---|
| A. Активация venv | Windows: & ~/projects/.common/lib/yt-tools/.venv/Scripts/Activate.ps1Linux/macOS: source ~/projects/.common/lib/yt-tools/.venv/bin/activate |
Одна команда, но меняет shell state |
| B. Full-path | ~/projects/.common/lib/yt-tools/.venv/Scripts/yt-frames.exe URL ... (Windows)~/projects/.common/lib/yt-tools/.venv/bin/yt-frames URL ... (Linux/macOS) |
Изолированно, но длиннее в каждом вызове |
После активации или full-path доступны:
yt-transcript,yt-frames,yt-watch,yt-tools
Внешние бинари (любая ОС):
yt-dlp— fetches metadata + source mp4ffmpeg— muxes streams + extracts frames
Полный install per-OS — в ~/projects/.common/lib/yt-tools/README.md. Windows-gotcha: после winget install Gyan.FFmpeg или winget install yt-dlp.yt-dlp нужен restart терминала (и Claude Code session) — winget пишет в per-user PATH, который текущий shell не перечитывает.
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 |
Оба flow пишут в <cwd>/yt-cache/<video-id>/ по умолчанию.
Steps
Flow A — iterative-watch
0. Activate venv: & ~/projects/.common/lib/yt-tools/.venv/Scripts/Activate.ps1 (Windows) или source ~/projects/.common/lib/yt-tools/.venv/bin/activate (Linux/macOS)
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
Альтернатива: skip шаг 0, используй full-path в каждом вызове (см. Prerequisites).
Stdout contract per CLI (бери последнюю строку, формат зависит от CLI):
yt-transcript,yt-watch— одна строка на stdout: bare absolute path артефакта (<abs>/transcript.mdили<abs>/watch.md).yt-frames— N строк форматаWrote: <abs path>, одна на каждый извлечённый кадр. Strip префикс"Wrote: "чтобы получить путь. Дизайн осознан: per-line output чтобы caller'ы пайпили / скрейпили без парсинга summary в конце.
Warnings и errors уходят в stderr (warning: …, error: …); stdout остаётся машинно-парсимым.
Flow B — targeted-frames
0. Activate venv: & ~/projects/.common/lib/yt-tools/.venv/Scripts/Activate.ps1 (Windows) или source ~/projects/.common/lib/yt-tools/.venv/bin/activate (Linux/macOS)
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 нет.
Failure modes
Все failures abort cleanly; никогда не оставляй наполовину готовое состояние.
| Symptom | Cause | Action |
|---|---|---|
yt-transcript / yt-frames not on PATH |
yt-tools pkg не pip-installed | Скажи юзеру install per ~/projects/.common/lib/yt-tools/README.md; стоп |
yt-dlp not found on PATH |
Внешний бин отсутствует | Дай install command для ОС юзера; стоп |
ffmpeg not found on PATH |
Внешний бин отсутствует | То же; на Windows после winget install Gyan.FFmpeg юзер должен 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>.jpgper 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
- Не запускай 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только если юзер просил.