Guides

Safe FFmpeg for Claude Code: Probe, Fit, and Verify

Agents invent broken FFmpeg commands. Flag order is backward. Seek parameters miss keyframes. Complex filter strings desynchronize audio or squash pixel aspect ratios. Worst of all, the agent declares success without ever inspecting the rendered file: the shell exited zero, but the resulting video is unplayable.

Prompting harder does not solve syntax hallucinations. The reliable fix is giving your agent a structured skill that enforces probe-first inspection, typed execution, and mandatory frame review before completion.

Workflow diagram illustrating probe first, typed execution, and contact sheet visual verification
The safe agent loop: probe stream parameters, invoke modular typed tools, and inspect contact sheets before finishing.

Step 0: machine preconditions

The skill is a local Python wrapper around system binaries: it never uploads files to a cloud API. Both ffmpeg and ffprobe must exist on your system PATH before you load the skill.

Command: ffmpeg -version
Output: ffmpeg version 7.1
Command: ffprobe -version
Output: ffprobe version 7.1
Comment: macOS: brew install ffmpeg-full | Ubuntu: sudo apt install ffmpeg | Windows: winget install Gyan.FFmpeg
Confirm ffmpeg and ffprobe are on your PATH. On macOS install ffmpeg-full to avoid missing filters.

Step 1: install kajisho5/ffmpeg-skill

The open-source kajisho5/ffmpeg-skill packages 42 structured Python tools for Claude Code, Cursor, and Codex. It runs locally using the standard library, passing arguments as discrete lists rather than raw shell strings.

Command: npx ffmpeg-skill
Output: Placed SKILL.md, scripts/, templates/, and references/ in your agent configuration
Comment: For other agents: npx ffmpeg-skill --cursor or npx ffmpeg-skill --codex
Run npx without flags for Claude Code. Pass --cursor or --codex for other agent environments.

Do not start every routine session by running doctor: the skill instructions state that doctor is a diagnostic utility for troubleshooting missing tools, not an everyday prerequisite. When run, doctor outputs JSON detailing tool availability and detected hardware encoders.

Step 2: the prompt calibration rule

When prompting Claude Code for video tasks, invoke the skill explicitly and define the completion condition. An unconstrained prompt risks the model falling back to raw shell commands.

Step 3: real 9:16 vertical social cut walkthrough

Here is the exact typed pipeline Claude executes when converting a landscape 16:9 interview into a 60-second vertical Reel. Each stage uses a dedicated script that self-probes its input and output:

Comment: 1. Probe source geometry, audio channels, and duration
Command: python3 scripts/probe.py interview.mp4 --json
Comment: 2. Cut the exact range (0:45 to 1:45)
Command: python3 scripts/cut.py interview.mp4 --start 00:00:45 --end 00:01:45 -o segment.mp4
Comment: 3. Fit to 9:16 vertical using blurred side padding
Command: python3 scripts/fit.py segment.mp4 --aspect 9:16 --fit blur -o reel-fitted.mp4
Comment: 4. Normalize loudness to -14 LUFS for Instagram Reels
Command: python3 scripts/loudness.py reel-fitted.mp4 --target -14 -o reel-final.mp4
Comment: 5. Run platform validation gate
Command: python3 scripts/check.py reel-final.mp4 --platform reels
Comment: 6. Generate 6-frame visual contact sheet
Command: python3 scripts/look.py reel-final.mp4 --tiles 3x2 -o contact-sheet.png
Real commands executed by the agent. Note that aspect refitting and loudness re-encode by definition.

Stream-copy (codec copy) is lightning fast, but it only applies when cutting exactly on keyframes without changing geometry or audio levels. Because vertical fitting changes pixel dimensions and loudness adjusts decibels, those stages re-encode cleanly to avoid corrupted headers.

Illustrative Claude Code session: probe, edit, verify
interview-reels/Probe, Cut, and Contact Sheet Verification
Probe interview.mp4. Extract 0:45 to 1:45, fit to 9:16 vertical 1080x1920, normalize speech audio to -14 LUFS for Reels, and output to reel-cut.mp4. Do not declare success until check passes and you inspect the contact sheet.
Reel edit complete: reel-cut.mp4 is 60.00 seconds at 1080x1920 (9:16 vertical), 29.97 fps, with integrated audio meeting Reels specification at -14.1 LUFS. Platform check passed without warnings, and I verified the 6-frame contact sheet: framing is centered with blurred side-fill and zero visual distortion.
Auto
OpusExtra high
Illustrative Claude Code session showing the tool execution trace: probe inspection, typed tool execution, platform check, and contact sheet visual validation.
Architecture diagram showing the creative code renderer layer, verification gate, and FFmpeg deterministic finishing engine
The division of labor: code renderers like HyperFrames build the scene, while FFmpeg serves as the finishing engine.

Frequently asked questions

  • Does ffmpeg-skill install FFmpeg? No. The skill installs Python scripts and markdown instructions. FFmpeg and ffprobe must already be present on your host machine.
  • Which loudness target should I use? For Instagram Reels and TikTok use -14 LUFS. For podcasts use -16 LUFS with true peak capped at -1.5 dBTP. For broadcast delivery use -23 LUFS.
  • Does stream copy always cut on exact frames? No. Stream copy can only slice at keyframes. Slicing between keyframes without re-encoding causes frozen initial frames. The cut.py script snaps or re-encodes when sub-second accuracy is requested.
  • Can this skill generate animated text from scratch? No. FFmpeg is an editor and encoder. For original motion graphics, use HyperFrames or Remotion where the agent writes HTML or React, and let FFmpeg finish the video.
Stay connected

Never miss a post

Updates on format changes, community features, and skill building.