Agent-first video cutting library — declarative JSON edits powered by FFmpeg
Project description
CutAgent
Agent-first video cutting library — declarative JSON edits powered by FFmpeg.
CutAgent is designed from the ground up for AI agents and programmatic video editing. Every CLI command outputs structured JSON. Every operation is composable through a declarative Edit Decision List (EDL) format. No GUI, no human-formatted text — just clean machine-readable interfaces for professional video cutting.
Why CutAgent?
- Agent-first: Every command returns structured JSON — built for LLM tool use, not human eyes
- Declarative EDL: Describe your edit as a JSON document, execute it in one call
- Zero runtime dependencies: Pure Python + FFmpeg — or
pip install 'cutagent[ffmpeg]'to bundle everything - Content intelligence: Scene detection, silence detection, audio levels, keyframe analysis, beat detection
- Professional operations: Trim, split, concat, reorder, extract, fade with crossfade transitions
- Audio-aware editing: Mix background music, adjust volume, replace audio, normalize loudness (EBU R128)
- Structured errors: Error codes, recovery hints, and context in every failure response
Requirements
- Python 3.10+
- FFmpeg and FFprobe (see setup options below)
Installation
pip install cutagent
With bundled FFmpeg (no separate install needed):
pip install 'cutagent[ffmpeg]'
This uses static-ffmpeg to auto-download ffmpeg + ffprobe binaries on first use. Works on Windows, macOS (Intel + Apple Silicon), and Linux.
From source (development):
git clone https://github.com/DaKev/cutagent.git
cd cutagent
pip install -e ".[dev]"
FFmpeg Setup
CutAgent needs ffmpeg and ffprobe. It searches for them in this order:
- Environment variables
CUTAGENT_FFMPEG/CUTAGENT_FFPROBE(exact path to binary) - Environment variable
CUTAGENT_FFMPEG_DIR(directory containing both binaries) - System PATH (
ffmpeg/ffprobeon$PATH) - static-ffmpeg package (if installed via
pip install 'cutagent[ffmpeg]') - imageio-ffmpeg package (ffmpeg only, if installed)
Platform-specific install (if not using cutagent[ffmpeg]):
| Platform | Command |
|---|---|
| macOS | brew install ffmpeg |
| Ubuntu/Debian | sudo apt install ffmpeg |
| Windows | winget install ffmpeg or choco install ffmpeg |
Verify your setup:
cutagent doctor
This checks for ffmpeg/ffprobe, reports versions, and flags any issues.
Quick Start
Python API
from cutagent import probe, trim, execute_edl
# Inspect a video
info = probe("interview.mp4")
print(info.duration, info.width, info.height)
# Trim a segment
result = trim("interview.mp4", start="00:02:15", end="00:05:40", output="clip.mp4")
# Execute a full edit decision list
edl = {
"version": "1.0",
"inputs": ["interview.mp4"],
"operations": [
{"op": "trim", "source": "interview.mp4", "start": "00:02:15", "end": "00:05:40"},
{"op": "trim", "source": "interview.mp4", "start": "00:12:00", "end": "00:14:30"},
{"op": "concat", "segments": ["$0", "$1"]}
],
"output": {"path": "highlight.mp4", "codec": "copy"}
}
result = execute_edl(edl)
CLI (AI-Native — all output is JSON)
# Discover capabilities (returns machine-readable schema)
cutagent capabilities
# Probe a video
cutagent probe interview.mp4
# Get keyframe positions
cutagent keyframes interview.mp4
# Detect scene boundaries
cutagent scenes interview.mp4 --threshold 0.3
# Build a full content summary (scenes + silence + audio levels)
cutagent summarize interview.mp4
# Trim
cutagent trim interview.mp4 --start 00:02:15 --end 00:05:40 -o clip.mp4
# Split at multiple points
cutagent split interview.mp4 --at 00:05:00,00:10:00 --prefix segment
# Concatenate
cutagent concat clip1.mp4 clip2.mp4 -o merged.mp4
# Extract audio
cutagent extract interview.mp4 --stream audio -o audio.aac
# Detect musical beats (for rhythm-aligned cuts)
cutagent beats interview.mp4
# Mix background music into a video
cutagent mix interview.mp4 --audio music.mp3 --mix-level 0.2 -o with_music.mp4
# Adjust audio volume
cutagent volume interview.mp4 --gain-db 6.0 -o louder.mp4
# Replace audio track
cutagent replace-audio interview.mp4 --audio voiceover.mp3 -o replaced.mp4
# Normalize audio loudness (EBU R128)
cutagent normalize interview.mp4 -o normalized.mp4
# Validate an EDL without executing
cutagent validate edit.json
# Execute an EDL
cutagent execute edit.json
EDL Format
The Edit Decision List is a declarative JSON format for multi-step edits. Operations run sequentially; $N references the output of operation N:
{
"version": "1.0",
"inputs": ["interview.mp4", "broll.mp4", "background_music.mp3"],
"operations": [
{"op": "trim", "source": "$input.0", "start": "00:01:00", "end": "00:03:00"},
{"op": "trim", "source": "$input.1", "start": "00:00:10", "end": "00:00:20"},
{"op": "normalize", "source": "$0"},
{"op": "fade", "source": "$1", "fade_in": 0.5, "fade_out": 0.5},
{"op": "concat", "segments": ["$2", "$3"], "transition": "crossfade", "transition_duration": 0.5},
{"op": "mix_audio", "source": "$4", "audio": "$input.2", "mix_level": 0.15}
],
"output": {"path": "final.mp4", "codec": "libx264"}
}
Available operations: trim, split, concat, reorder, extract, fade, speed, mix_audio, volume, replace_audio, normalize
Architecture
┌──────────────────────────────────────────────────────────────────┐
│ cutagent (CLI / Python API) │
├──────────────────┬─────────────────┬─────────────────────────────┤
│ cli.py │ engine.py │ validation.py │
│ JSON output │ EDL execution │ Dry-run validation │
├──────────────────┼─────────────────┼─────────────────────────────┤
│ probe.py │ operations.py │ models.py │
│ Media analysis │ Video ops │ Typed dataclasses │
│ + beat detect │ audio_ops.py │ │
│ │ Audio ops │ │
├──────────────────┴─────────────────┴─────────────────────────────┤
│ ffmpeg.py (subprocess wrappers) │ errors.py (error codes) │
└──────────────────────────────────────────────────────────────────┘
ffmpeg.pyis the only module that spawns subprocessesmodels.pyanderrors.pyhave zero internal dependencies- All public functions return typed dataclasses, never raw dicts
- The CLI outputs JSON exclusively — designed for machine consumption
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Validation error (bad input, invalid EDL) |
| 2 | Execution error (FFmpeg failed) |
| 3 | System error (FFmpeg not found, permissions) |
Error Handling
Every error includes a code, message, and recovery suggestions:
{
"error": true,
"code": "TRIM_BEYOND_DURATION",
"message": "End time 01:00:00 (3600.000s) exceeds duration (120.500s)",
"recovery": [
"Source duration is 120.500s — set end to 120.500 or less",
"Run 'cutagent probe <file>' to check the actual duration"
],
"context": {"source": "clip.mp4", "duration": 120.5, "end": "01:00:00"}
}
Contributing
Contributions are welcome! Please read CONTRIBUTING.md for guidelines on:
- Setting up the development environment
- Architecture principles and code style
- Adding new operations
- The JSON output contract
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cutagent-0.3.0.tar.gz.
File metadata
- Download URL: cutagent-0.3.0.tar.gz
- Upload date:
- Size: 67.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d12e6748f999778abd9b3d2767bff3960be794b1e275f265cfe719d01765667
|
|
| MD5 |
99b7a9b88cebce3915df87a4fda1d54d
|
|
| BLAKE2b-256 |
33eb1cdcc2a78af7770e3d0cbfa85d70dc9ad99bc6138c297479d12126e15edd
|
Provenance
The following attestation bundles were made for cutagent-0.3.0.tar.gz:
Publisher:
publish.yml on DaKev/cutagent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cutagent-0.3.0.tar.gz -
Subject digest:
8d12e6748f999778abd9b3d2767bff3960be794b1e275f265cfe719d01765667 - Sigstore transparency entry: 962714125
- Sigstore integration time:
-
Permalink:
DaKev/cutagent@d1db2264394aaa6042347e809c0403dd82be035e -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/DaKev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d1db2264394aaa6042347e809c0403dd82be035e -
Trigger Event:
release
-
Statement type:
File details
Details for the file cutagent-0.3.0-py3-none-any.whl.
File metadata
- Download URL: cutagent-0.3.0-py3-none-any.whl
- Upload date:
- Size: 55.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c606a7369bc86d12ff449dd1ac632da96599f631d12d10efd90ffb695b98fc33
|
|
| MD5 |
1fdde1482c875e05a7658cf0000abcf8
|
|
| BLAKE2b-256 |
ccabb06a6da778338e879dfea48860cf3b811a7da4810f97ec6a7d983165ff16
|
Provenance
The following attestation bundles were made for cutagent-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on DaKev/cutagent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cutagent-0.3.0-py3-none-any.whl -
Subject digest:
c606a7369bc86d12ff449dd1ac632da96599f631d12d10efd90ffb695b98fc33 - Sigstore transparency entry: 962714127
- Sigstore integration time:
-
Permalink:
DaKev/cutagent@d1db2264394aaa6042347e809c0403dd82be035e -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/DaKev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d1db2264394aaa6042347e809c0403dd82be035e -
Trigger Event:
release
-
Statement type: