Back to Hermes Agent

☤ ASCII Video

skills/creative/ascii-video/README.md

2026.6.516.1 KB
Original Source

☤ ASCII Video

Renders any content as colored ASCII character video. Audio, video, images, text, or pure math in, MP4/GIF/PNG sequence out. Full RGB color per character cell, 1080p 24fps default. No GPU.

Built for Hermes Agent. Usable in any coding agent. Canonical source lives here; synced to NousResearch/hermes-agent/skills/creative/ascii-video via PR.

What this is

A skill that teaches an agent how to build single-file Python renderers for ASCII video from scratch. The agent gets the full pipeline: grid system, font rasterization, effect library, shader chain, audio analysis, parallel encoding. It writes the renderer, runs it, gets video.

The output is actual video. Not terminal escape codes. Frames are computed as grids of colored characters, composited onto pixel canvases with pre-rasterized font bitmaps, post-processed through shaders, piped to ffmpeg.

Modes

ModeInputOutput
Video-to-ASCIIA video fileASCII recreation of the footage
Audio-reactiveAn audio fileVisuals driven by frequency bands, beats, energy
GenerativeNothingProcedural animation from math
HybridVideo + audioASCII video with audio-reactive overlays
Lyrics/textAudio + timed text (SRT)Karaoke-style text with effects
TTS narrationText quotes + API keyNarrated video with typewriter text and generated speech

Pipeline

Every mode follows the same 6-stage path:

INPUT --> ANALYZE --> SCENE_FN --> TONEMAP --> SHADE --> ENCODE
  1. Input loads source material (or nothing for generative).
  2. Analyze extracts per-frame features. Audio gets 6-band FFT, RMS, spectral centroid, flatness, flux, beat detection with exponential decay. Video gets luminance, edges, motion.
  3. Scene function returns a pixel canvas directly. Composes multiple character grids at different densities, value/hue fields, pixel blend modes. This is where the visuals happen.
  4. Tonemap does adaptive percentile-based brightness normalization with per-scene gamma. ASCII on black is inherently dark. Linear multipliers don't work. This does.
  5. Shade runs a ShaderChain (38 composable shaders) plus a FeedbackBuffer for temporal recursion with spatial transforms.
  6. Encode pipes raw RGB frames to ffmpeg for H.264 encoding. Segments concatenated, audio muxed.

Grid system

Characters render on fixed-size grids. Layer multiple densities for depth.

SizeFontGrid at 1080pUse
xs8px400x108Ultra-dense data fields
sm10px320x83Rain, starfields
md16px192x56Default balanced
lg20px160x45Readable text
xl24px137x37Large titles
xxl40px80x22Giant minimal

Rendering the same scene on sm and lg then screen-blending them creates natural texture interference. Fine detail shows through gaps in coarse characters. Most scenes use two or three grids.

Character palettes (24)

Each sorted dark-to-bright, each a different visual texture. Validated against the font at init so broken glyphs get dropped silently.

FamilyExamplesFeel
Density ramps .:-=+#@█Classic ASCII art gradient
Block elements ░▒▓█▄▀▐▌Chunky, digital
Braille ⠁⠂⠃...⠿Fine-grained pointillism
Dots ⋅∘∙●◉◎Smooth, organic
Stars ·✧✦✩✨★✶Sparkle, celestial
Half-fills ◔◑◕◐◒◓◖◗◙Directional fill progression
Crosshatch ▣▤▥▦▧▨▩Hatched density ramp
Math ·∘∙•°±×÷≈≠≡∞∫∑ΩScientific, abstract
Box drawing ─│┌┐└┘├┤┬┴┼Structural, circuit-like
Katakana ·ヲァィゥェォャュ...Matrix rain
Greek αβγδεζηθ...ωClassical, academic
Runes ᚠᚢᚦᚱᚷᛁᛇᛒᛖᛚᛞᛟMystical, ancient
Alchemical ☉☽♀♂♃♄♅♆♇Esoteric
Arrows ←↑→↓↔↕↖↗↘↙Directional, kinetic
Music ♪♫♬♩♭♮♯○●Musical
Project-specific .·~=≈∞⚡☿✦★⊕◊◆▲▼●■Themed per project

Custom palettes are built per project to match the content.

Color strategies

StrategyHow it maps hueGood for
Angle-mappedPosition angle from centerRainbow radial effects
Distance-mappedDistance from centerDepth, tunnels
Frequency-mappedAudio spectral centroidTimbral shifting
Value-mappedBrightness levelHeat maps, fire
Time-cycledSlow rotation over timeAmbient, chill
Source-sampledOriginal video pixel colorsVideo-to-ASCII
Palette-indexedDiscrete lookup tableRetro, flat graphic
TemperatureWarm-to-cool blendEmotional tone
ComplementaryHue + oppositeBold, dramatic
TriadicThree equidistant huesPsychedelic, vibrant
AnalogousNeighboring huesHarmonious, subtle
MonochromeFixed hue, vary S/VNoir, focused

Plus 10 discrete RGB palettes (neon, pastel, cyberpunk, vaporwave, earth, ice, blood, forest, mono-green, mono-amber).

Full OKLAB/OKLCH color system: sRGB↔linear↔OKLAB conversion pipeline, perceptually uniform gradient interpolation, and color harmony generation (complementary, triadic, analogous, split-complementary, tetradic).

Value field generators (21)

Value fields are the core visual building blocks. Each produces a 2D float array in [0, 1] mapping every grid cell to a brightness value.

Trigonometric (12)

FieldDescription
Sine fieldLayered multi-sine interference, general-purpose background
Smooth noiseMulti-octave sine approximation of Perlin noise
RingsConcentric rings, bass-driven count and wobble
SpiralLogarithmic spiral arms, configurable arm count/tightness
TunnelInfinite depth perspective (inverse distance)
VortexTwisting radial pattern, distance modulates angle
InterferenceN overlapping sine waves creating moire
AuroraHorizontal flowing bands
RippleConcentric waves from configurable source points
PlasmaSum of sines at multiple orientations/speeds
DiamondDiamond/checkerboard pattern
Noise/staticRandom per-cell per-frame flicker

Noise-based (4)

FieldDescription
Value noiseSmooth organic noise, no axis-alignment artifacts
fBMFractal Brownian Motion — octaved noise for clouds, terrain, smoke
Domain warpInigo Quilez technique — fBM-driven coordinate distortion for flowing organic forms
VoronoiMoving seed points with distance, edge, and cell-ID output modes

Simulation-based (4)

FieldDescription
Reaction-diffusionGray-Scott with 7 presets: coral, spots, worms, labyrinths, mitosis, pulsating, chaos
Cellular automataGame of Life + 4 rule variants with analog fade trails
Strange attractorsClifford, De Jong, Bedhead — iterated point systems binned to density fields
Temporal noise3D noise that morphs in-place without directional drift

SDF-based

7 signed distance field primitives (circle, box, ring, line, triangle, star, heart) with smooth boolean combinators (union, intersection, subtraction, smooth union/subtraction) and infinite tiling. Render as solid fills or glowing outlines.

Hue field generators (9)

Determine per-cell color independent of brightness: fixed hue, angle-mapped rainbow, distance gradient, time-cycled rotation, audio spectral centroid, horizontal/vertical gradients, plasma variation, perceptually uniform OKLCH rainbow.

Coordinate transforms (11)

UV-space transforms applied before effect evaluation: rotate, scale, skew, tile (with mirror seaming), polar, inverse-polar, twist (rotation increasing with distance), fisheye, wave displacement, Möbius conformal transformation. make_tgrid() wraps transformed coordinates into a grid object.

Particle systems (9)

TypeBehavior
ExplosionBeat-triggered radial burst with gravity and life decay
EmbersRising from bottom with horizontal drift
Dissolving cloudSpreading outward with accelerating fade
Starfield3D projected, Z-depth stars approaching with streak trails
OrbitCircular/elliptical paths around center
Gravity wellAttracted toward configurable point sources
Boid flockingSeparation/alignment/cohesion with spatial hash for O(n) neighbors
Flow-fieldSteered by gradient of any value field
Trail particlesFading lines between current and previous positions

14 themed particle character sets (energy, spark, leaf, snow, rain, bubble, data, hex, binary, rune, zodiac, dot, dash).

Temporal coherence

10 easing functions (linear, quad, cubic, expo, elastic, bounce — in/out/in-out). Keyframe interpolation with eased transitions. Value field morphing (smooth crossfade between fields). Value field sequencing (cycle through fields with crossfade). Temporal noise (3D noise evolving smoothly in-place).

Shader pipeline

38 composable shaders, applied to the pixel canvas after character rendering. Configurable per section.

CategoryShaders
GeometryCRT barrel, pixelate, wave distort, displacement map, kaleidoscope, mirror (h/v/quad/diag)
ChannelChromatic aberration (beat-reactive), channel shift, channel swap, RGB split radial
ColorInvert, posterize, threshold, solarize, hue rotate, saturation, color grade, color wobble, color ramp
Glow/BlurBloom, edge glow, soft focus, radial blur
NoiseFilm grain (beat-reactive), static noise
Lines/PatternsScanlines, halftone
ToneVignette, contrast, gamma, levels, brightness
Glitch/DataGlitch bands (beat-reactive), block glitch, pixel sort, data bend

12 color tint presets: warm, cool, matrix green, amber, sepia, neon pink, ice, blood, forest, void, sunset, neutral.

7 mood presets for common shader combos:

MoodShaders
Retro terminalCRT + scanlines + grain + amber/green tint
Clean modernLight bloom + subtle vignette
Glitch artHeavy chromatic + glitch bands + color wobble
CinematicBloom + vignette + grain + color grade
DreamyHeavy bloom + soft focus + color wobble
Harsh/industrialHigh contrast + grain + scanlines, no bloom
PsychedelicColor wobble + chromatic + kaleidoscope mirror

Blend modes and composition

20 pixel blend modes for layering canvases: normal, add, subtract, multiply, screen, overlay, softlight, hardlight, difference, exclusion, colordodge, colorburn, linearlight, vividlight, pin_light, hard_mix, lighten, darken, grain_extract, grain_merge. Both sRGB and linear-light blending supported.

Feedback buffer. Temporal recursion — each frame blends with a transformed version of the previous frame. 7 spatial transforms: zoom, shrink, rotate CW/CCW, shift up/down, mirror. Optional per-frame hue shift for rainbow trails. Configurable decay, blend mode, and opacity per scene.

Masking. 16 mask types for spatial compositing: shape masks (circle, rect, ring, gradients), procedural masks (any value field as a mask, text stencils), animated masks (iris open/close, wipe, dissolve), boolean operations (union, intersection, subtraction, invert).

Transitions. Crossfade, directional wipe, radial wipe, dissolve, glitch cut.

Scene design patterns

Compositional patterns for making scenes that look intentional rather than random.

Layer hierarchy. Background (dim atmosphere, dense grid), content (main visual, standard grid), accent (sparse highlights, coarse grid). Three distinct roles, not three competing layers.

Directional parameter arcs. The defining parameter of each scene ramps, accelerates, or builds over its duration. Progress-based formulas (linear, ease-out, step reveal) replace aimless sin(t) oscillation.

Scene concepts. Scenes built around visual metaphors (emergence, descent, collision, entropy) with motivated layer/palette/feedback choices. Not named after their effects.

Compositional techniques. Counter-rotating dual systems, wave collision, progressive fragmentation (voronoi cells multiplying over time), entropy (geometry consumed by reaction-diffusion), staggered layer entry (crescendo buildup).

Hardware adaptation

Auto-detects CPU count, RAM, platform, ffmpeg. Adapts worker count, resolution, FPS.

ProfileResolutionFPSWhen
draft960x54012Check timing/layout
preview1280x72015Review effects
production1920x108024Final output
max3840x216030Ultra-high
autoDetected24Adapts to hardware + duration

auto estimates render time and downgrades if it would take over an hour. Low-memory systems drop to 720p automatically.

Render times (1080p 24fps, ~180ms/frame/worker)

Duration4 workers8 workers16 workers
30s~3 min~2 min~1 min
2 min~13 min~7 min~4 min
5 min~33 min~17 min~9 min
10 min~65 min~33 min~17 min

720p roughly halves these. 4K roughly quadruples them.

Known pitfalls

Brightness. ASCII characters are small bright dots on black. Most frame pixels are background. Linear * N multipliers clip highlights and wash out. Use tonemap() with per-scene gamma instead. Default gamma 0.75, solarize scenes 0.55, posterize 0.50.

Render bottleneck. The per-cell Python loop compositing font bitmaps runs at ~100-150ms/frame. Unavoidable without Cython/C. Everything else must be vectorized numpy. Python for-loops over rows/cols in effect functions will tank performance.

ffmpeg deadlock. Never stderr=subprocess.PIPE on long-running encodes. Buffer fills at ~64KB, process hangs. Redirect stderr to a file.

Font cell height. Pillow's textbbox() returns wrong height on macOS. Use font.getmetrics() for ascent + descent.

Font compatibility. Not all Unicode renders in all fonts. Palettes validated at init, blank glyphs silently removed.

Requirements

◆ Python 3.10+ ◆ NumPy, Pillow, SciPy (audio modes) ◆ ffmpeg on PATH ◆ A monospace font (Menlo, Courier, Monaco, auto-detected) ◆ Optional: OpenCV, ElevenLabs API key (TTS mode)

File structure

├── SKILL.md                 # Modes, workflow, creative direction
├── README.md                # This file
└── references/
    ├── architecture.md      # Grid system, fonts, palettes, color, _render_vf()
    ├── effects.md           # Value fields, hue fields, backgrounds, particles
    ├── shaders.md           # 38 shaders, ShaderChain, tint presets, transitions
    ├── composition.md       # Blend modes, multi-grid, tonemap, FeedbackBuffer
    ├── scenes.md            # Scene protocol, SCENES table, render_clip(), examples
    ├── design-patterns.md   # Layer hierarchy, directional arcs, scene concepts
    ├── inputs.md            # Audio analysis, video sampling, text, TTS
    ├── optimization.md      # Hardware detection, vectorized patterns, parallelism
    └── troubleshooting.md   # Broadcasting traps, blend pitfalls, diagnostics

Projects built with this

✦ 85-second highlight reel. 15 scenes (14×5s + 15s crescendo finale), randomized order, directional parameter arcs, layer hierarchy composition. Showcases the full effect vocabulary: fBM, voronoi fragmentation, reaction-diffusion, cellular automata, dual counter-rotating spirals, wave collision, domain warping, tunnel descent, kaleidoscope symmetry, boid flocking, fire simulation, glitch corruption, and a 7-layer crescendo buildup.

✦ Audio-reactive music visualizer. 3.5 min, 8 sections with distinct effects, beat-triggered particles and glitch, cycling palettes.

✦ TTS narrated testimonial video. 23 quotes, per-quote ElevenLabs voices, background music at 15% wide stereo, per-clip re-rendering for iterative editing.