Skip to content

Architecture

videopython has four library layers and an optional MCP server. The order is the point: it is what lets a video-editing install stay free of PyTorch.

videopython.audio      Audio container and analysis.   Uses shared package internals.
        ↑
videopython.base       Video, VideoMetadata, FrameIterator, Transcription,
                       shared result types.            Depends on audio.
        ↑
videopython.editing    Operation/Effect foundation,    Depends on base, audio.
                       the VideoEdit plan runner.
        ↑
videopython.ai         Generation, understanding,      Depends on base, audio,
                       dubbing, AI operations.         optionally editing.
                                                       Needs the [ai] extra.

videopython.mcp sits alongside as a thin server over ai + editing. Its [mcp] extra contains only the analysis and AI editing stack. Generation, dubbing, diarization, source separation, and TTS remain exclusive to the full [ai] extra.

Why the layering is enforced, not just intended

The core layers must not import AI modules or ML runtimes. An eager import torch in editing/ would make core imports fail when PyTorch is absent. Dependency extras control what gets installed; import boundaries keep the core usable without them.

The invariant is not left to code review: src/tests/test_import_isolation.py fails the build if a lower package imports a higher package or if base, audio, or editing gain an AI import.

Why import videopython is fast even with [ai] installed

[ai] is a single extra covering every AI capability, so installing it pulls in torch, transformers, diffusers and chatterbox. Importing all of that eagerly would add seconds to every process start, including ones that never touch a model.

So videopython/ai/__init__.py has no top-level imports of its submodules. Every public symbol is re-exported lazily through PEP 562 __getattr__, mapped to the one leaf module that defines it. from videopython.ai import AudioToText imports the understanding leaf and nothing else — not diffusers, not chatterbox.

Two consequences worth knowing:

  • Dependencies load at feature use. Without [ai] installed, import videopython.ai and public class imports can succeed. A missing model dependency raises when the feature tries to load it.
  • AI operations register lazily. face_crop and object_detection_overlay only appear in the operation registry (and therefore the LLM schema) after their classes have been imported. See LLM-first design.

Why AI effects live in ai, not editing

ObjectDetectionOverlay is an effect in every structural sense — shape-preserving, per-frame, windowed. It nonetheless lives in videopython.ai.effects, because it runs a detection model per frame and the layering above admits no exceptions. The drawing half of it is a pure, AI-free function (videopython.base.draw_detections) that anything can reuse with any list of DetectedObject.

The same split explains FaceTrackingCrop: the crop transform is in videopython.ai.transforms, while the geometry types it produces (BoundingBox, FaceTrack) are ordinary base result types with no AI dependency.

Contributor workflow, repository layout, and releases are in DEVELOPMENT.md.