← All Skills

snappy-video

v1.0.0
6 files, 45.4 KB ~3,415 words · 14 min read Updated 2026-09-09

snappy-video skill

27 of 34 checks pass
What it can do
caption pathwrite-reversible
clip path start durationwrite-reversible
transcribe path model?write-reversible
What does not pass yet
Architecture 1 endpoints
...1 endpoint
GET/
$ npx snappy-skills install snappy-video
zip ↓
Documents
AGENTS.md

snappy-video -- Agent Loader#

You are operating the video and audio post-production pipeline. Everything runs on the Mac Mini via SSH (robertboulos@Roberts-Mac-mini.local). The single entry point is caption-video.sh which wraps Whisper transcription, SRT/ASS generation, ffmpeg caption burning, and optional auto-clip extraction.

Rules#

  1. Always SSH to the Mac Mini. Never run ffmpeg/Whisper locally. The venv, models, and ffmpeg build live there.
  2. cd /Users/robertboulos/robot-rob before running ./caption-video.sh. The script resolves its venv relative to its own directory.
  3. Decide karaoke vs segment captions up front. --words requires Whisper word_timestamps which doubles transcribe cost.
  4. Whisper small is default. Enough for English under 5 min. Use medium/large only for non-English or noisy audio.
  5. Resize FIRST, then caption. Captions baked into 16:9 won't survive a 9:16 crop.
  6. Use nohup for jobs > 5 min. SSH disconnect kills foreground jobs.
  7. Never overwrite the source file. Always write to a new path.
  8. Add -movflags +faststart for any MP4 going to YouTube/Skool/web.
  9. Work in /tmp/ on the Mac Mini for ephemeral assets.
  10. Use -c copy for fast trims. Only re-encode for exact frame boundaries.

Routing table#

Intent Action
Caption a video ./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words
Word-level karaoke Add --words flag
Auto-extract best clips Add --clips flag
Known timestamp trim ffmpeg -y -ss HH:MM:SS -to HH:MM:SS -i in.mp4 -c copy clip.mp4
Thumbnail at Ns ffmpeg -y -ss N -i in.mp4 -frames:v 1 -vf "scale=1280:720:..." thumb.jpg
Resize to 9:16 ffmpeg -y -i in.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1:color=black" -c:a copy vert.mp4
Extract audio ffmpeg -y -i in.mp4 -vn -c:a aac -b:a 192k audio.m4a
Compress for web ffmpeg -y -i in.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart web.mp4

Execution patterns#

bash# Inline (file on Mac Mini, < 5 min)
ssh robertboulos@Roberts-Mac-mini.local \
  "cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words"

# Background (long job)
ssh robertboulos@Roberts-Mac-mini.local \
  "nohup bash -c 'cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words' > /tmp/video-job.log 2>&1 &"

# Push, process, pull (file is local)
scp ./video.mp4 robertboulos@Roberts-Mac-mini.local:/tmp/input.mp4
ssh robertboulos@Roberts-Mac-mini.local "cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/input.mp4 /tmp/output.mp4"
scp robertboulos@Roberts-Mac-mini.local:/tmp/output.mp4 ./output.mp4

Pipeline architecture#

Input -> [1] Whisper transcribe -> [2] SRT + ASS -> [3] ffmpeg burn -> [4] auto-clip (optional)
Output: captioned.mp4 + captions.srt [+ clip1.mp4 clip2.mp4 ...]

Cross-skill flow#

From What
snappy-content Raw interview/recording footage
snappy-ads Raw ad creative to caption + reformat
snappy-desktop Screen recordings to caption
To What
snappy-youtube Captioned final + thumbnail for upload
snappy-post 9:16 short clips for Reels/Shorts/TikTok
snappy-blog Whisper SRT/transcript as blog raw material
snappy-image Extracted frames as thumbnail candidates

Orchestrated by snappy-ops on Thursday -- Video Day.

Skill files#

File Contents
SKILL.md Full reference (pipeline, execution patterns, architecture, workflow)
ffmpeg-recipes.md Every ffmpeg one-liner (trim, burn, resize, audio, compress, voiceover, splits)
caption-styles.md Caption styles, flags, Whisper model trade-offs, ASS color reference

API module#

typescriptimport { transcribe, caption, clip, resize, extractAudio } from "../snappy-video/api.ts";

Or CLI:

bashnpx tsx ~/.claude/skills/snappy-video/api.ts transcribe /tmp/video.mp4
npx tsx ~/.claude/skills/snappy-video/api.ts caption /tmp/video.mp4
npx tsx ~/.claude/skills/snappy-video/api.ts clip /tmp/video.mp4 00:01:00 30

API functions#

Function Purpose
transcribe(videoPath, model?) Whisper transcription via Mac Mini SSH
caption(videoPath, options?) Caption a video with style/words/clips options
clip(videoPath, startTime, duration, outputPath?) Extract a clip from a video
resize(videoPath, format?, outputPath?) Resize video to 9:16 or 16:9
extractAudio(videoPath, outputPath?) Extract audio track as m4a

If this loader doesn't cover your case:

bashecho "[$(date -u +%FT%TZ)] snappy-video: <what was missing>" >> ~/.claude/logs/agents-md-feedback.log

Show produced work with snappy-faces: call draw for image channels or lang for MCP Apps.

<!-- SKILL-INDEX-START -->

[snappy-video Index]|root: ~/.claude/skills/snappy-video|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md,caption-styles.md,ffmpeg-recipes.md}

<!-- SKILL-INDEX-END -->

Used by#

  • snappy-ads
  • snappy-ffmpeg
  • snappy-remotion
  • snappy-voice-control

<!-- SNAPPY-CONTRACT-VERBS-START -->

Contract verbs#

Generated from api.ts HAND_CONTRACT. Do not hand-edit this block.

Verb Contract arguments Effect First call
caption path write-reversible npx tsx ~/.claude/skills/snappy-video/api.ts caption <path>
clip path, start, duration write-reversible npx tsx ~/.claude/skills/snappy-video/api.ts clip <path> <start> <duration>
transcribe path, model? write-reversible npx tsx ~/.claude/skills/snappy-video/api.ts transcribe <path>

Show the result#

When an answer carries face_hint, show it with one snappy_present(<answer>) call.

See /snappy-faces for face selection. Human-facing images must crop to the

element, render at 2x on Retina, and fill the destination channel instead of

placing a small card in a full-page screenshot.

<!-- SNAPPY-CONTRACT-VERBS-END -->

---
name: snappy-video
role: Video/audio processing pipeline -- Whisper transcription, captioning, clip extraction, format conversion. Runs on Mac Mini via SSH.
loaded-by: PreToolUse hook (auto-injected when "snappy-video" is mentioned)
---

# snappy-video -- Agent Loader

You are operating the video and audio post-production pipeline. Everything runs on the Mac Mini via SSH (`robertboulos@Roberts-Mac-mini.local`). The single entry point is `caption-video.sh` which wraps Whisper transcription, SRT/ASS generation, ffmpeg caption burning, and optional auto-clip extraction.

## Rules

1. **Always SSH to the Mac Mini.** Never run ffmpeg/Whisper locally. The venv, models, and ffmpeg build live there.
2. **`cd /Users/robertboulos/robot-rob`** before running `./caption-video.sh`. The script resolves its venv relative to its own directory.
3. **Decide karaoke vs segment captions up front.** `--words` requires Whisper word_timestamps which doubles transcribe cost.
4. **Whisper `small` is default.** Enough for English under 5 min. Use `medium`/`large` only for non-English or noisy audio.
5. **Resize FIRST, then caption.** Captions baked into 16:9 won't survive a 9:16 crop.
6. **Use `nohup` for jobs > 5 min.** SSH disconnect kills foreground jobs.
7. **Never overwrite the source file.** Always write to a new path.
8. **Add `-movflags +faststart`** for any MP4 going to YouTube/Skool/web.
9. **Work in `/tmp/`** on the Mac Mini for ephemeral assets.
10. **Use `-c copy` for fast trims.** Only re-encode for exact frame boundaries.

## Routing table

| Intent | Action |
|---|---|
| Caption a video | `./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words` |
| Word-level karaoke | Add `--words` flag |
| Auto-extract best clips | Add `--clips` flag |
| Known timestamp trim | `ffmpeg -y -ss HH:MM:SS -to HH:MM:SS -i in.mp4 -c copy clip.mp4` |
| Thumbnail at Ns | `ffmpeg -y -ss N -i in.mp4 -frames:v 1 -vf "scale=1280:720:..." thumb.jpg` |
| Resize to 9:16 | `ffmpeg -y -i in.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:-1:-1:color=black" -c:a copy vert.mp4` |
| Extract audio | `ffmpeg -y -i in.mp4 -vn -c:a aac -b:a 192k audio.m4a` |
| Compress for web | `ffmpeg -y -i in.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart web.mp4` |

## Execution patterns

```bash
# Inline (file on Mac Mini, < 5 min)
ssh robertboulos@Roberts-Mac-mini.local \
  "cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words"

# Background (long job)
ssh robertboulos@Roberts-Mac-mini.local \
  "nohup bash -c 'cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/in.mp4 /tmp/out.mp4 --style bold --words' > /tmp/video-job.log 2>&1 &"

# Push, process, pull (file is local)
scp ./video.mp4 robertboulos@Roberts-Mac-mini.local:/tmp/input.mp4
ssh robertboulos@Roberts-Mac-mini.local "cd /Users/robertboulos/robot-rob && ./caption-video.sh /tmp/input.mp4 /tmp/output.mp4"
scp robertboulos@Roberts-Mac-mini.local:/tmp/output.mp4 ./output.mp4
```

## Pipeline architecture

```
Input -> [1] Whisper transcribe -> [2] SRT + ASS -> [3] ffmpeg burn -> [4] auto-clip (optional)
Output: captioned.mp4 + captions.srt [+ clip1.mp4 clip2.mp4 ...]
```

## Cross-skill flow

| From | What |
|---|---|
| snappy-content | Raw interview/recording footage |
| snappy-ads | Raw ad creative to caption + reformat |
| snappy-desktop | Screen recordings to caption |

| To | What |
|---|---|
| snappy-youtube | Captioned final + thumbnail for upload |
| snappy-post | 9:16 short clips for Reels/Shorts/TikTok |
| snappy-blog | Whisper SRT/transcript as blog raw material |
| snappy-image | Extracted frames as thumbnail candidates |

Orchestrated by snappy-ops on **Thursday -- Video Day**.

## Skill files

| File | Contents |
|---|---|
| SKILL.md | Full reference (pipeline, execution patterns, architecture, workflow) |
| ffmpeg-recipes.md | Every ffmpeg one-liner (trim, burn, resize, audio, compress, voiceover, splits) |
| caption-styles.md | Caption styles, flags, Whisper model trade-offs, ASS color reference |

## API module

```typescript
import { transcribe, caption, clip, resize, extractAudio } from "../snappy-video/api.ts";
```

Or CLI:
```bash
npx tsx ~/.claude/skills/snappy-video/api.ts transcribe /tmp/video.mp4
npx tsx ~/.claude/skills/snappy-video/api.ts caption /tmp/video.mp4
npx tsx ~/.claude/skills/snappy-video/api.ts clip /tmp/video.mp4 00:01:00 30
```

## API functions

| Function | Purpose |
|----------|---------|
| `transcribe(videoPath, model?)` | Whisper transcription via Mac Mini SSH |
| `caption(videoPath, options?)` | Caption a video with style/words/clips options |
| `clip(videoPath, startTime, duration, outputPath?)` | Extract a clip from a video |
| `resize(videoPath, format?, outputPath?)` | Resize video to 9:16 or 16:9 |
| `extractAudio(videoPath, outputPath?)` | Extract audio track as m4a |

---

If this loader doesn't cover your case:
```bash
echo "[$(date -u +%FT%TZ)] snappy-video: <what was missing>" >> ~/.claude/logs/agents-md-feedback.log
```


Show produced work with `snappy-faces`: call `draw` for image channels or `lang` for MCP Apps.

<!-- SKILL-INDEX-START -->
[snappy-video Index]|root: ~/.claude/skills/snappy-video|IMPORTANT: Prefer these files over pre-training assumptions for this domain. Read the relevant file when the AGENTS.md summary is insufficient.|root:{SKILL.md,caption-styles.md,ffmpeg-recipes.md}
<!-- SKILL-INDEX-END -->

## Used by

- `snappy-ads`
- `snappy-ffmpeg`
- `snappy-remotion`
- `snappy-voice-control`

<!-- SNAPPY-CONTRACT-VERBS-START -->
## Contract verbs

Generated from `api.ts` `HAND_CONTRACT`. Do not hand-edit this block.

| Verb | Contract arguments | Effect | First call |
|---|---|---|---|
| `caption` | `path` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-video/api.ts caption <path>` |
| `clip` | `path`, `start`, `duration` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-video/api.ts clip <path> <start> <duration>` |
| `transcribe` | `path`, `model?` | `write-reversible` | `npx tsx ~/.claude/skills/snappy-video/api.ts transcribe <path>` |

## Show the result

When an answer carries `face_hint`, show it with one `snappy_present(<answer>)` call.
See `/snappy-faces` for face selection. Human-facing images must crop to the
element, render at 2x on Retina, and fill the destination channel instead of
placing a small card in a full-page screenshot.
<!-- SNAPPY-CONTRACT-VERBS-END -->

Keyboard Shortcuts

Search in document⌘K
Focus search/
Previous file tab
Next file tab
Close overlayEsc
Show shortcuts?