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, ...)
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.11+, 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 (1116 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.0.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.0.1-py3-none-any.whl (133.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pymotion_studio-1.0.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.0.1.tar.gz
Algorithm Hash digest
SHA256 4967555336865d03cbd9699aed58b4d3567ae8c2bf4c7d0a6ff7ac1d0377fb8c
MD5 fd363fe4297c5649eb6a9e5fceee1be4
BLAKE2b-256 46b02a441f5375d504429b1d56a326c5241ddab5fb1697ea8ce1f26b0f29f2c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymotion_studio-1.0.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.0.1-py3-none-any.whl.

File metadata

  • Download URL: pymotion_studio-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 133.2 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.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e4081a41eafedff8ebf143cfebebf4e6f8d6083c06db2a737607ff2ef54d7fc5
MD5 c5225a17842efcde7ea0f616306abf37
BLAKE2b-256 ce0030e930d395b92a6537eff169b13fb939b3f22b4c047e439fe1de5e65a6cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymotion_studio-1.0.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