Skip to content

feat: video skill — an ffmpeg toolbox over a workspace clip - #11

Open
1Croydan1 wants to merge 1 commit into
mainfrom
feature/video-skill
Open

feat: video skill — an ffmpeg toolbox over a workspace clip#11
1Croydan1 wants to merge 1 commit into
mainfrom
feature/video-skill

Conversation

@1Croydan1

Copy link
Copy Markdown
Collaborator

Почему

Иван скинул Альберту видео — он не отреагировал. Причин оказалось две, и это вторая половина починки.

Первая — в octo: telegram-коннектор вообще не знает video (LamantinAI/octo#9). Вторая — даже получив файл, Альберту нечем его открыть: ffmpeg в образе есть, но ни один скилл им не пользуется.

Этот PR добавляет инструментальную половину. Он полезен уже сейчас, не дожидаясь octo: видео, присланное документом, и сегодня кладётся в workspace с сообщённым путём.

Что умеет

подкоманда зачем
info длительность, размер, разрешение, fps, кодеки, has_audio — дёшево, до любого решения
frames стоп-кадры JPEG; без --at раскидывает --count (по умолчанию 3) по клипу, обходя начало и конец, где обычно чернота
clip вырезать кусок; копией потоков — мгновенно и без потерь
gif зацикленное превью (6 с, 10 fps, 480 px; потолок 30 с — гифки растут быстро)
audio снять звуковую дорожку в .m4a
compress ужать под бюджет размера (19 МБ — чуть ниже лимита Telegram), честно сообщая met_target

Речь намеренно не здесь. Скилл transcribe уже читает видеоконтейнеры — SKILL.md отправляет туда с тем же путём, вместо дублирования пайплайна.

Договорённости

Как у существующих скиллов: запуск через forkd, пути workspace-относительные (forkd даёт cwd = workspace), один JSON-объект в stdout, артефакты в корне workspace — как у imagegen. Вход ограничен workspace, выход никогда не затирает предыдущий артефакт.

Документирована и честная граница: извлечённые кадры — файлы, и сам Альберт их не видит (его зрение — только Blob от коннектора, cogitator.rs). Их можно отправить пользователю через chat.send_file; поэтому же в octo-PR превью едет блобом, а не путём.

Тесты

20, все прогнаны.

  • 7 на чистые функции: разбор таймкодов отвергает мусор, а не «сеет в 0:00» молча; выборка кадров держится подальше от краёв; имена артефактов не сталкиваются и не убегают из workspace.
  • 13 гоняют скрипт подпроцессом ровно как forkd — против клипов, которые ffmpeg собирает на месте. Включая пути честного отказа: немой клип, момент за концом, перевёрнутый диапазон, отсутствующий файл, путь наружу.

Зелёные и локально (ffmpeg 8.1.1, Python 3.11), и внутри задеплоенного образа (ffmpeg 6.1.1, Python 3.12.3) — версии ffmpeg разошлись на две мажорки, поэтому проверял обе.

Ran 20 tests in 4.508s
OK

Ветка собрана от актуального origin/main (f72a582). Rust не тронут — только файлы скилла.

🤖 Generated with Claude Code

Albert could already be handed a video (one sent as a document lands in the
workspace with its path reported), but had nothing to open it with. This adds
the tool side: read a clip's facts, take stills out of it, cut a piece, build a
small looping preview, lift the audio track off, or shrink it to fit a chat.

Speech is deliberately left to `transcribe`, which reads video containers
directly — the skill points there instead of duplicating the pipeline.

Conventions follow the existing skills: run through forkd, workspace-relative
paths (forkd's cwd is the workspace), one JSON object on stdout, artifacts in
the workspace root like imagegen's. Inputs are confined to the workspace, and
outputs never clobber an earlier artifact.

Tests: 20, all run. Seven cover the pure helpers (timestamp parsing refuses
nonsense rather than silently seeking to zero; frame sampling stays off the
usually-black edges; output naming avoids collisions and stays in the
workspace). Thirteen drive the script as a subprocess exactly as forkd does,
against clips ffmpeg builds on the spot — including the honest-failure paths:
a silent clip, a moment past the end, a backwards range, a missing file, a path
escaping the workspace. Green both locally (ffmpeg 8.1.1) and inside the
deployed image (ffmpeg 6.1.1, Python 3.12.3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant