ASCII videoPro
Live video or the camera as ASCII in Geist Mono for voice and camera modes, drawn from the shared glyph atlas in WebGL. Paused, the frame is text you can select and copy.
On this page
ProCamera mode for a voice agent: a live picture as Geist Mono glyphs from the shared atlas, on a classic or a fine ramp. Pause to select the frame as text.
Installation
Usage
import { AsciiVideo } from "@/components/ui/chatcn/pro/ascii-video"
<AsciiVideo camera label="Your camera as ASCII" columns={72} aspectRatio="3:4" />Each frame's tones are stretched to the full ramp with levels that ease between frames, so a light passing through never makes the picture pump. Glyphs are written into a one byte per cell texture and drawn in a single pass. ASCII_VIDEO_RAMPS.fine gives 70 steps for large grids.
Examples
States
ProPaused on a selectable frame, a fine ramp, a coarse grid on a transparent paper, a negative, the camera prompt and a missing file.
Props
| Prop | Type | Notes |
|---|---|---|
src | string | A video file. Plays muted and loops. Cross-origin files need CORS headers |
stream | MediaStream | null | A call, a screen share or canvas.captureStream(). You stop its tracks |
camera | boolean | MediaTrackConstraints | Use the camera. The frame offers a button, so the prompt follows a click |
autoStart | boolean | Ask for the camera on mount, when permission was granted before |
label | string | Required. The accessible name of the picture |
mirror | boolean | Default on for the camera |
aspectRatio | string | number | Default the video's own, then 16:9 |
paused, defaultPaused, onPausedChange | Controlled or uncontrolled pause | |
pauseControl | boolean | The corner pause button. Default true |
labels | Partial<VideoEffectLabels> | Every string the frame shows, for translation |
onStatusChange | (status) => void | idle, requesting, loading, ready, denied, unavailable or error |
columns | number | Characters across. Default 80 |
ramp | string | Light to dense. Default .:-=+*#%@ |
ink, paper | string | Tokens or CSS colors; paper may be transparent |
contrast, brightness, invert | Defaults 1.2, 0, off | |
autoLevels | boolean | Stretch each frame's tones. Default true |
selectable | boolean | Paused frames become selectable text. Default true |
fps | number | Default 20 |
Keyboard
| Key | Action |
|---|---|
Tab | Reaches the camera, retry and pause buttons |
Enter, Space | Turns on the camera, retries, pauses or plays |
Accessibility
- The picture is named by your
labelthroughrole="img"; the canvas and the<video>that feeds it are hidden from screen readers. - The camera prompt, the waiting state and every error are real text with a button that fixes the problem: blocked access points to the site settings, a missing camera asks to connect one, a camera in use names the other app.
- The pause button sits in the corner of any frame that loops (WCAG 2.2.2) and is reachable by keyboard.
- Under forced colors the effect hides and the plain video shows. Under
prefers-contrast: moreink and paper snap to the text and canvas tokens. - The paused text layer is hidden from screen readers: the glyphs describe nothing a label does not.
Motion
- Frames flow only while the frame is on screen, the tab is visible and nobody paused it. A paused or offscreen file pauses its playback too, so nothing decodes in the background.
- Under reduced motion files and streams hold their first frame until the person presses play. A camera the person turned on runs: it is their own picture, not decoration.
- The first frame fades in over 200 ms; nothing else animates.