Skip to main content

A Python-native, code-first video generation framework

Project description

Version

PyMotion

Code-first video generation for Python.
Build professional motion graphics, animated explainers, social ads, and product videos — entirely in Python.

CI PyPI Downloads Python License

mypy strict Coverage Ruff Security Audit Tests


Why PyMotion?

Most video tools force you into a GUI timeline. PyMotion doesn't. You write Python, you get broadcast-quality video. No templates to fight, no drag-and-drop constraints — just code that renders frames.

It ships with a Cairo 2D backend, a ModernGL 3D pipeline, FreeType+HarfBuzz typography, a full audio DSP chain, and 15 FFmpeg export presets out of the box. One pip install, one comp.render() call, done.

from pymotion import Composition, ColorClip, TextClip, Track

comp = Composition(1920, 1080, fps=30, duration=150)

track = Track(name="main")
bg = ColorClip(color="#1a1a2e")
bg.set_duration(150)
track.add(bg)

title = TextClip("Hello, PyMotion!", font="Arial", size=72.0, color="#FFFFFF")
title.set_duration(150).set_position(480.0, 500.0)
track.add(title)

comp.add_track(track)
comp.render("output.mp4", preset="h264_1080p")

That's a full 1080p video in 12 lines.


Features

2D Rendering Color, image, shape, gradient, and text clips — Cairo backend
3D Rendering PBR materials, point/spot/directional/ambient lights, SSAO, bloom, DOF (ModernGL headless)
Animation Keyframe tracks, 30+ easing functions, spring physics, cubic bezier curves
Typography FreeType + HarfBuzz shaping, variable fonts, 9 animated text presets (Typewriter, CountUp, Scramble, ...)
Audio Mixing, EQ, compressor, limiter, reverb, delay, pitch shift, beat detection, waveform analysis
Effects 30+ visual/color/distortion/light effects (blur, grain, glow, LUT, wave warp, god rays, ...)
Keying ChromaKey, LumaKey, ColorKey, DifferenceKey — with feathering, choking, despill
Editing Split, join, subclip, repeat, freeze frame, concatenate with transitions
Speed/Time Uniform speed, speed ramp, reverse, time remap, optical flow slow-motion
Layout Picture-in-picture, grid, split screen, stack — named anchor positioning
Tracking Motion tracking, video stabilization, follow-tracker binding
Proxy Low-res proxy generation with disk cache for fast preview
Transitions 39 built-in (fade, slide, wipe, zoom, glitch, film burn, shatter, vortex, ...)
Particles 9 presets — fire, sparkles, confetti, rain, smoke, stars, dust, explosion, bubbles
Export 15 presets — H.264, H.265, ProRes, AV1, WebM, GIF, PNG/EXR frame sequences
Batch Template system with field validation for data-driven video generation
Color .cube LUT loading, lift/gamma/gain grading, ACES/Reinhard/Filmic tone mapping
CLI render, preview, benchmark, validate, doctor, new

Installation

Prerequisites: Python 3.12+, FFmpeg, Cairo

# macOS
brew install ffmpeg cairo pkg-config

# Ubuntu / Debian
sudo apt-get install ffmpeg libcairo2-dev pkg-config libfreetype6-dev

# Windows (via chocolatey)
choco install ffmpeg cairo

Install from PyPI:

pip install pymotion-studio

With extras:

pip install "pymotion-studio[3d-extras]"     # GLTF model loading
pip install "pymotion-studio[gpu-compute]"   # wgpu acceleration
pip install "pymotion-studio[jit]"           # Numba JIT compilation
pip install "pymotion-studio[dev]"           # Development tools

Note: The Python import name is pymotion (no hyphen):

from pymotion import Composition, ColorClip, Track

Quick Start

Animated Text with Particles

from pymotion import Composition, ColorClip, Track
from pymotion.text.animated import Typewriter
from pymotion.particle.system import sparkles
from pymotion.utils.color import Color

comp = Composition(1920, 1080, fps=30, duration=150)

# Background
bg_track = Track(name="bg")
bg = ColorClip(color="#0D1B2A")
bg.set_duration(150)
bg_track.add(bg)

# Typewriter text
text_track = Track(name="text")
tw = Typewriter(
    text="Welcome to PyMotion",
    font_size=64.0,
    color=Color(1.0, 1.0, 1.0, 1.0),
    chars_per_frame=1.5,
)
tw.set_duration(150).at(10)
text_track.add(tw)

# Sparkle particles
fx_track = Track(name="fx")
sparks = sparkles(1920, 1080).to_clip(150)
sparks.set_duration(150)
fx_track.add(sparks)

comp.add_track(bg_track)
comp.add_track(text_track)
comp.add_track(fx_track)
comp.render("intro.mp4", preset="h264_1080p")

Batch Rendering with Templates

from pymotion import Template, Composition, ColorClip, TextClip, Track

class ProductVideo(Template):
    product_name: str
    brand_color: str = "#FF5500"

    def build(self) -> Composition:
        comp = Composition(1920, 1080, fps=30, duration=90)
        track = Track(name="main")
        bg = ColorClip(color=self.brand_color)
        bg.set_duration(90)
        track.add(bg)
        label = TextClip(self.product_name, font="Arial", size=80.0, color="#FFFFFF")
        label.set_duration(90).set_position(600.0, 480.0)
        track.add(label)
        comp.add_track(track)
        return comp

for name in ["Widget Pro", "Gadget X", "Tool Kit"]:
    ProductVideo(product_name=name).render(f"{name.lower().replace(' ', '_')}.mp4")

Examples

Five production-ready scripts ship with the repo, each targeting a real-world use case:

# Script Niche What It Demonstrates
01 real_estate_tour.py Property listings ImageClip slideshow, Typewriter text, sparkle particles, 7-track composition
02 tech_review_intro.py YouTube intros CountUp stats, radial/conic gradients, fire particles
03 fitness_social_ad.py Instagram/TikTok Vertical 1080x1920, CountDown timer, confetti, LetterByLetter
04 restaurant_menu_promo.py Menu promotions WordByWord reveals, stars particles, ShapeClip polygons
05 educational_explainer.py E-learning LetterByLetter titles, CountUp counters, diagram shapes
python examples/download_assets.py     # grab stock images (~5 MB)
python examples/01_real_estate_tour.py  # render

CLI

pymotion render scene.py -o out.mp4 -p h264_1080p   # render a composition
pymotion export-frame scene.py -f 30 -o thumb.png    # export single frame
pymotion benchmark scene.py -n 100                    # measure frame throughput
pymotion doctor                                       # verify system dependencies
pymotion validate scene.py                            # check composition integrity
pymotion new my-project                               # scaffold a new project

Architecture

pymotion/
├── animation/     Keyframe tracks, 30+ easings, spring, bezier, interpolation
├── audio/         Mixer, DSP effects (EQ, compressor, reverb, ...), beat detection
├── clip/          ColorClip, ImageClip, ShapeClip, TextClip, VideoClip, Scene3DClip
├── effects/       Visual, color, distortion, light effect processors
├── export/        FFmpeg encoder, 15 output presets
├── particle/      Vectorized particle system, 9 preset generators
├── render/        Cairo 2D, ModernGL 3D, compositor, color pipeline
├── security/      Path traversal, color, asset magic-byte, text sanitization validators
├── template/      Template ABC with field validation for batch rendering
├── text/          FreeType/HarfBuzz renderer, 9 animated text presets
├── transition/    39 transition implementations
├── utils/         Color (OKLCH), Vec2/Vec3, logging (structlog)
└── cli/           Click-based CLI (render, preview, benchmark, doctor, ...)

Internal frame format: BGRA uint8 NumPy arrays (H, W, 4) — matches Cairo ARGB32 on little-endian. The compositor uses bounding-box sparse blending with uint16 fixed-point fast paths for opaque layers and alpha-info caching for transparency detection.


Performance

Benchmarked on a typical 7-layer 1080p composition:

Metric Value
Frame render throughput ~75 fps (13 ms/frame)
12s video end-to-end ~7s wall time (2.5x realtime)
Static layer caching Single render, reused across frames
Particle simulation Vectorized NumPy — no per-particle Python loops
FFmpeg encoding Multi-threaded, contiguous frame pipe, zero-copy

Development

git clone https://github.com/Ohswedd/pymotion.git
cd pymotion
pip install -e ".[dev]"

make lint      # ruff format + ruff check + mypy --strict
make test      # pytest with coverage (85% minimum)
make clean     # remove caches and build artifacts

Running Tests

pytest -v                              # full suite (1285 tests)
pytest tests/unit/ -v                  # unit tests only
pytest tests/integration/ -v           # integration tests
pytest --cov=pymotion --cov-report=html  # coverage report

Docker

docker build -t pymotion .
docker run --rm -v $(pwd)/output:/app/output pymotion render scene.py -o output/video.mp4

System Dependencies

Dependency Purpose Bundled?
FFmpeg Video/audio encoding No — install separately
Cairo 2D vector rendering No — install separately
FreeType Font rasterization Yes (via freetype-py)
HarfBuzz Text shaping Yes (via uharfbuzz)
ModernGL 3D PBR rendering Yes (via pip)

Run pymotion doctor to verify your environment.


License

PyMotion is released under the PyMotion Source Available License 1.0.

What you can do:

  • Use PyMotion in any project, including commercial products
  • Fork the repo and modify the code for your own use
  • Contribute back via pull requests

What you cannot do:

  • Redistribute, rebrand, or republish PyMotion as a standalone library
  • Sell, sublicense, or commercially exploit the library itself
  • Publish modified versions to any package registry

Read the full LICENSE for details.

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

pymotion_studio-1.2.1.tar.gz (5.9 MB view details)

Uploaded Source

Built Distribution

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

pymotion_studio-1.2.1-py3-none-any.whl (155.3 kB view details)

Uploaded Python 3

File details

Details for the file pymotion_studio-1.2.1.tar.gz.

File metadata

  • Download URL: pymotion_studio-1.2.1.tar.gz
  • Upload date:
  • Size: 5.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymotion_studio-1.2.1.tar.gz
Algorithm Hash digest
SHA256 e4530d3e8c3fbad170db58bac961ec234643f4f87faf406372dd278e64b47a12
MD5 ff5477257a898ff7c73a9d69927f424e
BLAKE2b-256 0f518b6b0ff2af2751479980dd1e85734aacf2730c200da0f5328e72d4382118

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymotion_studio-1.2.1.tar.gz:

Publisher: publish.yml on Ohswedd/pymotion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymotion_studio-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: pymotion_studio-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 155.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pymotion_studio-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d3cb44f00614cb3b856924e800f501a3fa392e78679ba594c37e35e2ff21f9ef
MD5 9b874dd76b4281e78198c412edfdb4fc
BLAKE2b-256 441dcc8baf1d2cf3c92db42457079109c64e5685e9e0c7eaf5868702e4293761

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymotion_studio-1.2.1-py3-none-any.whl:

Publisher: publish.yml on Ohswedd/pymotion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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