ASCILINE/README.md
taisrisk 318e6daab4 Update README to include recorded preview videos
Recorded and included `.webm` examples of the high performance 1440p, HDR mode, and Pixel mode streams
then updated the markdown previews table to use these generated examples.
2026-06-15 16:20:20 +00:00

12 KiB
Raw Blame History

🌌 ASCILINE Engine (Upgraded Fork)

Note: This is an upgraded fork of the original ASCILINE project, adding high FPS support (60/120fps), low-latency live streaming, 1440p resolution presets, and an experimental 32M Ultra HDR rendering mode. If you love the core engine, please support the original creator.

ASCILINE is a high-performance, cross-platform real-time ASCII video rendering engine. Our core objective is to transform the web into a highly dynamic and interactive typographic canvas. By mapping pixels to text-based representations, we unlock new possibilities for web media delivery.

Output Details
HDR Mode 6 HDR 32M Color Mode
Experimental display-p3 colorspace with high-density output.
Pixel Mode PIXEL Mode
Showcases rendered using Mode 5 (16m Colors) combined with the --pixel flag for ultra-high fidelity.
1440p Resolution 1440p Ultra High Resolution
Showcases the new --res 1440p preset pushing ASCILINE to the limits of text rendering density.

🎯 Strategic Vision & Core Capabilities

  1. Pure Typographic Manipulation: The visual stream is not a standard media file—it's raw HTML/Canvas text. This makes the impossible possible: you can apply real-time CSS filters (neon glows, text shadows, animations) to video content.
  2. Local AI & LLM Ready: By reducing complex pixel streams into structured logical strings, ASCILINE acts as a perfect bridge for AI. Instead of feeding heavy computer vision models, lightweight LLMs can process semantic video summaries.
  3. Ultra-Low Bandwidth & Zero GPU (valid for ASCII MOD): Standard codecs (H.264/VP9) require dedicated hardware decoders, choking microcontrollers and weak devices. ASCILINE offloads the heavy lifting to the backend, streaming only lightweight text frames. By scaling down the output quality (using fewer columns), extremely low bandwidth requirements can be achieved. This means you can play fluid, real-time video on devices with constrained networks and zero GPU capabilities (smart appliances, retro terminals, basic microcontrollers).
  4. Bypassing Browser Constraints: Modern browsers aggressively throttle autoplay videos, and ad-blockers restrict traditional media frames. To the browser, ASCILINE is simply "JavaScript updating a canvas"—completely invisible to media restrictions.

🚀 Technical Features

  • Cross-Platform: Runs seamlessly on Windows, macOS, and Linux.
  • Real-Time ASCII Streaming: Ultra low-latency video-to-ASCII conversion, fully compatible with live RTMP/HTTP streams.
  • Real-Time Pixel Streaming: Replaces characters with colored blocks, approaching true HD video quality with high resolutions.
  • High Performance: Uses HTML5 Canvas for rendering. Supports high-framerate playback (60 FPS, 120 FPS) with the new --max-fps flag!
  • Master Clock Sync: The audio track acts as the absolute master clock, guaranteeing perfect A/V synchronization.
  • *Low-Overhead Binary Protocol: Frames are streamed as raw binary (Uint8Array) directly to the canvas, saving bandwidth and CPU.
  • Multiple Color Modes: Supports everything from classic B&W to 16M color ultra-fidelity.
  • Flexible Video Management: Supports JSON playlists (per-video mode & volume), folder-based auto-queuing (filesystem order), single-file mode, and infinite loop playback — all controlled via CLI arguments.

🛠️ Architecture

  1. Backend (Python/FastAPI): Decodes video using OpenCV, maps pixels to ASCII characters via NumPy, and streams binary data.
  2. Frontend (Vanilla JS): Receives binary frames via WebSockets, manages a jitter buffer, and renders to a Canvas grid.
  3. Communication: Optimized WebSocket protocol with a custom INIT handshake for dynamic resolution/FPS adjustment.

🗜️ Adaptive Frame Codec (opt-in, backward compatible)

The original binary protocol re-sends the full grid every frame. An opt-in adaptive codec picks the smallest of three encodings per frame and tags it in 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

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. The decoder (codec.js) is shared by the browser and the test suite, so the shipped path is the tested one.

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

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

An optional --quality {lossless,high,balanced,low} enables lossy temporal delta: a colour 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 ~1530% at imperceptible quality. Default is lossless (bit-exact).

Monitor Bandwidth in Real-Time: You can append the --debug flag when launching the server to see live bandwidth comparisons (RAW vs WIRE bytes) and the exact compression ratio in your terminal. This is highly useful for measuring the real-time savings of the adaptive codec on your specific video sources.

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

LAN / Network Streaming: To stream the video on your local network (Wi-Fi), use the --host flag:

python stream_server.py video.mp4 --host 0.0.0.0

📦 Installation

1. Clone the repository

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

2. Install dependencies

pip install fastapi uvicorn opencv-python numpy websockets

🔈 Audio Support (FFmpeg Required)

To enable server-side audio processing (Volume 1-5), you must have FFmpeg installed.

Option 1: Package Manager (Recommended)

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

Option 2: Manual Installation (Windows) If you get a FileNotFoundError or don't want to modify system variables:

  1. Download FFmpeg ZIP.
  2. Extract ffmpeg.exe from the bin folder.
  3. Drop it directly into your ASCILINE project folder alongside stream_server.py.

3. Run the Web Server

Single video:

python stream_server.py video.mp4 --cols 240

Folder mode — drop your videos into videos/ and run:

python stream_server.py --folder videos --cols 200
python stream_server.py --folder videos --cols 230 --loop          # infinite loop
python stream_server.py --folder videos --mode 5 --pixel --cols 320 --vol 2  # all videos same settings

Videos play in filesystem order (top to bottom as they appear in the folder, not alphabetically). Just add/remove files from the videos/ folder to control the queue.

JSON Playlist — full control per video:

python stream_server.py --playlist playlist.json --cols 220
python stream_server.py --playlist playlist.json --cols 220 --loop

Use playlist.json when you need different --mode or --vol settings for each video.

Open http://localhost:8000 in your browser.

4. Run directly in Terminal (Standalone)

If you prefer to bypass the web interface, you can render the video directly inside an ANSI-supported terminal (zero-flicker, true color):

python ascii_video_player2.py video.mp4 --cols 100 --quality 0

⚠️ Note: Do not resize your terminal window during playback, as dynamic text wrapping will corrupt the ASCII layout.

🎨 Customization

You can easily customize the look and feel of the engine:

Styling

Edit style.css to change the accent colors and typography using CSS variables:

:root {
    --accent-color: #00ff41; /* Classic Matrix Green */
    --bg-color: #050505;
}

Rendering Modes

The engine supports different fidelity levels via the --mode flag:

  • 1: Black & White (DOM mode)
  • 2: 512 Colors
  • 3: 32K Colors
  • 4: 262K Colors
  • 5: 16M Colors (Ultra)
  • 6: 32M Colors (Experimental HDR display-p3)
python stream_server.py --mode 6 --res 1080p

📐 Resolution & Auto-Scaling

You can easily control the output quality by using the --res flag, which provides convenient presets that automatically set the optimal width for higher quality/density output:

  • --res 480p (Maps to 854 columns)
  • --res 720p (Maps to 1280 columns)
  • --res 1080p (Maps to 1920 columns)
  • --res 1440p (Maps to 2560 columns)

Alternatively, you can manually specify the width (--cols). ASCILINE will automatically calculate the correct --rows based on the source video's aspect ratio to prevent stretching.

  • ASCII Mode Recommended: --cols 200 to --cols 240 (Best balance of text detail and cinematic 30 FPS performance).
  • Pixel Mode Recommended: --cols 600 to --cols 900 (Provides near-HD visual quality. Performance heavily depends on your machine's CPU/VRAM).
  • Smart Defaults: If you do not specify --res or --cols, ASCILINE automatically defaults to 450 when Pixel Mode is enabled, and 200 for standard ASCII text mode.

  • ⚠️ Hardware Limits & A/V Sync: Higher resolutions (like 720p or 1080p) will output incredibly dense and highly detailed ASCII art and pixels, but they require a very fast CPU to process frames in real-time. If you push the resolution too high for your specific hardware (e.g., --res 1080p on a standard laptop), the Python backend won't be able to encode and send the massive frames fast enough. When the video stream lags behind the audio, you will experience A/V desync (audio finishing early). If this happens, simply select a lower resolution or lower your --cols value!

python stream_server.py video.mp4 --mode 5 --res 720p
# OR manually specify width
python stream_server.py video.mp4 --mode 5 --cols 240
# Terminal will show: [AUTO] 1920x1080 → grid 240x67

Server-Side Volume Control

Volume is controlled at the server level via the --vol flag (scale 05). When set to 0, the audio engine (FFmpeg) never runs, saving CPU and bandwidth.

--vol FFmpeg Multiplier Description
0 Muted (no processing)
1 1.0× Normal (default)
3 1.5× Loud
5 2.0× Double volume
python stream_server.py video.mp4 --pixel --cols 560 --vol 0   # Silent
python stream_server.py video.mp4 --cols 220 --vol 3   # Loud

Playlist Format (playlist.json)

Each entry can override the global --mode, --pixel, --vol, --cols, and --res defaults:

[
    { "video": "intro.mp4",  "mode": 1, "vol": 1 },
    { "video": "main.mp4",   "mode": 5, "pixel": true, "vol": 3, "res": "720p" },
    { "video": "outro.mp4",  "mode": 3, "vol": 2, "cols": 240 }
]

Video paths are resolved automatically — the engine checks the project root and the videos/ subfolder, so you can write just the filename.

🙏 Support the Original Creator

As mentioned, this is an upgraded fork designed for modern, high-performance web applications (HDR, 1440p, 120 FPS, low latency).

All credit for the core engine architecture and adaptive streaming codec goes to the original creator. If you find this project helpful, please support the original author by visiting their repository, starring their project, and supporting them directly:

👉 Original ASCILINE Repository (YusufB5)

📜 License & Ethical Guardrails

ASCILINE is distributed under the MIT License, but with an anti ad strict ethical guardrail.

See the LICENSE file for the full text, which includes the ANTI-ADVERTISEMENT RESTRICTION clause.