Ascii video output from your webcam in your terminal.
Find a file
Harshit-Dhanwalkar 96369d6f94 Add nl_srterror
2026-06-21 19:15:08 +05:30
assets Implementing my own C libs 2026-06-08 13:36:51 +05:30
C Add nl_srterror 2026-06-21 19:15:08 +05:30
Cpp Update README and organise file structure 2026-05-15 01:27:35 +05:30
tests rename file to security_tests.c 2026-06-01 23:26:51 +05:30
.gitignore Update Readme and gitignore 2026-06-17 15:54:08 +05:30
LICENCE Add PolyForm non-commerial LICENSE 2026-06-01 17:08:59 +05:30
README.md Update README and format code 2026-06-19 13:07:18 +05:30

AsciiCam

Real-time ASCII video from your webcam in the terminal - pure C99, no heavy runtime dependencies.

Edge detection + threshold plugin


Features

Feature Details
YUYV to grayscale SSE2 SIMD (yuyv_to_gray_simd) - 16 pixels per iteration on x86_64, NEON on ARM64
YUYV to RGB Fixedpoint BT.601 conversion for truecolor output
Multiple render modes Braille (), Blocks (█ ░), ASCII ramp, Halfblock, Dots - switch live with m/M
Edge detection Sobel, Sobel with direction, Laplacian - toggle with x/X
Hotreloadable charsets Load .txt ramps from a directory, switch with n/N, monitor with inotify
Pseudo3D depth pop Parallax effect based on brightness - adjust with +/-/v
FloydSteinberg dither Errordiffusion to reduce banding
ANSI truecolor \033[38;2;R;G;Bm percell coloring
Hotreload plugin system inotify + dlopen - rebuild a filter .so, it reloads live
FPScapped render loop CLOCK_MONOTONIC + nanosleep frame pacing
Producer/consumer threads Doublebuffered capture + render (stubbed in main loop, active in thread_sharing.c)
Hardware camera controls V4L2 exposure, contrast, white-balance via ioctl — live keys e/E, c/C, w/W (Linux only; macOS/Windows display n/a)
Crossplatform Linux (V4L2, nolibc), macOS (AVFoundation, system libc), Windows (Media Foundation)

Linux: requires gcc, linux/videodev2.h (kernel headers), libdl, libpthread. macOS: requires Clang and AVFoundation frameworks (linked automatically). Windows: requires MinGW-w64; links mfplat, mf, mfreadwrite, mfuuid, ole32 (Media Foundation). See Makefile windows branch.

No other external dependencies.


Build

git clone https://github.com/Harshit-Dhanwalkar/AsciiCam.git
cd AsciiCam/C/
make

Requires: gcc, linux/videodev2.h (kernel headers), libdl, libpthread. No other external dependencies.

build/webcam_ascii --help

Run

# Basic (grayscale, 80×40, /dev/video0)
./build/webcam_ascii

# Truecolor output
./build/webcam_ascii -C

# With all three plugins
./build/webcam_ascii -p build/invert.so -p build/threshold.so -p build/edge_detect.so

# Edge detection mode, custom resolution
./build/webcam_ascii -e -w 320 -h 240 -W 120 -H 50

# Dithering + inverted charset
./build/webcam_ascii -D -i

Plugin system

Plugins are shared objects (.so).

gcc -O2 -fPIC -shared -Iinclude filters/my_filter.c -o build/my_filter.so
./build/webcam_ascii -p build/my_filter.so

Hot-reload: the binary watches the .so with inotify. Recompile it while the viewer is running and it reloads automatically within $\approx$100 ms.

Runtime controls:

Key Action
m / M cycle render mode forward / backward
x / X cycle edge detection mode forward / backward
n / N cycle loaded charset forward / backward
p / o increase / decrease depth-pop strength
e / E hw exposure down / up (V4L2, Linux only)
w / W hw white-balance down / up (V4L2, Linux only)
c / C hw contrast down / up (V4L2, Linux only)
/ select plugin
[ / ] param $\pm$1
{ / } param $\pm$10
r reset param to 128
q quit

TODO

  • Adjustable capture resolution
  • Producer/consumer thread split (double-buffered)
  • Brightness / contrast adjustment
  • Invert brightness to charset mapping
  • ANSI truecolor output
  • Floyd-Steinberg dithering
  • Sobel edge detection
  • SIMD YUYV to grayscale (SSE2)
  • Hot-reload plugin system
  • nolibc - zero libc calls
  • Custom charset via config file
  • Hardware camera controls (V4L2 exposure / contrast / white-balance)
  • MacOS support
  • Windows support (Media Foundation capture backend)
    • Windows console raw-mode and signal handling (SetConsoleMode / SetConsoleCtrlHandler)
    • Hardware controls via IAMCameraControl / IAMVideoProcAmp (capture works, controls stubbed)
    • macOS hardware controls via AVCaptureDevice exposure/white-balance APIs (capture works, controls stubbed)
  • Cature frame resizing
  • Record to .mp4 / .gif
  • Inter-frame delta compression
  • LUT cache optimization
  • Replace pthread with raw futex syscalls
  • Replace dlopen with a minimal ELF loader
  • Custom threading library using clone() + futex to eliminate -lpthread dependency
  • Implement an ELF loader (or statically link plugins) to eliminate -ldl dependency
    • Color support for MacOS

Fixes

  • Issue #2 MacOS support
  • nl_calloc: zero-fill loop was commented out (returned uninitialized memory) and the SIZE_MAX overflow guard ran after the allocation, leaking the spurious block on overflow. Both fixed.
  • nl_free: backward coalescing was a TODO stub — non-LIFO frees (e.g. edge-detection scratch buffers) left permanently unmerged holes. Implemented by walking from arena start to find the preceding block.
  • main.c double-buffer bug: a second out_buf was malloc/free'd every frame inside the loop, shadowing the persistent pre-loop allocation. Frame-loop malloc removed; the single persistent buffer is reused for the program's lifetime.
  • ascii.c RENDER_HALF_BLOCK height rounding: safe_dst_h was rounded down to a multiple of 4 unconditionally, but half-block mode only needs multiples of 2 (it stacks 2 subpixel rows per glyph, not 4). Fixed to be mode-aware.

Project is under PolyForm Noncommercial License BY-NC. For commercial use contact harshitpd1729@gmail.com.