Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
A

ASCILINE

> 编程语言
Open source

A high-performance ASCII video rendering engine featuring real-time WebSocket binary streaming and an isolated compiler for serverless static generation. Built

2.6K stars0 likes1 views
WebsiteGitHub

About

A high-performance ASCII video rendering engine featuring real-time WebSocket binary streaming and an isolated compiler for serverless static generation. Built

 █████╗ ███████╗ ██████╗██╗██╗     ██╗███╗   ██╗███████╗  ██
██╔══██╗██╔════╝██╔════╝██║██║     ██║████╗  ██║██╔════╝  █████
███████║███████╗██║     ██║██║     ██║██╔██╗ ██║█████╗    ████████
██╔══██║╚════██║██║     ██║██║     ██║██║╚██╗██║██╔══╝    ████████
██║  ██║███████║╚██████╗██║███████╗██║██║ ╚████║███████╗  █████
╚═╝  ╚═╝╚══════╝ ╚═════╝╚═╝╚══════╝╚═╝╚═╝  ╚═══╝╚══════╝  ██

ASCILINE is a high-performance, cross-platform real-time ASCII video rendering engine. It maps pixels to text-based representations and streams the result over a low-overhead binary protocol, turning the browser canvas into a typographic display surface.

Output Details
Original Source
Standard MP4 video file.
ASCII Mode
Rendered using Mode 4 (32K colors) from a 30fps source.
PIXEL Mode
Rendered using the --pixel flag for high fidelity colored blocks █ .

Table of Contents

  • Design Goals
  • Technical Features
  • Architecture
  • Adaptive Frame Codec (opt-in, ASCII modes 2-6)
  • Zero-Dependency Static Web Player
  • Installation
  • Running with Docker
  • Customization
  • Troubleshooting
  • Live Demo
  • Star History
  • Support ❤️
  • License
  • Community
  • Contact

Design Goals

  1. Pure typographic manipulation: the visual stream is raw HTML/Canvas text, not a standard media file. That means real-time CSS filters (glows, shadows, animations) can be applied directly to what would otherwise be a video.
  2. Zero GPU, ultra-low bandwidth (ASCII modes): standard codecs (H.264/VP9) need dedicated hardware decoders, which chokes microcontrollers and weak devices. ASCILINE does the heavy lifting server-side and streams lightweight text frames — fewer columns means proportionally less bandwidth. This makes fluid playback possible on constrained networks and zero-GPU devices (smart appliances, retro terminals, basic microcontrollers).
  3. Works everywhere: no <video> tag, no browser-side codec decoding, no autoplay restrictions. To the browser, it's just text on a canvas.

Roadmap idea, not implemented yet: because ASCII output is already a compact, structured text representation, it could in principle serve as a lightweight input for downstream text/LLM processing instead of feeding raw pixel streams to a vision model. Nothing in the current codebase does this — flagging it here as a direction, not a shipped feature.

Technical Features

  • Cross-platform: Windows, macOS, Linux.
  • Real-time ASCII and pixel streaming: low-latency video-to-text conversion; pixel mode replaces characters with colored blocks, approaching 360p quality.
  • HTML5 Canvas rendering, tuned for 24–30 FPS playback. Higher-FPS sources are automatically decimated for stability.
  • Master clock sync: the audio track is the absolute time reference, keeping A/V synchronized.
  • Low-overhead binary protocol: frames are streamed as raw Uint8Array straight to the canvas.
  • Multiple color modes: from black & white up to 16M-color high fidelity.
  • Flexible video management: JSON playlists (per-video mode & volume), folder-based auto-queuing, single-file mode, infinite loop — all via CLI flags.

Architecture

  1. Backend (Python/FastAPI): decodes video via OpenCV, maps pixels to ASCII via NumPy, streams binary frames.
  2. Frontend (vanilla JS): receives binary frames over WebSocket, manages a jitter buffer, renders to a canvas grid.
  3. Communication: a custom INIT handshake negotiates resolution/FPS, followed by the binary frame stream.

ASCILINE uses a modular architecture that separates the core rendering engine from its delivery methods.

…

Adaptive Frame Codec (opt-in, ASCII modes 2-6)

The original protocol re-sends the full grid every frame. An opt-in adaptive codec picks the smallest of several encodings per frame and tags it with a 1-byte header, without changing the rendered output:

tag encoding best for
0 RAW framebuffer as-is (legacy) incompressible frames
1 ZLIB zlib(framebuffer) general motion
2 DELTA only the cells that changed since the last frame static / low-motion
3 RLE_FULL run-length encoded framebuffer large flat-color regions
4 DCT Discrete Cosine Transform High-ratio spatial compression. Used exclusively by the static player. Automatically enforces --pixel output.

Clients opt in with /ws?codec=adaptive; omit it and you get the original protocol byte-for-byte, so existing clients are unaffected. A keyframe is forced periodically so dropped packets / late joiners resync.

codec.js (the shared decoder used by both the live player and the test suite) understands all four tags. Not every encoder produces all four, though: the Python side (codec.py, used by the live server and by compiler.py) can emit RLE_FULL when it wins the size comparison. The browser-side JS encoder (static_player/studio/encoder.js, used by the client-only Studio compiler) intentionally only emits RAW/ZLIB/DELTA — it doesn't implement RLE run-building, to keep the in-browser encoder simple. RAW/ZLIB/DELTA already cover most cases reasonably well, so this is a deliberate simplicity/size trade-off, not a bug — decoders stay permissive, encoders stay conservative.

Measured wire savings (mode 6, 200×80 grid):

content vs. legacy
static screen / slideshow 0.3% (≈375×)
high-motion / full-frame change 63% (never worse than legacy)

An optional --quality {lossless,high,balanced,low} enables lossy temporal delta: a color cell is only re-sent once it drifts past a tolerance from what the viewer already sees (the character plane stays exact), cutting the hard cases a further ~15–30% at imperceptible quality. Default is lossless (bit-exact).

Monitor bandwidth in real time: pass --debug when launching the server to see live RAW vs WIRE byte comparisons and the compression ratio in your terminal.

Verified two independent ways, both bit-exact: Python-encoded vectors decoded by codec.js in Node (experiments/gen_vectors.py → experiments/check_vectors.js), and a live adaptive-vs-legacy WebSocket diff (experiments/test_e2e.js). Generate test clips with experiments/make_test_clips.sh.

LAN / network streaming: use --host to expose the server on your network.

bash
python stream_server.py video.mp4 --host 0.0.0.0

Zero-Dependency Static Web Player

ASCILINE can compile a video into a self-contained .ascf (ASCII Compressed Format) file and play it back with a static HTML page — no Python backend at runtime, hostable anywhere (GitHub Pages, Vercel, Netlify).

Trade-off: compiled .ascf files are naturally larger than standard .mp4. In exchange you get true DOM-level interaction, pixel-perfect text selection, and no dependency on the browser's video codecs.

There are two ways to produce a .ascf file:

1. Python compiler (more capable and faster — the recommended default)

bash
python compiler.py your_video.mp4 --cols 250 --pixel --quantize 2
  • --quantize 0-3: drops color bits to reduce file size (0 = lossless, 3 = aggressive).
  • --profile: Enables Discrete Cosine Transform (Tag 4) spatial compression. Provides the engine's highest compression ratio, significantly reducing the final .ascf payload size at the cost of higher encode times and lossy quantization. Automatically enforces --pixel.
  • --qf 1-100: Quality factor for the DCT profile (default: 70). Higher means better quality and larger file.
  • --tolerance: color drift tolerance before a pixel update is sent, to skip invisible changes.
  • --hard: max zlib compression (level 9) — slower to compile, smaller output.

This is what powers the live demo at asciline.dev: the static clips there are compiled with this Python path.

2. Browser Studio — compile & watch without installing anything

static_player/studio/ is a standalone page (index.html + encoder.js, using pako from a CDN) that compiles a video to .ascf entirely client-side — drop a video in, get a .ascf out, nothing ever leaves your browser, no Python required.

u can try it from - https://yusufb5.github.io/ASCILINE/static_player/studio/

The page includes a built-in preview with a custom seekbar, allowing you to instantly scrub through your compiled clip. Because it shares the main codec.js, this studio player natively decodes all advanced compression tags (including Tag 4 DCT).

(Note: While it can play all tags, the client-side encoder itself is conservative and only emits RAW/ZLIB/DELTA for speed. For production output or maximum compression with RLE/DCT, use the Python compiler).

Playing a compiled file (the full player)

For the full experience — audio sync and ASCII/pixel mode support — use the main player at static_player/index.html.

Method A: Drag & Drop (No server needed!) Simply open static_player/index.html in your browser and drag your .ascf file (along with an optional .mp3 file for audio) directly onto the page. Playback starts instantly, completely bypassing browser CORS restrictions with zero backend required.

Method B: Local File Server If you prefer to load files via URL instead of drag-and-drop, serve the folder through a plain static server:

bash
python -m http.server

Infinite Playback & Low RAM: The static player uses an aggressive rolling buffer (~3 seconds). Rendered frames are instantly garbage-collected, allowing continuous playback with no duration limit and a near-zero memory footprint.

Installation

0. Requirements

  • Python 3.9+
  • FFmpeg & FFprobe (see below — required for audio and thumbnails)
  • A modern browser for the web player (any browser with Canvas + WebSocket support)

1. Clone the repository

bash
git clone https://github.com/YusufB5/ASCILINE.git
cd ASCILINE

2. Install dependencies

ASCILINE's dependencies are defined in pyproject.toml. Install the base package with:

bash
pip install .

Or, if you prefer the plain requirements file:

bash
pip install fastapi uvicorn opencv-python numpy websockets

Running headless (server / no display, e.g. a VPS or container)? opencv-python-headless is a lighter drop-in replacement for opencv-python and avoids pulling in GUI dependencies you won't use.

Optional — play from YouTube (and other yt-dlp sites):

bash
pip install ".[ytdlp]"

This installs the ytdlp extra defined in pyproject.toml, pulling in yt-dlp for URL streaming. Only needed if you pass a URL instead of a local file — local playback works without it. URL playback also uses FFmpeg (see below) to normalize downloads.

FFmpeg & FFprobe (required for audio and thumbnails)

Package manager (recommended):

  • Windows: winget install ffmpeg
  • macOS: brew install ffmpeg
  • Linux: sudo apt install ffmpeg

Manual (Windows): if you hit a FileNotFoundError o

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Python

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言