kajisho5/ffmpeg-skill
ffmpeg-skill is an Agent Skill (SKILL.md plus 42 stdlib-only Python tools) that lets Claude Code, Cursor, Codex and other agents edit video and audio with local ffmpeg/ffprobe. It enforces a probe → edit losslessly → check → verify workflow, and every tool takes --dry-run, --json and --plan. A machine-readable contract, whose input schemas are derived at run time from each script's argparse parser (the author's "SPEC" pattern), drives an MCP server that lists a core 12 tools by default. The repo also ships per-platform render templates, a doctor capability check, a test suite and evals. It is useful as a worked example of a deterministic, verifiable skill/tool layer in which the agent supplies judgement and the tools do the work.
How to use it
Install targets differ by agent. The npx installer copies files, and a copy does not update itself (re-run npx ffmpeg-skill to refresh it).
npx ffmpeg-skill # Claude Code → ~/.claude/skills/ffmpeg-skill
npx ffmpeg-skill --cursor # Cursor → ~/.cursor/skills/ffmpeg-skill
npx ffmpeg-skill --codex # Codex → ~/.agents/skills/ffmpeg-skill (Cursor reads this location too)
npx ffmpeg-skill --all # all three
npx ffmpeg-skill --project # this project → ./.claude/skills/ffmpeg-skill
claude plugin install kajisho5/ffmpeg-skill # plugin route, no Node, updates with claude plugin updateAfter installing, check the machine and inspect what an agent framework will see:
npx ffmpeg-skill doctor
npx ffmpeg-skill contract --jsonMCP client config:
{"mcpServers": {"ffmpeg-skill": {"command": "python3", "args": ["/Users/you/.claude/skills/ffmpeg-skill/mcp/server.py"]}}}The scripts also run directly from a shell:
S=~/.claude/skills/ffmpeg-skill/scripts
python3 $S/probe.py input.mp4 --compact
python3 $S/fit.py input.mp4 --duration 60 --aspect 9:16 --dry-run
python3 $S/render.py talk.mp4 --template tiktok --cues cues.txtRequirements
- FFmpeg 5.0+ and Python 3.9+. Node 16+ is needed only for the installer.
- Always required: libx264, aac, and the filters drawtext, subtitles (libass), loudnorm, xfade, acrossfade, scdet, silencedetect and tile.
- The apt and gyan.dev builds have everything. Some Homebrew bottles lack libass, libfreetype or libzimg.
- On macOS,
ffmpeg-fullis keg-only. The skill picks it up automatically only when the lean Homebrewffmpegis the one on PATH.
Interface facts worth knowing before integrating
- Failures: they come back as
{"status": "failed", "error": {"kind": "input | ffmpeg | output | missing_tool | timeout | verification | interrupted", ...}}. - Timeouts: the default is 1800 s, set with
--timeoutorFFMPEG_SKILL_TIMEOUT. A timeout exits with code 124 and removes the partial output. - Smaller output:
--json-briefreturns roughly a third of the bytes of--json. - Doctor exit codes: 0 means all required components are present, 1 means something required is missing, 2 means nothing is proven missing but something is unknown.
- Doctor's overall
okis not per-tool readiness. A plain Homebrew ffmpeg can beokwhilecaptionreportsusable: "no"because the subtitles filter is missing. Readdoctor --json'stoolsfield instead. - MCP surface:
tools/listshows 12 tools by default;FFMPEG_SKILL_MCP_FULL=1lists all 42.- All 42 are callable by name through
tools/calleither way. - The server also exposes five prompt recipes: reel, podcast, multicam, delivery_check, hdr.
- Plans:
--plan FILEsaves a dry run with fingerprinted inputs.render.py FILEexecutes it later and refuses if an input has changed. - Caching:
render.py --cache DIRreuses unchanged stages. Cache keys include the ffmpeg, skill and contract versions. - Stability: 2.x promises that no tool name, CLI argument, JSON key or exit code is removed or renamed until 3.0. A snapshot test enforces this.
- 2.0.0 already removed
--crfin favour of--quality. - 2.0.0 also made writing to an existing output path a refusal unless
--overwriteis passed. - Pinning: dependents should pin a tag or npm version, not
main. Releases are auto-cut from PR labels after merge.
Evidence
Apple VideoToolbox (--hw, opt-in), measured on an M4 Max
- Speed: 2–7× faster than x264/x265 medium.
- Size at matched SSIM: 1.1–2.9× the bytes on SDR and 1.9–3.5× on HDR.
- That size cost is why it is not the default.
CI coverage
- Every PR runs on FFmpeg 5.1.1 (static), 6.1 (Ubuntu), 7.1 (Debian trixie), 8.x (Homebrew macOS) and 9.x (gyan.dev Windows).
- Python 3.9 and 3.13 are both exercised.
- A test runs every tool under
--dry-runbehind a fake ffmpeg and asserts that ffmpeg was never called and no file was written. - Another test hashes every input after a run to confirm it was not modified.
Other material
- The real-device corpus is a ~1.4 GB download (
tests/corpus.py --fetch --verify). - There are benchmarks for sync, silence and scenes, plus regex-graded agent evals in
evals/. - The page gives no numbers for any of these.
Limits
Platform coverage
- The real-footage corpus has been run on Linux and macOS only.
- Neither the full corpus nor a third-party install has been verified on Windows (tracked in issue #143).
- Some fake-ffmpeg tests, including the dry-run test, are skipped on Windows.
No content understanding
look.pyonly renders a PNG. Nothing in the repo detects faces, subjects or interesting moments.fit --fit cropcentre-crops unless the caller supplies--crop-x/-y.scenes.py --highlightsranks scenes by audio level or duration, not by content.- A non-visual caller has to make these choices itself.
Refusals by design
- Filler-word removal needs measured word timings.
- Beat-snapping refuses below
--min-confidence. - Transcription is optional. Without an installed engine (Parakeet or a Whisper variant), it refuses rather than guessing. Those engines download model weights on their first run.
Other caveats
doctor'sgpu_encodersfield shows encoders compiled into ffmpeg. It does not prove the GPU or driver will accept a job.- Sync confidence below 0.3 is probably wrong. Separate-device recordings longer than 10 minutes need
--fix-drift. - A stream-copy cut can start up to one GOP early. The tool re-encodes when the snap exceeds 0.5 s.
- The page states no licence; check the repository before adopting.
Organisations named here
- Claude Code
- Cursor
- kajisho5
- Model Context Protocol
Technologies named here
- ffmpeg-skill
- FFmpeg
- ffprobe
- Claude Code
- Cursor
- Codex
- Claude Desktop
- MCP
- doctor
- contract --json
- render.py
- parakeet-mlx
- faster-whisper
- openai-whisper
- whisper.cpp
- AI-video-production-OS
- Node.js
- npm
- Model Context Protocol
- GitHub Actions
- Whisper
- Parakeet
- Linux
- macOS
- Python
- Windows
Techniques named here
- SPEC
- Probe-edit-verify agent workflow
- Contract-derived MCP server
- Plan before render
- Beat-synced cuts
- Filler word removal
- Caption size fitting
- Phrase-aware caption wrapping
- Sync with drift correction
- Capability detection with unknown state
Related in coding-agents
