Skip to main content

A performance-oriented Python video editing library focused on speed and simplicity.

Project description

MovieLite

A fast and intuitive Python video editing library, designed as a lightweight alternative to MoviePy.

MovieLite Demo

The animation above was fully generated using MovieLite itself!
Check out the code here.

Overview

MovieLite is a Python video editing library built with a focus on speed and simplicity for common workflows. It offers a clean, chainable API that will feel familiar to MoviePy users, but delivers significant performance gains for CPU-based rendering.

The library achieves this speed by leveraging Numba's JIT compilation for critical operations like alpha blending and transformations. While it doesn't aim for feature-for-feature parity with MoviePy and currently lacks GPU acceleration, it excels at providing a much faster experience for everyday tasks, such as:

  • Applying transformations (zoom, position, scale).
  • Compositing overlays (text, images, other videos).
  • Rendering projects with multiple effects.

If you love MoviePy's approach but need a significant speed boost for your CPU-bound projects, MovieLite is for you.

Key Features

  • Frame-by-frame processing: Full control over every frame and audio sample
  • Performance optimized: Uses Numba JIT compilation for critical rendering operations
  • Clean API: Chainable methods for intuitive video editing workflows
  • Comprehensive effects library: Built-in visual effects (vfx), audio effects (afx), and transitions (vtx)
  • Multiprocessing support: Parallel rendering for faster video generation
  • Audio mixing: Mix multiple audio tracks with per-sample control
  • Memory efficient: Streaming architecture for large video files

Performance Comparison

MovieLite is designed to be faster than moviepy for common video editing tasks. Performance improvements come from:

  1. Numba JIT compilation: Critical rendering loops are compiled to native code
  2. Optimized compositing: Efficient alpha blending and frame composition
  3. Memory management: Streaming architecture reduces memory footprint
  4. Multiprocessing: Parallel frame rendering for multi-core systems

Benchmark Results

To run benchmarks comparing movielite with moviepy 2.2.1:

python benchmarks/compare_moviepy.py --input /path/to/input

Real benchmark results (1280x720 video, 30fps):

Task movielite moviepy Speedup
No processing 6.34s 6.71s 1.06x 🚀
Video zoom 9.52s 31.81s 3.34x 🚀
Fade in/out 8.53s 9.03s 1.06x 🚀
Text overlay 7.82s 35.35s 4.52x 🚀
Video overlay 18.22s 75.47s 3.14x 🚀
Alpha video overlay 10.75s 42.11s 3.92x 🚀
Complex mix* 38.07s 175.31s 4.61x 🚀
Total 99.24s 375.79s 3.79x 🚀

*Complex mix includes: video with zoom + fade, image clips with fade, text overlay, video overlay - all composed together.

movielite excels at:

  • Transform operations (zoom, scale, resize) - up to 3.17x faster
  • Text overlays and compositing - up to 3.75x faster
  • Video overlays and layering - up to 3.83x faster
  • Alpha channel compositing - up to 3.36x faster
  • Complex multi-effect compositions - up to 4.21x faster

Results may vary based on hardware, video codec, and complexity.

Architecture

Frame-by-Frame Processing

Like moviepy, movielite operates on a frame-by-frame basis:

# Every frame is individually processed
for frame_idx in range(total_frames):
    t = frame_idx / fps
    frame = clip.get_frame(t)  # Get raw frame
    frame = apply_transforms(frame, t)  # Apply effects
    frame = blend_with_other_clips(frame, t)  # Composite
    write_frame_to_output(frame)

This approach provides:

  • Complete control over every pixel
  • Ability to apply time-based effects
  • Support for complex compositing operations
  • Memory efficiency through streaming

Numba Optimization

Critical operations are JIT-compiled with Numba:

@numba.jit(nopython=True, cache=True)
def blend_foreground_with_bgr_background_inplace(
    background, foreground, x, y, opacity, mask, ...
):
    # Pixel-perfect alpha blending at native speed
    ...

This provides near-native performance for:

  • Alpha blending operations
  • Pixel-wise transformations
  • Color space conversions

What It Supports

Video Capabilities

  • Video clips with frame-level access
  • Alpha video clips (transparency support via AlphaVideoClip)
  • Image clips (static images as video frames)
  • Text rendering (via pictex library)
  • Mask support for advanced compositing effects
  • Video effects: fade, blur, color adjustments, vignette, zoom, glitch effects
  • Video transitions: crossfade, dissolve, blur dissolve
  • Position, scale, opacity, and size transformations
  • Custom frame transformations
  • Video looping

Audio Capabilities

  • Audio clips with sample-level access
  • Audio effects: fade in/out
  • Volume control and volume curves
  • Multiple audio track mixing
  • Audio from video files
  • Custom audio transformations

Output Formats

  • Video codec: libx264 (H.264)
  • Container format: MP4
  • Audio codec: AAC
  • Quality presets: LOW, MIDDLE, HIGH, VERY_HIGH

Limitations

  • Output is limited to MP4 format with libx264 codec
  • No GPU acceleration (CPU-based rendering only)

Installation

pip install movielite

Requirements

  • Python 3.10+
  • FFmpeg (must be installed and available in PATH)
  • NumPy
  • OpenCV (opencv-python)
  • Numba (for JIT compilation)
  • multiprocess
  • tqdm
  • pictex (for TextClip)

Installing FFmpeg

Windows:

  1. Download FFmpeg from ffmpeg.org
  2. Extract to a permanent location (e.g., C:\ffmpeg)
  3. Add the bin directory to your PATH environment variable

macOS:

brew install ffmpeg

Linux:

sudo apt-get install ffmpeg  # Debian/Ubuntu
sudo yum install ffmpeg      # CentOS/RHEL

Quick Start

Basic Video Editing

from movielite import VideoClip, VideoWriter

# Load and extract a segment
clip = VideoClip("input.mp4")
subclip = clip.subclip(10, 15)  # Extract seconds 10-15

# Create output
writer = VideoWriter("output.mp4", fps=30)
writer.add_clip(
    subclip
    .set_position((100, 100))
    .set_opacity(0.8)
)
writer.write()

clip.close()

Adding Effects

from movielite import VideoClip, VideoWriter, vfx

clip = VideoClip("video.mp4")

# Chain multiple effects
clip.add_effect(vfx.FadeIn(1.0))
clip.add_effect(vfx.FadeOut(1.5))
clip.add_effect(vfx.Blur(intensity=3.0))

writer = VideoWriter("output.mp4", fps=clip.fps, size=clip.size)
writer.add_clip(clip)
writer.write()

clip.close()

Text Overlays

from movielite import VideoClip, TextClip, VideoWriter
from pictex import Canvas, LinearGradient, Shadow

# Create styled text
canvas = (
    Canvas()
    .font_family("Arial")
    .font_size(60)
    .color("white")
    .padding(20)
    .background_color(LinearGradient(["#2C3E50", "#FD746C"]))
    .border_radius(10)
    .text_shadows(Shadow(offset=(2, 2), blur_radius=3, color="black"))
)

video = VideoClip("background.mp4")
text = TextClip("Hello World", start=2, duration=3, canvas=canvas)
text.set_position((video.size[0] // 2 - text.size[0] // 2, 100))

writer = VideoWriter("output.mp4", fps=video.fps, size=video.size)
writer.add_clip(video)
writer.add_clip(text)
writer.write()

video.close()

Concatenating Videos

from movielite import VideoClip, VideoWriter

clip1 = VideoClip("intro.mp4", start=0)
clip2 = VideoClip("main.mp4", start=clip1.end)
clip3 = VideoClip("outro.mp4", start=clip2.end)

writer = VideoWriter("final.mp4", fps=30)
writer.add_clips([clip1, clip2, clip3])
writer.write()

clip1.close()
clip2.close()
clip3.close()

Audio Mixing

from movielite import VideoClip, AudioClip, VideoWriter, afx

video = VideoClip("video.mp4")

# Background music at 50% volume
music = AudioClip("background.mp3", start=0, volume=0.5)
music.add_effect(afx.FadeIn(2)).add_effect(afx.FadeOut(2))

# Sound effect at specific time
sfx = AudioClip("ding.wav", start=5.0, volume=1.0)

writer = VideoWriter("output.mp4", fps=video.fps)
writer.add_clip(video)  # Video includes its own audio track
writer.add_clip(music)
writer.add_clip(sfx)
writer.write()

video.close()

Transitions

from movielite import VideoClip, VideoWriter, vtx

clip1 = VideoClip("scene1.mp4", start=0, duration=5)
clip2 = VideoClip("scene2.mp4", start=4, duration=5)  # 1s overlap

# Apply crossfade transition
clip1.add_transition(clip2, vtx.CrossFade(duration=1))

writer = VideoWriter("output.mp4", fps=30)
writer.add_clips([clip1, clip2])
writer.write()

clip1.close()
clip2.close()

Custom Frame Transformations

import cv2
import numpy as np
from movielite import VideoClip, VideoWriter

clip = VideoClip("video.mp4")

# Apply custom sepia effect
def sepia_transform(frame: np.ndarray, t: float) -> np.ndarray:
    kernel = np.array([
        [0.131, 0.534, 0.272],
        [0.168, 0.686, 0.349],
        [0.189, 0.769, 0.393]
    ])
    sepia = cv2.transform(frame, kernel)
    return np.clip(sepia, 0, 255).astype(np.uint8)

clip.add_transform(sepia_transform)

writer = VideoWriter("output.mp4", fps=clip.fps)
writer.add_clip(clip)
writer.write()

clip.close()

Masking for Advanced Compositing

import numpy as np
from movielite import VideoClip, TextClip, VideoWriter
from pictex import Canvas

# Video to be masked
video = VideoClip("waves.mp4", start=0, duration=10)

# Create text as mask
canvas = Canvas().font_size(200).color("white").background_color("transparent")
text = TextClip("Hello World!", start=0, duration=10, canvas=canvas)

# Animate mask position and scale
text.set_position(lambda t: (
    960 - text.size[0] // 2,
    500 + int(20 * np.sin(2 * np.pi * (t / text.duration)))
))
text.set_scale(lambda t: 1.0 + 0.4 * (t / text.duration))

# Apply mask - video only visible through text
video.set_mask(text)
video.set_size(1920, 1080)

writer = VideoWriter("output.mp4", fps=30, size=(1920, 1080))
writer.add_clip(video)
writer.write()

video.close()

Multiprocessing for Faster Rendering

from movielite import VideoClip, VideoWriter, VideoQuality

clip = VideoClip("input.mp4")

writer = VideoWriter("output.mp4", fps=clip.fps, size=clip.size)
writer.add_clip(clip)

# Use 8 parallel processes for rendering
writer.write(processes=8, video_quality=VideoQuality.HIGH)

clip.close()

API Reference

For detailed API documentation, see docs/api.md.

Core Classes

Effect Modules

  • vfx - Visual effects (fade, blur, color, zoom, glitch)
  • afx - Audio effects (fade in/out)
  • vtx - Video transitions (crossfade, dissolve)

Advanced Usage

For advanced topics, see docs/advanced.md:

  • Custom effect development
  • Performance optimization techniques
  • Memory management strategies
  • Advanced audio processing
  • Masking and compositing techniques
  • Integration with other libraries

Examples

Additional examples are available in the examples/ directory:

Roadmap and Future Directions

Our focus will be on three key areas: performance, developer experience, and flexibility.

Contributions are highly welcome! If any of these ideas resonate with you, feel free to open an issue or a pull request to discuss it.

1. Performance Enhancements

  • GPU Acceleration: While MovieLite is well optimized for CPU, adding optional GPU support (e.g., using CuPy or PyTorch for transformations and blending) is a major goal. This would unlock another order-of-magnitude performance boost for users with compatible hardware.
  • Core Rendering Optimizations: We plan to introduce more intelligent caching. For instance, an ImageClip with a static scale shouldn't be re-rendered on every frame.
  • Expanded Numba JIT Usage: Some of the current visual effects (vfx) can be rewritten using Numba to run at near-native speed, further improving rendering times for complex compositions.

2. Developer Experience (DevEx)

  • A More Intuitive API: We want to make the library even more pleasant to work with. This includes:
    • Adding convenience features like string-based positioning (.set_position("center")).
    • Implementing a deep .copy() method for clips to make duplication easier.
    • Providing ways to manage the effect stack, such as removing or replacing transformations after they've been added.
  • Better Type Hinting and Documentation: Improving inline documentation and type hints to enhance autocompletion and code analysis in modern editors.

3. Flexibility and Advanced Control

  • Flexible Output Options: We aim to give users more control over the final render by:
    • Officially supporting more video/audio codecs and container formats (e.g., WebM, MOV).
    • Exposing FFmpeg parameters directly in the VideoWriter, similar to MoviePy's ffmpeg_params, for advanced users who need fine-grained control over encoding quality, presets, and other options.
  • Expanded Effects Library: Continuously adding new, performant effects to the vfx, afx, and vtx modules based on community feedback and common use cases.

License

MIT License - see LICENSE for details.

Changelog

See CHANGELOG.md for version history and changes.

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

movielite-0.2.1.tar.gz (40.7 kB view details)

Uploaded Source

Built Distribution

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

movielite-0.2.1-py3-none-any.whl (53.0 kB view details)

Uploaded Python 3

File details

Details for the file movielite-0.2.1.tar.gz.

File metadata

  • Download URL: movielite-0.2.1.tar.gz
  • Upload date:
  • Size: 40.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for movielite-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8f2d27f36266b159a1da8a018c521cc2d4c353f607729396b797be66063c9d41
MD5 1f7e83c6e43c79262ba3c2d3f95503ca
BLAKE2b-256 f05e4ea5c36fe16949d60e2f78523b2ae731c8595e6ed4e63842683fb3ee3791

See more details on using hashes here.

File details

Details for the file movielite-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: movielite-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 53.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for movielite-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 492bdeddfffc9829b9a225dbadfa555da2fca9e3d6a224d0dc4d0c6e84d8a4ff
MD5 2520511fa7d007098b684e59ea13ffe5
BLAKE2b-256 eaf9c9d2145b180a689909e5e866220d3dcfcb89b2528ed6766fcf6cadfa0b77

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