Skip to main content

AI-driven structured animation in Python.

Project description

an

AI-driven structured animation in Python. The user is the director; the AI agent is the assistant orchestrator; existing animation libraries (a custom 2D-cutout runtime, Manim, Remotion) are the executors.

pip install an

Renamed from anima (PyPI conflict). The package and CLI are now an. Repo: https://github.com/thorwhalen/an.


What works today (v0.1)

an lets you describe a scene in natural language inside a Claude Code session and have it rendered as an mp4 — including dialogue with offline lip-sync, without any API keys (offline TTS produces silent audio of the right length, offline lip-sync deterministically generates viseme tracks). Real speech via ElevenLabs and accurate phoneme alignment via Rhubarb plug in once you set them up.

an check                                # diagnose backend system deps
an init my-scene                        # create a fresh project
# edit scene.md ...
an validate my-scene                    # schema + semantic validation
an render my-scene                      # → output/main.mp4

30-second tour

A project is a small directory:

my-scene/
├── scene.md            # human Markdown — what you and the agent edit
├── ir/scene.json       # Pydantic-validated SSOT (auto-synced)
├── assets/             # characters, environments, voices, styles
├── artifacts/          # audio, viseme tracks, per-shot mp4s
├── output/             # final mp4s
└── .an/                # agent decisions log + memory

Authoring lives in scene.md:

# Park Bench

```yaml meta
title: Park Bench
duration: 6
fps: 24
resolution: { width: 640, height: 360 }

Shot s1 (cutout)

- { kind: character, id: charlie, store: characters, ref: charlie-v1 }
- { kind: character, id: maya, store: characters, ref: maya-v1 }
charlie: Did you ever wonder why we always meet here?
maya: Because the pigeons trust us.

Then `an render my-scene` produces an mp4 with two characters and animated mouths over the dialogue lines. Defaults are entirely offline — to swap in real speech, set `ELEVEN_API_KEY` and use `ElevenLabsTTS`; to swap in real phoneme alignment, install `rhubarb-lipsync` and use `RhubarbLipSync`.

## 3-minute tour

`an` separates a scene into three layers:

1. **Narrative** — `scene.md`. Human Markdown with structured fenced blocks (`yaml meta`, `yaml shot`, `yaml entities`, `dialogue`). What you and the agent edit.
2. **Scene Graph** — `ir/scene.json`. Pydantic-validated, renderer-agnostic. The single source of truth for tooling. Diffable. Pipeline stages (audio synthesis, lip-sync) write into the JSON; `an sync` keeps it consistent with the Markdown using mtime-newer-wins.
3. **Render Code** — generated per-backend (cutout JSON for the JS runtime, Manim Python, Remotion TSX). Disposable; never edited by hand.

Composition is fluent in Python and flattens to a canonical timeline:

```python
from an import sequence, parallel, tween, delay, flatten

action = sequence(
    tween("charlie/torso", "rotation", to=10.0, duration=1.0),
    delay(0.5),
    tween("charlie/torso", "rotation", to=0.0, duration=1.0),
)
flat = flatten(action)
# [FlatAction(start=0.0, end=1.0, ...), FlatAction(start=1.5, end=2.5, ...)]

Persistence goes through a project mall — a dict of dol-backed MutableMappings:

from an import build_project_mall

mall = build_project_mall("my-scene", ensure=True)
mall["voices"]["maya-warm"] = {"provider": "elevenlabs", "voice_id": "..."}
scene = mall["scenes"]["main"]   # returns a SceneIR

End-to-end orchestration:

from an.orchestrate import orchestrate

report = orchestrate("my-scene")
# report.success: bool, .output_path: Path, .validation, .verifications

Architecture

Subsystem Implementation
Renderer Protocol an.adapters.Renderer
Cutout backend an.adapters.cutout — Python compiles to JSON; PixiJS in headless Chromium screenshots frames; ffmpeg muxes mp4
Manim / Remotion / Whiteboard Skeleton implementations (Phase 6)
TTS Protocol OfflineTTS (default), ElevenLabsTTS
Lip-sync Protocol OfflineLipSync (default), RhubarbLipSync
Verifier Protocol LayoutLintVerifier, HumanInTheLoopVerifier
Persistence dol-backed MutableMappings organized into build_project_mall(...)
CLI argh-based dispatch over an.tools._dispatch_funcs

What's not in v0.1

  • 3D animation, generative video, interactive output, SaaS hosting, music/sound-effect generation, in-house GUI, or editing of pre-existing video footage. an synthesizes; it does not cut.
  • The Manim / Remotion / Whiteboard backends are skeletons — they implement the Protocol and route correctly, but only the cutout backend produces real video at v0.1.
  • The orchestrator's free-text iterative edit loop ("make Maya's laugh longer and warmer") is driven by the an Claude Code skill calling into the orchestrate primitives — there's no standalone implementation in pure Python.

Reference

  • Architectural pillars and per-subsystem reading order: CLAUDE.md.
  • Deep design reports (~250 KB total): misc/docs/.
  • The skills the agent uses to drive an: .claude/skills/.
  • Examples: examples/single_character/ (simplest renderable scene), examples/park_bench_cartoon/ (two-character dialogue demo).

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

an-0.1.8.tar.gz (209.5 kB view details)

Uploaded Source

Built Distribution

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

an-0.1.8-py3-none-any.whl (96.7 kB view details)

Uploaded Python 3

File details

Details for the file an-0.1.8.tar.gz.

File metadata

  • Download URL: an-0.1.8.tar.gz
  • Upload date:
  • Size: 209.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for an-0.1.8.tar.gz
Algorithm Hash digest
SHA256 b03d079665f06b3111f23d9ff4711cfb30d5d1980ffddc52c2f5c71e10678eb4
MD5 a1336e614e168ece45f701c554f1fd04
BLAKE2b-256 e310916305f6fc6e2d1abb12c3e32d8db54d62ce0e0c65aae8d3bb9d1add07cd

See more details on using hashes here.

File details

Details for the file an-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: an-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 96.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for an-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 4d29acaf012695cb33bfc90dc006c78f2401fc85e42cdcb812dddca84c9f7227
MD5 cae0cdc83d108960ef99079fc15be3af
BLAKE2b-256 f80171c26ef8c7b2f052bfc7235ad6f469e26b108c59ce72d14ab8b3e10f24fc

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