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.4.tar.gz (199.1 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.4-py3-none-any.whl (90.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: an-0.1.4.tar.gz
  • Upload date:
  • Size: 199.1 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.4.tar.gz
Algorithm Hash digest
SHA256 8b74af51af8e9c0ba21f1e26c1e3b716169fa97bf0feeb5854752ff4ab789a4e
MD5 ef39e4896600dec83d2ee71fe728e0a1
BLAKE2b-256 ad0cc7db5c200d80afde728b10e9c10fa0729b5a3422a7d4e5853ff7ce745f8c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: an-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 90.5 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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ed0b7afac58fb3e451ceb29e33e94a5847fb7db00a7f4ea79d40ad151457172e
MD5 47a6e3e72922177073e17ea2507916de
BLAKE2b-256 25b5607b182c1161763aedad60b7e99e0de30c266d39de947d0a3f0394e3f85a

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