Skip to content
Sign in
EffectsASCII videoMenu

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.

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

$ pnpm dlx shadcn@latest add @chatcn-pro/ascii-video

Usage

tsx
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

PropTypeNotes
srcstringA video file. Plays muted and loops. Cross-origin files need CORS headers
streamMediaStream | nullA call, a screen share or canvas.captureStream(). You stop its tracks
cameraboolean | MediaTrackConstraintsUse the camera. The frame offers a button, so the prompt follows a click
autoStartbooleanAsk for the camera on mount, when permission was granted before
labelstringRequired. The accessible name of the picture
mirrorbooleanDefault on for the camera
aspectRatiostring | numberDefault the video's own, then 16:9
paused, defaultPaused, onPausedChangeControlled or uncontrolled pause
pauseControlbooleanThe corner pause button. Default true
labelsPartial<VideoEffectLabels>Every string the frame shows, for translation
onStatusChange(status) => voididle, requesting, loading, ready, denied, unavailable or error
columnsnumberCharacters across. Default 80
rampstringLight to dense. Default .:-=+*#%@
ink, paperstringTokens or CSS colors; paper may be transparent
contrast, brightness, invertDefaults 1.2, 0, off
autoLevelsbooleanStretch each frame's tones. Default true
selectablebooleanPaused frames become selectable text. Default true
fpsnumberDefault 20

Keyboard

KeyAction
TabReaches the camera, retry and pause buttons
Enter, SpaceTurns on the camera, retries, pauses or plays

Accessibility

  • The picture is named by your label through role="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: more ink 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.