Skip to main content

559 named video transitions across four render backends

Project description

cut-fx

559 named video transitions across four render backends, with GPU acceleration when available.

Built at Trollfabriken AITrix AB to make programmatic video rendering match the visual vocabulary of consumer video editors. Five-hundred-and-fifty-nine named transitions across eleven taxonomy buckets, mapped to thirty-four hand-written base engines and parametric variants. Four render backends: ffmpeg filter_complex, NumPy/OpenCV procedural, HTML/CSS via web-overlay, and GLSL shaders. GPU acceleration when available, CPU fallback when not. One API: apply_transition(clip_a, clip_b, transition="atomic_teleport", output=...).


What it solves

Programmatic batch video rendering — AIMOS Insight municipal report videos, civic-education explainers, pipeline-driven content — needs named, repeatable transitions. ffmpeg's xfade covers dissolves. It does not cover 559 named effects. Writing each effect from scratch is not feasible.

Problem What cut-fx does
Named transitions not in ffmpeg xfade 559 catalog entries map to 34 base engines
Different effects need different render tech Four backends; catalog picks the right one
GPU present on some machines, absent on others Runtime detection; CPU fallback always works
LLMs need a machine-readable transition spec JSON schema export via cut_fx.schema
Beat-aligned cuts require audio analysis cut_fx.beats wraps audio-arrange
Lyric-timed transitions Optional lyric-sync integration

Installation

pip install cut-fx

Runtime requirement: ffmpeg >= 6.0 must be on PATH.

# Ubuntu / Debian
sudo apt-get install ffmpeg

# macOS
brew install ffmpeg

# Windows
choco install ffmpeg

Extras:

Extra Installs Enables
overlay web-overlay HTML/CSS/SVG transitions (light_fx, particle_nature, graphic_stylized)
shader moderngl, moderngl-window GLSL shader transitions; requires OpenGL 3.3+
beats audio-arrange, librosa Beat-synced cut placement
lyrics lyric-sync Lyric-timed transitions
all all of the above Full feature set
dev pytest, ruff, build, pillow Development tools
pip install "cut-fx[overlay,shader,beats]"
pip install "cut-fx[all]"

Quick start

from cut_fx import apply_transition

apply_transition(
    clip_a="intro.mp4",
    clip_b="main.mp4",
    transition="atomic_teleport",
    output="combined.mp4",
    overlap_seconds=0.8,
)

List what is available:

from cut_fx import list_transitions, list_categories

list_categories()
# ['motion', 'rotation', 'shape_mask', 'optical_blur', 'light_fx',
#  'particle_nature', 'graphic_stylized', 'digital_glitch',
#  'grid_card_layout', 'film_retro', 'general_fx']

list_transitions(category="digital_glitch")
# ['Capture Glitch 2', 'Console Buzz', 'Cyber Beehive', 'Cyber Flare',
#  'Cyber Phantom', 'Hologram Shred', ...]

Inspect a specific transition:

from cut_fx import get_transition_info

info = get_transition_info("cyber_phantom")
# TransitionInfo(
#     name='Cyber Phantom',
#     slug='cyber_phantom',
#     category='digital_glitch',
#     base_engine='glitch_scan',
#     parameters={'intensity': 0.7, 'scan_lines': 12, 'color_shift': True},
#     backends=['procedural', 'shader'],
# )

The catalog

The catalog (cut_fx/data/transitions_catalog.json) lists 559 transition names across 11 taxonomy buckets. Behind those names are 34 base engine implementations. Each base engine accepts parameters: direction, easing, intensity, colour, shape, count, duration curve.

The 559 → 34 design: a named transition is a (base_engine, parameter_set) tuple. Adding a new named variant means adding one JSON entry — no new Python code.

Bucket Transitions Base engines Example named variants
motion 119 4 180 Wipe, Block Slides, Push Right
light_fx 93 5 Basic Flash, Bright Flash, Crescent Sparks
grid_card_layout 47 3 3-block Swing, 3D Card 2, Bizarre Rubik
rotation 46 3 3-flap Turn, 3D Flip, Calendar Flip
shape_mask 44 4 Circle, Comic Cutout, Blast Door
film_retro 35 3 B&W Arrows, Black Smoke, Black Fade
optical_blur 31 3 Auto Focus, Blur & Zoom, Blur Focus
particle_nature 22 3 Bubble Blur, Crystal Energy, Dust Flurry
digital_glitch 16 4 Cyber Phantom, Hologram Shred, Console Buzz
graphic_stylized 12 2 Comic Cut, Glowing Graffiti, Light Graffiti I
general_fx 94 (composed) 3D Glass, Atomic Teleport, Acrylic Fades

The general_fx bucket entries are composed from existing base engines. "Atomic Teleport" is a light_fx flash + shape_mask radial + motion zoom-out, assembled in sequence.

Inspect catalog totals at runtime:

from cut_fx.catalog import catalog_summary

print(catalog_summary())
# {'total': 559, 'categories': 11, 'base_engines': 34, ...}

Render engines

Each catalog entry specifies which backend handles it. The dispatch is automatic.

Engine Handles Implementation
ffmpeg motion, rotation, optical_blur, simple wipes filter_complex with crop/scale/translate/rotate expressions; xfade for cross-dissolves
procedural digital_glitch, film_retro, custom pixel math NumPy + OpenCV; frame-by-frame in Python
overlay light_fx, particle_nature, graphic_stylized, shape_mask HTML/CSS/SVG via web-overlay; alpha-composited over ffmpeg base
shader Premium light_fx variants, refraction, fluid sim GLSL via moderngl; optional; CPU fallback to procedural when absent

The overlay engine requires pip install "cut-fx[overlay]" and a headless Chromium install (playwright install chromium). The shader engine requires pip install "cut-fx[shader]" and OpenGL 3.3+ context support.

Force a specific backend:

apply_transition(
    clip_a="a.mp4",
    clip_b="b.mp4",
    transition="basic_flash",
    output="out.mp4",
    backend="procedural",  # override automatic selection
)

Hardware acceleration

At import time, cut_fx probes for hardware encoders and GPU context.

from cut_fx.gpu import gpu_status

print(gpu_status())
# {
#   'ffmpeg_hwaccel': 'nvenc',       # or 'videotoolbox', 'qsv', None
#   'opengl_available': True,
#   'opengl_renderer': 'NVIDIA GeForce RTX 3080',
#   'shader_backend': 'moderngl',    # or 'procedural' (fallback)
# }

Acceleration paths:

  • ffmpeg hardware encoders: NVENC (NVIDIA), VideoToolbox (Apple), QSV (Intel). Detected via ffmpeg -hwaccels. Falls back to libx264/libx265 when none is found.
  • GLSL shader engine: requires a real GPU context. Falls back to the procedural (NumPy/OpenCV) implementation automatically — output is identical, speed is lower.

Print a summary from the CLI:

cut-fx gpu

No GPU is required. All 559 transitions render on CPU.


Beat-synced cuts

Requires pip install "cut-fx[beats]".

from cut_fx.beats import transitions_on_beats

transitions_on_beats(
    clips=["clip1.mp4", "clip2.mp4", "clip3.mp4", "clip4.mp4"],
    audio="track.mp3",
    transition="cyber_phantom",
    output="beat_video.mp4",
    beats_per_cut=2,       # place a cut every 2 beats
    overlap_seconds=0.4,
)

transitions_on_beats uses audio-arrange to extract beat timestamps, then places transitions at beat boundaries. The beats_per_cut parameter controls cut density. Fractional values are supported: beats_per_cut=0.5 cuts on every half-beat.

For lyric-timed cuts, add pip install "cut-fx[lyrics]":

from cut_fx.beats import transitions_on_lyrics

transitions_on_lyrics(
    clips=["verse.mp4", "chorus.mp4"],
    lyrics_file="song.lrc",
    transition="light_burst",
    output="lyric_video.mp4",
)

LLM integration

cut_fx.schema exports a JSON Schema describing every valid transition call. Pass it to an LLM as a tool definition.

from cut_fx.schema import transition_spec_schema

schema = transition_spec_schema()
# {
#   "$schema": "https://json-schema.org/draft/2020-12/schema",
#   "title": "TransitionSpec",
#   "type": "object",
#   "properties": {
#     "transition": {"type": "string", "enum": ["atomic_teleport", "cyber_phantom", ...]},
#     "overlap_seconds": {"type": "number", "minimum": 0.1, "maximum": 5.0},
#     "backend": {"type": "string", "enum": ["auto", "ffmpeg", "procedural", "overlay", "shader"]},
#     ...
#   },
#   "required": ["transition"]
# }

Feed the schema to an LLM as a function spec. The LLM returns a valid TransitionSpec object. Pass it directly to apply_transition:

from cut_fx import apply_transition
from cut_fx.config import TransitionConfig

spec = TransitionConfig(**llm_response)
apply_transition(clip_a="a.mp4", clip_b="b.mp4", output="out.mp4", **spec.model_dump())

CLI

Apply a transition between two clips:

cut-fx apply intro.mp4 main.mp4 --transition atomic_teleport --output combined.mp4

List all transitions in a category:

cut-fx list --category digital_glitch

List all categories with transition counts:

cut-fx categories

Show detail for a named transition:

cut-fx info cyber_phantom

Render a short preview (3-second synthetic clips):

cut-fx preview atomic_teleport --output preview.mp4

Show GPU and hardware encoder status:

cut-fx gpu

Package structure

cut-fx/
├── src/
│   └── cut_fx/
│       ├── __init__.py          # public API re-exports
│       ├── api.py               # apply_transition, apply_sequence, list_*
│       ├── catalog.py           # loads transitions_catalog.json
│       ├── config.py            # TransitionConfig (pydantic model)
│       ├── schema.py            # JSON schema export for LLM tool use
│       ├── gpu.py               # hardware detection
│       ├── beats.py             # beat-synced and lyric-synced cuts
│       ├── cli.py               # cut-fx command-line entry point
│       ├── data/
│       │   ├── transitions_catalog.json   # 559 entries
│       │   └── engine_mapping.json        # slug → base_engine lookup
│       └── engines/
│           ├── base.py          # abstract BaseEngine
│           ├── dispatcher.py    # selects engine per catalog entry
│           ├── ffmpeg/          # filter_complex builder
│           ├── procedural/      # NumPy + OpenCV per-frame
│           ├── overlay/
│           │   └── templates/   # HTML/CSS/SVG transition templates
│           └── shader/
│               └── glsl/        # .vert / .frag shader sources
├── tests/
├── pyproject.toml
├── README.md
└── LICENSE

© Trollfabriken AITrix AB — MIT licensed

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

cut_fx-0.1.3.tar.gz (87.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cut_fx-0.1.3-py3-none-any.whl (108.4 kB view details)

Uploaded Python 3

File details

Details for the file cut_fx-0.1.3.tar.gz.

File metadata

  • Download URL: cut_fx-0.1.3.tar.gz
  • Upload date:
  • Size: 87.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for cut_fx-0.1.3.tar.gz
Algorithm Hash digest
SHA256 4007f92bdbf1747852e032fff0664ea434a43ecc97ad9540e4b4e2664d549733
MD5 18ef69d34ab3d05c130f022d6f7ee736
BLAKE2b-256 f9eb585dfc90f399a6a54a789b9941022a5b44b45c291c349121fbad40c73f0c

See more details on using hashes here.

File details

Details for the file cut_fx-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: cut_fx-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 108.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for cut_fx-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 fd60d59760b95314e40b0febaccc951b4c06e3eacbfb39672e82caab1d2aa51b
MD5 d2dbad446a6b16c999053f263c03eb0c
BLAKE2b-256 982ea985aac5845baccca04f245c8acd69c165191e2c3390d6f01cd5e04ce4e6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page