Usage Guide

tt-animatediff — comprehensive usage

AnimateDiff video generation on Tenstorrent Blackhole hardware. Three interfaces: CLI, Python API, and Gradio UI. All backed by the same SD 1.4 TTNN UNet pipeline.

01

Installation

Prerequisites

Python 3.10+, 16 GB RAM for CPU mode. Blackhole hardware requires Tenstorrent Blackhole P100/P150/P300c or QB2 with tt-metal built and its Python env active. Model weights are downloaded automatically from HuggingFace on first run.

CPU / any machine CPU

Runs Phase 1: diffusers.AnimateDiffPipeline + full MotionAdapter on any machine. No Tenstorrent hardware needed.

bash
$ git clone https://github.com/tenstorrent/tt-animatediff.git
$ cd tt-animatediff
$ pip install -r requirements.txt
$ python examples/generate.py --mode cpu --prompt "ocean waves at sunset"

Blackhole hardware Blackhole

Phase 2.5: TTNN UNet on Blackhole with cross-frame temporal attention. Requires tt-metal built and its Python env active.

  1. Build tt-metal (one-time, ~30 min)

    $ git clone https://github.com/tenstorrent/tt-metal.git ~/tt-metal
    $ cd ~/tt-metal && ./build_metal.sh
  2. Clone this repo and install dependencies

    $ git clone https://github.com/tenstorrent/tt-animatediff.git
    $ cd tt-animatediff && pip install -e .
  3. Activate the tt-metal Python env before each session

    $ source ~/tt-metal/python_env/bin/activate
  4. Generate your first animation

    $ python examples/generate.py --prompt "aurora borealis over a frozen lake"
First run

The TTNN UNet JIT-compiles on first use (~2–3 min). Compiled kernels are cached — subsequent runs are fast.

ttsim simulator sim

Bit-exact Blackhole simulation on any Linux/x86_64 machine. No hardware required.

bash
$ mkdir -p ~/sim
$ wget -O ~/sim/libttsim_bh.so \
    https://github.com/tenstorrent/ttsim/releases/download/v1.7.0/libttsim_bh.so
$ source ~/tt-metal/python_env/bin/activate
$ python examples/generate.py --mode sim --frames 2 --steps 4

See docs/SIMULATOR.md for the full simulator setup guide.

Gradio web UI BlackholeCPUsim

bash
$ pip install -e ".[ui]"
$ python app.py
# Open http://localhost:7860
02

CLI Reference

All modes are driven by a single entry point: examples/generate.py.

All flags

FlagDefaultDescription
--prompt TEXT(required)Text description of the animation
--negative-prompt TEXTstandard exclusionsFeatures to suppress
--mode MODEblackholecpu · blackhole · sim
--frames N8Number of frames (2–24). Multi-chip QB2: must be a multiple of the chip count
--steps N25Denoising steps. Use 4 for quick sim previews
--seed N42Random seed. Same seed + same prompt = same animation
--temporal-alpha F0.35Cross-frame attention blend (Blackhole/sim only). 0.0–1.0
--lightningoffUse Euler scheduler. On Blackhole: same step count, different solver. On CPU: distilled 4-step adapter
--lightning-steps N4CPU Lightning checkpoint step count. Must be 2, 4, or 8
--motion-adapteroffPhase 3: inject AnimateDiff MotionAdapter at 7 UNet points (Blackhole/sim only)
--motion-adapter-skip KEY…Skip injection points by name. E.g. --motion-adapter-skip up1 up2 for 6.75× speedup
--sim PATH~/sim/libttsim_bh.soPath to ttsim binary (sim mode only)
--device-id N0Blackhole chip index (0-based). Use for multi-process parallel dispatch
--chain-from PATHLoad latents from a previous run to blend visual continuity
--chain-save PATHSave this run's final latents for use with --chain-from
--chain-alpha F0.6Blend weight for chain latents (0 = ignore, 1 = replace base noise)
--output PATHoutput/out.gifOutput GIF path

Common recipes

Fast preview on any machine

# CPU, 4 frames, 10 steps — quick feedback on a new prompt
$ python examples/generate.py --mode cpu --frames 4 --steps 10 \
    --prompt "crackling campfire in a dark forest, cinematic"

Standard Blackhole generation

# 8 frames, 25 steps, ~100 s total on P300C
$ python examples/generate.py \
    --prompt "aurora borealis over a frozen tundra, long exposure" \
    --frames 8 --steps 25 --seed 1337

Fast MotionAdapter (skip up1+up2)

# ~7.7 s/frame — faster than Phase 2.5, full encoder-side attention
$ python examples/generate.py --motion-adapter \
    --motion-adapter-skip up1 up2 --frames 8 \
    --prompt "mycelium network pulsing with bioluminescence"

Prompt chaining — visual narrative continuity

# Run 1: save latents
$ python examples/generate.py --prompt "a seed germinating in dark soil" \
    --chain-save chain.pt --output scene1.gif

# Run 2: blend from run 1's latents
$ python examples/generate.py --prompt "a sapling reaching toward sunlight" \
    --chain-from chain.pt --chain-alpha 0.6 --output scene2.gif

Simulator — no hardware

# 2 frames, 4 steps — quick compatibility check
$ python examples/generate.py --mode sim --frames 2 --steps 4 \
    --prompt "test render"
03

Python API

Import animatediff_ttnn directly from Python. The high-level generate_animation() entry point manages device lifetime, mode selection, and caching internally — no setup code needed.

generate_animation()

python
from animatediff_ttnn import generate_animation, export_mp4, export_gif

# Simplest call — auto mode picks Blackhole if tt-metal is importable, else CPU
frames = generate_animation(
    prompt="swirling nebula, teal and gold, cinematic",
)

# Save as MP4 or GIF
export_mp4(frames, "output.mp4", fps=8)
export_gif(frames, "output.gif")

Full signature

ParameterDefaultDescription
prompt(required)Text description of the animation
negative_prompt""Features to suppress
num_frames8Frame count. Blackhole multi-chip: must be a multiple of chip count
num_steps25Denoising steps. Use 4 for fast preview/sim
guidance_scale7.5CFG scale. Use 1.0 with CPU Lightning mode
seed42Random seed for reproducibility
temporal_alpha0.35Cross-frame attention blend (Blackhole/sim only). 0–1
height512Output frame height in pixels
width512Output frame width in pixels
mode"auto""auto" · "blackhole" · "sim" · "cpu"
sim_soNonePath to libttsim_bh.so (sim mode). Defaults to ~/sim/libttsim_bh.so
use_lightningFalseEuler scheduler instead of PNDM
lightning_steps4CPU Lightning checkpoint step count (2, 4, or 8). Ignored on Blackhole/sim
chain_fromNonePath to a .pt latent file from a previous run for visual continuity
chain_saveNonePath to save this run's final latents for use as chain_from next time
chain_alpha0.6Blend weight for chain latents
on_stepNoneCallback (step_idx, num_steps, frame_latents) called after each denoising step (Blackhole/sim only)

Returns: list[PIL.Image] — one image per frame, in generation order.

Mode selection

mode="auto" tries to import ttnn and picks "blackhole" if available, "cpu" otherwise. The TTNN device and compiled UNet are initialized on the first call and held for the lifetime of the process — subsequent calls are fast.

Per-step progress callback

python
from animatediff_ttnn import generate_animation

def on_step(step_idx, num_steps, frame_latents):
    pct = 100 * (step_idx + 1) / num_steps
    print(f"  step {step_idx+1}/{num_steps} ({pct:.0f}%)")

frames = generate_animation(
    prompt="lava flow through volcanic rock, molten orange glow",
    mode="blackhole",
    num_frames=8,
    on_step=on_step,
)

CPU Lightning

python
# CPU Lightning: 4-step distilled adapter, ~20 s/frame
frames = generate_animation(
    prompt="crystalline cave, blue ice, shafts of light",
    mode="cpu",
    use_lightning=True,
    lightning_steps=4,   # must match checkpoint: 2, 4, or 8
    guidance_scale=1.0,   # distilled — CFG baked in
)

Prompt chaining

python
# Scene 1 — save latents
frames1 = generate_animation(
    prompt="a lone lighthouse in a stormy sea",
    chain_save="lighthouse.pt",
)

# Scene 2 — blend from scene 1 for visual DNA continuity
frames2 = generate_animation(
    prompt="a calm harbour at dawn, same coastline",
    chain_from="lighthouse.pt",
    chain_alpha=0.6,
)

Export functions

python
from animatediff_ttnn import export_mp4, export_gif

# MP4 — libx264 / yuv420p, requires ffmpeg on PATH
export_mp4(frames, "output.mp4", fps=8)

# GIF — no external dependencies
export_gif(frames, "output.gif")

export_mp4 requires ffmpeg on $PATH. Install with sudo apt install ffmpeg (Ubuntu) or brew install ffmpeg (macOS).

Low-level API

Direct access to phase-specific pipelines for scripting and testing:

python
# Phase 1 — CPU baseline
from animatediff_ttnn.pipeline import create_animatediff_pipeline, generate, export_gif

pipe = create_animatediff_pipeline()
frames = generate(pipe, "ocean waves at sunset", num_frames=8)

# Phase 2.5 — Blackhole temporal attention (requires device + models)
from animatediff_ttnn.session import ensure_blackhole
from animatediff_ttnn.generation_helpers import encode_prompt
from animatediff_ttnn.temporal_attention import generate_frames_temporal

device, (ttnn_model, ttnn_vae, config, time_proj) = ensure_blackhole()
embeddings = encode_prompt("ocean", "blurry")
frames = generate_frames_temporal(device, ttnn_model, ttnn_vae,
    config, time_proj, embeddings, num_frames=8, ...)
04

Gradio UI

A browser-based interface for interactive generation with real-time denoising previews.

Starting the UI

Blackhole CPU only Simulator
$ pip install -e ".[ui]"
$ source ~/tt-metal/python_env/bin/activate
$ python app.py
# Open http://localhost:7860, select Mode: blackhole
$ pip install -e ".[ui]"
$ python app.py
# Open http://localhost:7860, select Mode: cpu
$ pip install -e ".[ui]"
$ source ~/tt-metal/python_env/bin/activate
$ python app.py
# Open http://localhost:7860
# Select Mode: sim — enter sim binary path if not ~/sim/libttsim_bh.so

Parameters reference

ParameterRange / TypeDefaultNotes
Modeblackhole · cpu · simblackholeSelects compute backend
PrompttextSee Prompt guide
Negative prompttextstandard exclusions
Frames2–248Recommend 2–4 for sim
Steps4–5025Use 4 for sim/Lightning preview
Seedinteger42Fixed seed = reproducible output
Temporal alpha0.0–1.00.35Blackhole/sim only. See tuning guide
LightningcheckboxoffEuler solver. CPU requires matching Lightning checkpoint
Lightning steps2 · 4 · 84CPU Lightning only
Chain from / savefile pathBlackhole/sim only. Visual continuity across runs
Chain alpha0.0–1.00.6Blend weight for chain latents
Sim binary pathfile path~/sim/libttsim_bh.soSim mode only
Streaming previews

On Blackhole/sim, the UI streams a colourised preview after each denoising step. Early steps look noisy — that's normal. The final frame is VAE-decoded. Preview generation is pure CPU tensor ops with no hardware overhead.

05

Mode comparison

ModeHardwareSpeed (8fr, 512²)Temporal qualityNotes
cpuNone~2 min/frameFull MotionAdapter ✓Any machine, 16 GB RAM
cpu --lightningNone~20 s/frameFull MotionAdapter ✓4-step distilled adapter, CFG=1.0
blackholeBlackhole P300C~12.5 s/frameCross-frame blendPNDM · 25 steps · CFG=7.5
blackhole --lightningBlackhole P300C~12.0 s/frameCross-frame blendEuler solver · same step count
blackhole --motion-adapterBlackhole P300C~52 s/frameFull MotionAdapter Phase 3 ✓7 injection points, batched D→H
blackhole --motion-adapter --motion-adapter-skip up1 up2Blackhole P300C~7.7 s/frameEncoder-side MotionAdapter ✓5 injection points, fastest Blackhole mode
simNone (ttsim)10–100× slower than siliconCross-frame blendBit-exact, Linux/x86_64 only

Timings measured on QB2 (4 × P300C), warm model (TTNN JIT compiled). See benchmarks page for full breakdown.

06

Prompt guide

This pipeline uses SD 1.4 in all modes. Knowing its characteristics produces consistently better results.

Natural scenes

Forests, mountains, oceans, sky, fire, water. SD 1.4's strongest domain.

Painterly styles

Oil painting, watercolor, impressionism, concept art. Style cues land reliably.

Cinematic lighting

Golden hour, neon, moonlight, candlelight, volumetric fog, depth of field.

Architecture

Temples, ruins, castles, sci-fi structures, cathedrals.

Cosmic / abstract

Nebulae, galaxies, aurora, energy fields, geometric patterns, mandalas.

Motion-friendly

Crackling fire, flowing lava, drifting smoke, pulsing mycelium, aurora shimmer.

Avoid

Photorealistic people / faces — anatomy drifts frame-to-frame. Text in the image — SD 1.4 cannot render legible text. Prompts over ~60 words — CLIP truncates at 77 tokens.

Patterns that work

examples
# Style before subject
"watercolor painting of ancient ruins at sunset, soft brushstrokes, muted palette"

# Cinematic descriptors
"cinematic 4K, dramatic side lighting, volumetric fog, depth of field"

# Specific motion verbs
"crackling campfire"  "ocean waves crashing"  "aurora borealis shimmering"
"shifting cosmos"     "lava flowing"           "smoke drifting"

# Combine style + lighting + subject
"oil painting of a cathedral at dusk, dramatic crepuscular rays, golden hour, impressionist"

# Negative prompt — always include these
"blurry, low quality, distorted, text, people, faces, modern buildings"

Temporal alpha tuning Blackholesim

Controls how strongly frames are blended together during cross-frame attention in Phase 2.5.

0.0
No cross-frame mixing — frames denoised independently
0.2–0.3
Subtle coherence, slight variation frame-to-frame
0.35 ★
Default — good balance for most subjects
0.5–0.7
Strong coherence; backgrounds stabilize, fine detail may flatten
1.0
Maximum blending — very similar frames, minimal motion

Rule of thumb: fast motion (fire, water) → 0.2–0.35. Slow atmospheric drift (aurora, cosmos) → 0.4–0.6.

Step count guidance

ModeMinimumSweet spotNotes
PNDM standard (Blackhole/sim)4 (preview)25Diminishing returns beyond 30
Euler Lightning (Blackhole/sim)425Base TTNN UNet — same CFG=7.5, different solver
Euler Lightning (CPU)24Real distilled adapter — CFG=1.0 baked in; more steps degrades quality
07

Troubleshooting

ImportError: No module named 'ttnn'

The tt-metal Python env is not active. Run source ~/tt-metal/python_env/bin/activate before any Blackhole or sim command. In mode="auto" this causes automatic fallback to CPU — no error is raised.

TT_FATAL / hardware abort

A chip may be in a bad state. Try tt-smi -s to check chip health. If chip 3 is listed as hung (BOARD_ID_HIGH 0x461, BOARD_ID_LOW 0x31924055), the setup_blackhole() function reads hwmon sentinel values to skip dead chips automatically.

ValueError: num_frames must be a multiple of num_chips

On a QB2 (4-chip mesh), frame count must be a multiple of 4: use 4, 8, 12, or 16. This constraint applies to Phase 2.5 and the Gradio UI's Blackhole mode.

TTNN JIT compilation taking a long time

First-run UNet kernel compilation takes 2–3 minutes. Compiled kernels are cached — subsequent runs start in seconds. Do not interrupt the first run.

export_mp4: ffmpeg not found

$ sudo apt install ffmpeg      # Ubuntu / Debian
$ brew install ffmpeg          # macOS

ttsim probe failed

The ttsim binary version is incompatible with the installed tt-metal version. Download a matching release from github.com/tenstorrent/ttsim/releases. The probe runs in a subprocess to prevent a simulator abort() from killing the Gradio server.

CPU Lightning: quality degrades with more steps

The distilled ByteDance/AnimateDiff-Lightning checkpoint is trained for exactly 2, 4, or 8 steps with guidance_scale=1.0 (baked in). Using more steps or a different CFG scale degrades output. Use --lightning-steps to match the checkpoint and don't override guidance_scale.

Gradio UI: preview looks like noise

Normal for the first several denoising steps. The latent-space preview uses a fast tanh-colourised mapping (no VAE) — noise is expected until ~step 10 of a 25-step run. Watch for structure emerging in the middle steps.