A high-level, intent-driven camera system for Manim that separates cinematography from scene logic.
- Intent-driven API: Describe what you want to show, not how to move the camera
- Semantic targets: Reference objects by meaning, not coordinates
- Automatic framing: Smart composition with professional defaults
- Reusable shots: Named camera patterns that work across scenes
✅ Core System - Research & Architecture
- Core shot system with named shots
- Intent-driven API (show, emphasize, reveal)
- Automatic framing with composition rules
- Semantic target registry
- Emphasis effects system
- Timeline devtools
✅ Shot System & Shot Manager
- Enhanced Shot object with focus, zoom, padding, duration, easing
- Shot Manager with state tracking (add, go, transition)
- Shot interpolation with 15 easing functions
- Interrupt-safe transitions
- Failure handling with fallbacks
- Working demo scenes
✅ Semantic Target Registry
- Dynamic rebinding with assign() method
- Callable targets for lazy evaluation
- History tracking and previous target fallback
- Four fallback modes (USE_PREVIOUS, USE_DEFAULT, WARN_ONLY, RAISE_ERROR)
- Support for single objects, VGroups, lists, and callables
- Runtime target resolution in shots
- Comprehensive demo scenes and documentation
✅ Automatic Framing Intelligence
- Comprehensive bounding box analysis (tight, label-aware, visual)
- Four framing strategies (TIGHT, MEDIUM, WIDE, CONTEXTUAL)
- Smart defaults based on object type (8 categories)
- Margin and aspect ratio safety validation
- ObjectClassifier with intelligent content detection
- 5 demonstration scenes with before/after comparisons
✅ Intent-Driven Camera API
- explain(), compare(), transition_intent() methods
- 9 built-in presets (slow_math, cinematic, etc.)
- Chainable API (then_explain, then_compare, then_wait)
- Preset system with style overrides
- Fluent, readable camera choreography
- 4 demonstration scenes
✅ Constraints, Effects, Accessibility
- Enhanced constraints (velocity caps, axis locks, rotation limits)
- Focus effects (dim background, glow, micro pulse)
- Accessibility modes (reduced motion, min text height, high contrast)
- Global CameraConfig system
- 3 demonstration scenes
✅ Developer Tools & Timeline
- Enhanced timeline export with frame position and zoom data
- Visualization overlay (bounding boxes, velocity vectors)
- Enhanced logging and diagnostics system
- Frame-by-frame analysis tools
- 3 demonstration scenes
✅ Advanced Zoom Effects & Detail Bubbles
- Bubble Callouts - Show details on the side WITHOUT moving camera!
- Perfect for education: "let me show you what's happening here"
- Keeps context visible while showing microscopic detail
- Circle, square, or rounded bubble shapes
- Built-in detail generators (friction ridges, molecules, grid)
- See BUBBLE_CALLOUT_GUIDE.md for complete guide
- 5 beautiful zoom effects with automatic background fading
- Spotlight Zoom: Dims background while zooming to target
- Tunnel Zoom: Distance-based fading for depth effect
- Iris Zoom: Circular fade pattern like camera iris
- Cinematic Zoom: Professional film-quality smooth zoom
- Focus Pull: Shifts focus between two targets
- MiniScene system for full-screen detailed zooms
- Simple one-line API designed for ease of use
- 15+ demonstration scenes showing all features
camera_choreo/
├── core/ # Shot system and intent API
├── framing/ # Automatic framing and constraints
├── targets/ # Semantic target registry
├── effects/ # Visual emphasis effects
├── devtools/ # Timeline and debugging tools
└── examples/ # Usage examples
pip install -e .from manim import *
from camera_choreo import CameraChoreography
class MyScene(MovingCameraScene):
def construct(self):
choreo = CameraChoreography(self)
# Define semantic targets
choreo.target("title", title_text)
choreo.target("proof", proof_mobjects)
# Intent-driven camera movements
choreo.show("title", duration=2)
choreo.emphasize("important_equation", style="zoom")
choreo.reveal("proof", direction="left_to_right")from manim import *
from camera_choreo import CameraChoreography
from camera_choreo.core.shot import Shot
from camera_choreo.core.easing import Easing
class MyShotScene(MovingCameraScene):
def construct(self):
shots = CameraChoreography(self)
# Register targets
shots.target("overview", all_objects)
shots.target("detail", detail_object)
# Define named shots
overview = Shot(
name="overview",
focus="overview",
zoom="wide",
padding=0.3,
duration=1.5,
easing=Easing.SMOOTH
)
detail = Shot(
name="detail",
focus="detail",
zoom="tight",
padding=0.2,
duration=1.2,
easing=Easing.EASE_IN_OUT
)
# Add shots
shots.add(overview)
shots.add(detail)
# Execute shot sequence
shots.go("overview")
self.wait(1)
shots.transition("overview", "detail")
self.wait(1)
shots.go("overview")from manim import *
from camera_choreo import CameraChoreography
from camera_choreo.core.shot import Shot
class SemanticTrackingScene(MovingCameraScene):
def construct(self):
shots = CameraChoreography(self)
# Create objects
node1 = Circle(color=BLUE).shift(LEFT * 3)
node2 = Circle(color=GREEN).shift(RIGHT * 3)
# Assign semantic name to track objects
shots.assign_target("active_node", node1)
# Define shot using semantic name
active_shot = Shot(
name="active",
focus="active_node", # References semantic name, not object
zoom="tight"
)
shots.add(active_shot)
# Camera follows node1
shots.go("active")
self.wait(1)
# Dynamically rebind to track node2
shots.assign_target("active_node", node2)
# Camera automatically follows node2!
shots.go("active")
self.wait(1)Show details in a bubble on the side - camera doesn't move!
from manim import *
from camera_choreo import CameraChoreography
from camera_choreo.effects.miniscene import create_friction_ridges
class FrictionBubbleDemo(MovingCameraScene):
def construct(self):
choreo = CameraChoreography(self)
# Main scene - stays visible the whole time!
title = Text("Understanding Friction").to_edge(UP)
block = Rectangle(width=2, height=1.5, color=BLUE, fill_opacity=0.6)
ground = Rectangle(width=8, height=0.5, color=GRAY).shift(DOWN * 1.5)
self.add(title, block, ground)
# Show detail in bubble WITHOUT moving camera
callout = choreo.detail_callout(
block.get_bottom(),
bubble_shape="circle",
detail_generator=create_friction_ridges
)
callout.animate_in()
self.wait(2)
callout.animate_out()from manim import *
from camera_choreo import CameraChoreography
class BeautifulZoomDemo(MovingCameraScene):
def construct(self):
choreo = CameraChoreography(self)
# Setup scene
target = Circle(color=BLUE)
background = VGroup(*[Dot().shift(RIGHT * x + UP * y)
for x in range(-5, 6) for y in range(-3, 4)])
self.add(background, target)
# One-line beautiful zoom with background fading!
choreo.spotlight_zoom(target, zoom_factor=2.5, duration=2.0)
self.wait(2)Run demo scenes:
# NEW! Bubble Callout demos (detail bubbles without moving camera)
manim -pql camera_choreo/examples/bubble_callout_demo.py PhysicsFrictionDemo # BEST EXAMPLE!
manim -pql camera_choreo/examples/bubble_callout_demo.py CircleBubbleDemo
manim -pql camera_choreo/examples/bubble_callout_demo.py MolecularBubbleDemo
manim -pql camera_choreo/examples/bubble_callout_demo.py CompleteBubbleShowcase
# Basic examples
manim -pql camera_choreo/examples/basic_example.py BasicChoreographyExample
# Shot system demos
manim -pql camera_choreo/examples/example1.py ShotSystemDemo
manim -pql camera_choreo/examples/example1.py EasingDemo
manim -pql camera_choreo/examples/example1.py FailureHandlingDemo
# Semantic target registry demos
manim -pql camera_choreo/examples/example2.py SemanticTrackingDemo
manim -pql camera_choreo/examples/example2.py CallableTargetsDemo
manim -pql camera_choreo/examples/example2.py FallbackDemo
manim -pql camera_choreo/examples/example2.py AlgorithmVisualization
manim -pql camera_choreo/examples/example2.py GroupTargetsDemo
# Advanced zoom effects demos (camera moves and zooms)
manim -pql camera_choreo/examples/advanced_zoom_demo.py SpotlightZoomDemo
manim -pql camera_choreo/examples/advanced_zoom_demo.py TunnelZoomDemo
manim -pql camera_choreo/examples/advanced_zoom_demo.py IrisZoomDemo
manim -pql camera_choreo/examples/advanced_zoom_demo.py CinematicZoomDemo
manim -pql camera_choreo/examples/advanced_zoom_demo.py FocusPullDemo
manim -pql camera_choreo/examples/advanced_zoom_demo.py AllZoomEffectsDemo
# MiniScene demos (full-screen zoom)
manim -pql camera_choreo/examples/miniscene_demo.py FrictionRidgesDemo
manim -pql camera_choreo/examples/miniscene_demo.py MolecularDetailDemo
# Easy usage demos
manim -pql camera_choreo/examples/easy_usage_demo.py SimpleZoomExample
manim -pql camera_choreo/examples/easy_usage_demo.py CompleteShowcaseExample
# See other examples
ls camera_choreo/examples/example*.pyRun tests:
pytest tests/