---
name: ffmpeg-video-processor
description: "Build complex ffmpeg pipelines: trim, concat, watermark, transcode, subtitle burn-in. Writes correct ffmpeg commands for the hard cases: filter graphs, complex overlays, lossless trims, audio sync. Validates output codec compatibility before running."
license: MIT
---

# FFmpeg Video Processor

FFmpeg has a brutal learning curve: filter graphs, stream mapping, and codec flags that fail silently or produce broken output an hour into an encode. This skill writes correct `ffmpeg` invocations for the cases where the man page stops helping — `-filter_complex` graphs, overlay chains, lossless cuts, and audio/video resync — and checks that your chosen container and codecs are actually compatible before you commit to a long run.

## When to use it

- Concatenating clips that have different resolutions, frame rates, or codecs (where `-f concat` alone produces glitches).
- Burning subtitles (`.srt`/`.ass`) into the picture, or overlaying a watermark/logo at a specific corner with padding and opacity.
- Trimming without re-encoding (stream copy on keyframe boundaries) versus frame-accurate trims that require a re-encode.
- Fixing A/V drift, swapping audio tracks, or normalizing loudness.
- Transcoding for a target (web H.264/AAC in MP4, VP9/Opus in WebM, ProRes for editing) and wanting to know it'll play before rendering.

## How it works

The skill reasons about FFmpeg's actual pipeline — input options vs. output options, `-map` for stream selection, the split between simple `-vf`/`-af` chains and full `-filter_complex` graphs with named pads like `[0:v][1:v]overlay[out]`. It picks the right tools for each job: `overlay`, `subtitles`/`ass`, `scale`, `fps`, `concat` filter, `setpts`/`asetpts` and `-itsoffset` for sync, `loudnorm` for audio. For lossless trims it uses `-c copy -ss`/`-to` and warns about keyframe alignment. Before suggesting a command it sanity-checks codec-to-container fit (e.g. you can't mux H.265 into a naive AVI; PCM doesn't belong in MP4) and flags pixel-format issues like `yuv444p` breaking QuickTime.

## Example

```
curl -fsSL --create-dirs -o ~/.claude/skills/ffmpeg-video-processor/SKILL.md https://claudeskil.com/skills/ffmpeg-video-processor/SKILL.md

# "Overlay logo.png bottom-right with 20px margin, burn subs.srt, output web-ready MP4"
ffmpeg -i input.mp4 -i logo.png -filter_complex \
  "[0:v][1:v]overlay=W-w-20:H-h-20[bg]; \
   [bg]subtitles=subs.srt[v]" \
  -map "[v]" -map 0:a \
  -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \
  -c:a aac -b:a 128k -movflags +faststart output.mp4
```

## Tips & gotchas

- `-ss` before `-i` seeks fast (keyframe-based); after `-i` is frame-accurate but slower. The skill places it deliberately.
- Lossless trims cut at the nearest keyframe, so the start may be off by a fraction of a second — re-encode if you need exact frames.
- `-movflags +faststart` is what makes MP4s start playing before fully downloaded; easy to forget for web.
- When concatenating mismatched sources, the `concat` filter (re-encode) is safe; the `concat` demuxer (`-f concat`) requires identical codecs/params.

## FAQ

**Will it run commands or just print them?** It generates the command and the codec-compatibility check; you review and execute, so nothing destructive happens unprompted.

**Can it explain a graph I already have?** Yes — paste an existing `-filter_complex` string and it annotates each pad and filter.

**CRF or bitrate?** It defaults to CRF for quality-targeted output and switches to two-pass bitrate when you need a specific file size.
