Live webcam → ASCII art in your terminal. 95-char density ramp, truecolor output, painterly color styles, optional solid-block rendering, and a few fractal-driven psychedelic modes.
If you've never built a Rust project on this Mac, you need the Xcode linker and the Rust toolchain. Both installs are one command each.
# 1. Xcode Command Line Tools (needed for the linker — pops up a GUI prompt)
xcode-select --install
# 2. Rust toolchain via rustup (installs cargo into ~/.cargo/bin)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 3. Pick up the new PATH in this shell session
source "$HOME/.cargo/env"After rustc --version prints something, follow the steps below.
cargo install --git https://github.com/bluevisor/terminal-camThe binary lands in ~/.cargo/bin/terminal-cam (already on PATH if
you sourced $HOME/.cargo/env). Run it with terminal-cam.
Or clone and run from the source tree:
git clone https://github.com/bluevisor/terminal-cam
cd terminal-cam
cargo run --releasemacOS will prompt for camera permission on first launch — grant it to your terminal application (System Settings → Privacy & Security → Camera).
| Key | Action |
|---|---|
Esc |
Open / close menu |
↑ ↓ |
Select menu item |
← → |
Change value |
Enter |
Apply / advance |
Space |
Save screenshot |
q / Ctrl-C |
Quit |
- Camera source — cycle detected cameras
- Style —
Color,Vivid,B&W,Grayscale,Sepia,Van Gogh,Monet,Alice,LucyVan Gogh— static palette snap. Source hue picks one of three ramps (cool / warm / green), source luma picks the anchor within it. Hand-curated from Starry Night, Irises, and the self-portrait.Monet— pastelized HSV with a slow dappled-light mottle and atmospheric warm/cool shift.Alice— geometry-first. Source colors pass through near-untouched; a Julia-set iteration field carves dark fractal ribbons along image edges, the source is UV-warped by a domain-warped two-octave sine field, and a slow breathing radial chromatic aberration splays RGB fringes from the corners inward.Lucy— fluid-dynamic overlay. A scalar flow field built from domain-warped sine noise streams along edge tangents (perpendicular to the luma gradient) so swirls trace contours rather than crossing them; an afterimage feedback buffer leaves fading rainbow trails behind motion.
- Render mode —
ASCII(density-ramp glyphs) orBlocks(solid█in color styles so the color escape alone carries the image;░▒▓█shading ramp in B&W). - Color depth —
auto/truecolor/256/16. Auto-detects fromCOLORTERM; falls back to 256-color for terminals that don't speak 24-bit. - Mirror — horizontal flip (on by default; webcams are usually mirrored).
- Brightness —
-1.00to+1.00, added to each RGB channel pre-style. - Contrast —
0.1to3.0. Applied to RGB upstream (not just to glyph density) so it affects the emitted color, Van Gogh palette-band selection, and Alice / Lucy HSV value. - Screenshot path — directory used when pressing
Space. PressEnteror→on the row, type a path, then pressEnterto save it to the app config.~is expanded to your home directory.
Screenshots are saved as PNG files using the current terminal crop, mirror, style, brightness, contrast, and render mode settings.
| Terminal | Auto-detects as |
|---|---|
| iTerm2, Warp, Kitty, Alacritty, Ghostty, WezTerm, VS Code | truecolor |
| Apple Terminal.app | 256 |
anything with TERM=*-256color |
256 |
If colors look wrong, the terminal probably doesn't support truecolor —
open the menu and set Color depth to 256. The image will show some
banding but the colors will be correct.
Per terminal cell, every frame:
- Average RGB over the source block.
- Add brightness offset, apply contrast stretch around mid-gray (128).
- Run the style transform. Palette / fractal styles produce new RGB from source luma + hue (Van Gogh), HSV rotation (Monet / Alice / Lucy), or an affine matrix (Sepia).
- Recompute luminance from the stylized RGB.
- Pick a glyph:
- ASCII: sigmoid-shaped luma indexes the 95-char density ramp.
- Blocks (color): solid
█— color escape carries brightness. - Blocks (B&W):
░▒▓█shading ramp, since there's no color channel.
- Quantize the fg color to the selected depth (truecolor / 256-palette / ANSI-16) and emit the escape + glyph.
Each frame is wrapped in DEC 2026 synchronized-update markers
(\x1b[?2026h / \x1b[?2026l) so supporting terminals paint atomically.
The options overlay is composed into the same byte buffer as the render
and flushed in one write — no camera-flash-behind-menu flicker.
Aspect ratio is preserved via center-crop: the source is cropped to match
the terminal grid's pixel canvas (cols : rows × CHAR_ASPECT) so faces
don't squash or stretch as you resize the window.
src/main.rs— input loop, terminal mode setup, frame pacingsrc/camera.rs—nokhwacapture thread + shared frame slotsrc/render.rs— per-cell render pipeline, config, synchronized outputsrc/screenshot.rs— screenshot capture + dependency-free PNG writingsrc/config.rs— screenshot path config load/savesrc/style.rs— style transforms (Sepia / Van Gogh / Monet / Alice / Lucy) and the Julia-set iteration helpersrc/color.rs— depth detection + truecolor / 256 / ANSI-16 quantizationsrc/ascii.rs— 95-char density ramp and 5-stop shading rampsrc/menu.rs— centered options overlay (half-block title, version footer, rendered into the render buffer so it composites atomically)
The terminal cell aspect ratio (CHAR_ASPECT = 2.0 in src/render.rs)
is the one font-dependent constant. If circles render as horizontal
ovals, bump it; if vertical ovals, drop it. iTerm2 / Terminal.app / Kitty
with default fonts are all close to 2.0.
Van Gogh's three palette ramps live at the top of src/style.rs as
VG_COOL / VG_WARM / VG_GREEN. Each is a 5-anchor ramp (dark →
light); swap in your own anchors for a different painter.
Alice and Lucy's Julia c parameter drifts on a small loop — tune
speed, amplitude, and center in alice() / lucy() in src/style.rs
to explore different regions of the fractal parameter space.
nokhwa— cross-platform camera capturecrossterm— terminal I/Oparking_lot— faster mutex for the frame slotanyhow— error handling
MIT — see LICENSE.