termflix 0.7.1

Terminal animation player with 60 procedurally generated animations, multiple render modes, and true color support
# termflix

[![Crates.io](https://img.shields.io/crates/v/termflix)](https://crates.io/crates/termflix)
![Runs on Linux | macOS | Windows](https://img.shields.io/badge/runs%20on-Linux%20%7C%20macOS%20%7C%20Windows-blue)
![Arch x86-64 | ARM | AppleSilicon](https://img.shields.io/badge/arch-x86--64%20%7C%20ARM%20%7C%20AppleSilicon-blue)
![License](https://img.shields.io/badge/license-MIT-green)

A terminal animation player with 60 procedurally generated animations, multiple render modes, and true color support. Low CPU impact, works great in tmux, only needs your terminal.

[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoffee.com/probello3)

![termflix screenshot](https://raw.githubusercontent.com/paulrobello/termflix/main/screenshot.png)

**[Live gallery →](https://paulrobello.github.io/termflix/)** — every animation as a still and animated GIF, regenerated by CI on each push to `main`.

## Features

- **60 Animations** — Fire, matrix rain, starfields, plasma, ocean waves, aurora, lightning, and much more
- **3 Render Modes** — Braille (highest resolution), half-block, and ASCII density mapping
- **4 Color Modes** — Mono, ANSI 16, ANSI 256, and 24-bit true color
- **ANSI-256 Dithering** — 4×4 Bayer ordered dithering makes gradients look near-true-color on 256-color terminals (`--dither`)
- **Colorblind-Safe** — Remap any animation onto a perceptually-uniform palette (`--palette`) or apply daltonization correction (`--colorblind`)
- **Per-Animation Defaults** — Each animation auto-selects its best render mode
- **Runtime Hotkeys** — Cycle animations, render modes, and color modes on the fly
- **Recording & Playback** — Record sessions and replay them
- **Auto-Cycle** — Rotate through animations on a timer
- **Particle System** — Reusable procedural particle engine powering many animations
- **Low CPU** — Efficient rendering with minimal resource usage

## Animations

| Animation | Description | Default Render |
|-----------|-------------|---------------|
| `fire` | Doom-style fire effect with heat propagation | Half-block |
| `matrix` | Matrix digital rain with trailing drops | ASCII |
| `plasma` | Classic plasma with overlapping sine waves | Half-block |
| `starfield` | 3D starfield with depth parallax | Braille |
| `wave` | Sine wave interference from moving sources | Half-block |
| `life` | Conway's Game of Life cellular automaton | Braille |
| `particles` | Fireworks bursting with physics and fade | Braille |
| `pendulum` | Pendulum wave with mesmerizing phase patterns | Half-block |
| `rain` | Raindrops with splash particles and wind | Half-block |
| `fountain` | Water fountain with jets, splashes, and mist | Half-block |
| `flow` | Perlin noise flow field with particle trails | Braille |
| `spiral` | Rotating multi-arm spiral pattern | Half-block |
| `ocean` | Ocean waves with foam and depth shading | Half-block |
| `aurora` | Aurora borealis with layered curtains | Half-block |
| `lightning` | Lightning bolts with recursive branching | Braille |
| `smoke` | Smoke rising with Perlin turbulence | Half-block |
| `ripple` | Ripple interference from random drop points | Half-block |
| `snow` | Snowfall with accumulation on the ground | Half-block |
| `garden` | Growing garden with rain, clouds, and blooming plants | ASCII |
| `fireflies` | Fireflies blinking with warm glow | Half-block |
| `dna` | Rotating DNA double helix with base pairs | ASCII |
| `pulse` | Expanding pulse rings from center | Half-block |
| `boids` | Boids flocking simulation with trails | Half-block |
| `lava` | Lava lamp blobs rising, merging, and splitting | Half-block |
| `sandstorm` | Blowing sand with dune formation | Half-block |
| `petals` | Cherry blossom petals drifting in wind | Half-block |
| `campfire` | Campfire with rising ember sparks | Half-block |
| `waterfall` | Cascading water with mist spray | Half-block |
| `eclipse` | Moon crossing sun with corona rays | Half-block |
| `blackhole` | Black hole with accretion disk and lensing | Half-block |
| `radar` | Rotating radar sweep with fading blips | Half-block |
| `rainforest` | Layered rainforest with parallax scrolling, rain, birds, and falling leaves | Half-block |
| `crystallize` | DLA crystal growth from center seed | Braille |
| `hackerman` | Scrolling hex/binary hacker terminal | ASCII |
| `visualizer` | Audio spectrum analyzer with bouncing bars | Half-block |
| `cells` | Cell division and mitosis animation | Half-block |
| `atom` | Electrons orbiting a nucleus in 3D | Half-block |
| `automata` | Cellular automata cycling through multiple rulesets | Half-block |
| `globe` | Rotating wireframe Earth with continents | Half-block |
| `dragon` | Dragon curve fractal with color cycling | Braille |
| `sierpinski` | Animated Sierpinski triangle with zoom | Braille |
| `mandelbrot` | Mandelbrot set with zoom and color cycling | Braille |
| `maze` | Animated maze generation with recursive backtracking and BFS solving | Half-block |
| `metaballs` | Organic metaballs merging and splitting with smooth distance fields | Half-block |
| `nbody` | N-body gravitational simulation with colorful orbiting masses and merging | Half-block |
| `langton` | Langton's Ant cellular automaton | Half-block |
| `sort` | Sorting algorithm visualizer | Half-block |
| `tetris` | Self-playing Tetris with AI piece placement | Half-block |
| `snake` | Self-playing Snake game AI | Half-block |
| `invaders` | Space Invaders attract mode demo | Half-block |
| `pong` | Self-playing Pong with AI paddles | Half-block |
| `flappy_bird` | Self-playing Flappy Bird with AI | Half-block |
| `reaction_diffusion` | Gray-Scott reaction-diffusion coral/brain patterns | Half-block |
| `voronoi` | Animated Voronoi diagram with drifting colored cells and edge detection | Half-block |
| `galton` | Galton board with balls cascading into a bell-curve histogram | Half-block |
| `solar_system` | Solar system with planets, moons, rings, and an asteroid belt | Half-block |
| `physarum` | Physarum slime mold agents self-organizing into networks | Half-block |
| `newtons_cradle` | Newton's cradle with energy-conserving swings | Half-block |
| `strange_attractor` | Lorenz strange attractor with a rotating rainbow trail | Half-block |
| `ink_in_water` | Colored ink puffs dispersing through a turbulent flow field | Half-block |

## Installation

### Quick Install (Linux / macOS / WSL)

```bash
curl -sL https://raw.githubusercontent.com/paulrobello/termflix/main/install.sh | bash
```

Installs the latest release binary to `/usr/local/bin`. Custom install location:

```bash
INSTALL_DIR=~/.local/bin curl -sL https://raw.githubusercontent.com/paulrobello/termflix/main/install.sh | bash
```

### From crates.io

```bash
cargo install termflix
```

### From Source

Requires Rust 1.85+ (edition 2024):

```bash
git clone https://github.com/paulrobello/termflix
cd termflix
make install
```

### Pre-built Binaries

Download from [GitHub Releases](https://github.com/paulrobello/termflix/releases/latest):

| Platform | Binary |
|----------|--------|
| Linux x86_64 | `termflix-linux-x86_64` |
| Linux ARM64 | `termflix-linux-aarch64` |
| macOS x86_64 | `termflix-macos-x86_64` |
| macOS ARM64 (Apple Silicon) | `termflix-macos-aarch64` |
| Windows x86_64 | `termflix-windows-x86_64.exe` |

**macOS note:** After downloading manually, remove the quarantine flag:
```bash
xattr -cr termflix-macos-*
chmod +x termflix-macos-*
```

## Usage

```bash
# Run default animation (fire)
termflix

# Run a specific animation
termflix starfield

# List all animations
termflix --list

# Set render mode (braille, half-block, ascii)
termflix plasma -r braille

# Set color mode (mono, ansi16, ansi256, true-color)
termflix fire -c true-color

# ANSI-256 with Bayer dithering (near-true-color on 256-color terminals)
termflix plasma -c ansi256 --dither

# Colorblind-safe palette remap (viridis, magma, inferno, plasma, okabe-ito)
termflix fire --palette viridis

# Daltonization correction (protanopia, deuteranopia, tritanopia)
termflix plasma --colorblind deuteranopia

# Auto-cycle through animations every 10 seconds
termflix --cycle 10

# Scale particle density
termflix rain --scale 1.5

# Remove FPS cap (render as fast as terminal allows)
termflix --unlimited

# Clean mode (no status bar)
termflix --clean

# Screensaver mode (exits on any keypress or focus)
termflix matrix --clean --screensaver

# Screensaver mode but keep hotkeys active (only q/Esc/Ctrl+C dismiss)
termflix matrix --clean --screensaver --screensaver-keys

# Record a session
termflix matrix --record session.asciianim

# Play back a recording
termflix --play session.asciianim

# Post-processing: bloom, vignette, scanlines
termflix fire --bloom-intensity 0.5 --bloom-threshold 0.6 --vignette 0.4 --scanlines

# Profile per-frame timing (prints a summary on exit)
termflix --profile plasma

# Full redraw every frame (disables dirty-cell rendering; fixes tearing under tmux)
termflix plasma --full-frames

# Render inline, no writer thread (for debugging / A-B comparison)
termflix plasma --single-threaded

# Drive parameters from an external NDJSON file (one JSON object per line)
termflix --data-file /tmp/termflix.json
```

## Hotkeys

| Key | Action |
|-----|--------|
| `q` / `Esc` | Quit |
| `` / `` (or `n` / `p`) | Previous / next animation |
| `r` | Cycle render mode (braille → half-block → ascii) |
| `c` | Cycle color mode |
| `b` | Toggle bloom |
| `s` | Toggle brightness smoothing |
| `d` | Toggle ANSI-256 dithering |
| `h` | Toggle status bar |

## How It Works

termflix uses a pixel-level canvas that gets rendered to terminal characters:

- **Braille mode** (`⠁⠂⠃...⣿`) — 2×4 pixels per terminal cell = highest resolution
- **Half-block mode** (`▀▄█`) — 1×2 pixels per cell = good balance of resolution and color
- **ASCII mode** (` .:-=+*#%@`) — 1×1 pixel per cell = widest compatibility

Each animation implements the `Animation` trait, writing to the canvas at sub-cell resolution. The renderer converts the canvas to terminal escape sequences with cursor positioning (no newlines — eliminates flickering).

A reusable `ParticleSystem` generator powers many of the particle-based animations with configurable emitters, gradients, gravity, and drag.

## tmux Support

termflix auto-detects tmux and adapts:

- **Adaptive frame pacing** — Automatically adjusts frame rate to match tmux's throughput, preventing output backlog and input lag
- **Responsive quit** — Runs `tmux clear-history` on exit to flush buffered output
- **Split-safe** — No lockups when splitting panes; FPS scales with pane size
- **Background-safe** — No output backlog when switching away from iTerm2

### Tearing or flickering rows under tmux

By default termflix uses **differential (dirty-cell) rendering** — each frame sends only the cells that changed, which is the big throughput win under tmux. tmux forwards those updates to your terminal; if it doesn't wrap them in synchronized-output, the terminal applies them non-atomically and you may see brief tearing or a few "stale" rows (most noticeable when the status bar updates each second). Enable tmux's synchronized-output passthrough to fix it:

```bash
tmux set -as terminal-features '*:sync'                         # apply now, current server
echo "set -as terminal-features '*:sync'" >> ~/.tmux.conf       # persist across restarts
```

This needs a terminal that supports synchronized output — iTerm2, Alacritty, kitty, WezTerm, Ghostty, and Warp all do; macOS **Terminal.app does not**. If yours doesn't, run termflix with `--full-frames` under tmux to disable dirty-cell rendering (reverts to a full redraw every frame — no tearing, but no throughput win).

Typical FPS in tmux (200×44, halfblock truecolor):
- Full pane: ~10 fps (smooth)
- Split pane: ~20 fps (less output per frame)
- Outside tmux: 24 fps (full speed)

## Configuration

termflix supports a TOML config file for persistent defaults. CLI flags always override config settings.

```bash
# Generate default config file
termflix --init-config

# Show config file path and current settings
termflix --show-config
```

Config location:
- **macOS**: `~/Library/Application Support/termflix/config.toml`
- **Linux**: `~/.config/termflix/config.toml`
- **Windows**: `%APPDATA%\termflix\config.toml`

Example config:
```toml
# Default animation
animation = "plasma"

# Render mode: braille, half-block, ascii
render = "half-block"

# Color mode: mono, ansi16, ansi256, true-color
color = "true-color"

# Target FPS (1-120)
fps = 24

# Scale factor for particle density (0.5-2.0)
scale = 1.0

# Hide status bar
clean = false

# Auto-cycle interval in seconds (0 = disabled)
cycle = 0

# Remove FPS cap and render as fast as possible (overrides fps)
unlimited_fps = false

# Colorblind-safe remap palette: viridis | magma | inferno | plasma | okabe-ito
# palette = "viridis"

# Daltonization correction: protanopia | deuteranopia | tritanopia
# (mutually exclusive with palette)
# colorblind = "deuteranopia"

# Ordered (Bayer 4x4) dithering for ANSI-256 mode (reduces banding)
# dither = true

# Temporal brightness smoothing time constant in seconds (0 = off)
# smoothing = 0.08

# Color quantization step (0 = off, 4/8/16 = coarser colors, less output)
# color_quant = 0

# External control via an NDJSON file (one JSON object per line)
# data_file = "/tmp/termflix.json"

# Post-processing effects
# [postproc]
# bloom = 0.3               # Glow intensity (0.0-1.0)
# bloom_threshold = 0.6     # Brightness threshold to trigger bloom (0.0-1.0)
# vignette = 0.4            # Edge darkening (0.0-1.0)
# scanlines = false         # CRT scanline effect

# Custom keybindings (action -> key name)
# [keybindings]
# next = "Right"
# prev = "Left"
# quit = "q"
# render = "r"
# color = "c"
# status = "h"
```

## Gallery

A live PNG + GIF gallery of every animation is published at **<https://paulrobello.github.io/termflix/>**, regenerated by the `Gallery` workflow on every push to `main` and on manual dispatch (Actions → Gallery → Run workflow).

To regenerate locally:

```bash
make gallery                            # all animations → ./gallery
make gallery ARGS="fire,plasma"         # subset
make gallery ARGS="fire --gallery-dir /tmp/g"
```

The `gallery/` directory is gitignored — never commit the generated binaries; let CI publish them.

The workflow auto-enables Pages on its first run via `actions/configure-pages` with `enablement: true`. If your fork has Pages disabled organization-wide, flip **Settings → Pages → Build and deployment → Source** to **GitHub Actions** manually before the first run.

## Contributing

Contributions are welcome! To add a new animation:

1. Create `src/animations/your_animation.rs` implementing the `Animation` trait
2. Register it in `src/animations/mod.rs`
3. Run `cargo build --release` and test

```bash
cargo fmt       # Format code
cargo clippy    # Lint
cargo build     # Build
```

## License

This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.

## Author

Paul Robello — probello@gmail.com

## Links

- **GitHub**: [https://github.com/paulrobello/termflix]https://github.com/paulrobello/termflix
- **Crates.io**: [https://crates.io/crates/termflix]https://crates.io/crates/termflix