- Emacs Lisp 56.7%
- Python 42%
- Makefile 1.2%
- Shell 0.1%
|
Some checks failed
Repository structure / structure (push) Has been cancelled
The player hand-built its canvas: a buffer keymap installed through emulation-mode-map-alists, a display table, a global window-size-change hook with its own minibuffer-borrowing check, and a teardown reachable only from q or a failed open. Killing the buffer left the status timer running forever, the area outside the canvas showed the user's background, and etaf-ascii-video-close outside a player killed whatever buffer was current. The player now opens through etaf-app-open. Its keys are root :keys of the View with the labels help already showed; the canvas surface is the player's dark background; the fit function refits the grid when the window's text area settles at a new size, so a grid from size hints, a preset or set-grid stays until then; and one close function stops the status timer however the buffer goes away. etaf-ascii-video-close signals user-error outside a player. The help palette is built with etaf-ui-theme-tokens (the eleven tokens it provided are unchanged; the rest of the modal chrome now follows the same dark palette). The mode line stays visible as before. Requires ETAF 0.3.0 and ETAF UI 0.2.0; version 0.1.1. Validation: make -C etaf-ascii-video check (12/12, API 17 verified); the new canvas-and-kill test fails on the previous tree at each of its three claims (close kills a non-player buffer, no canvas surface, a leaked timer after kill); real GUI with ffmpeg: fit 199x48 in 205x50, SPC/n/f/ b/+/-/1-4/F/c drive the player, split refits 93x22 and unsplit 199x48, a preset survives settles, ? lists all 17 labelled keys in a dark modal, q and kill-buffer return the timer count to its baseline. |
||
|---|---|---|
| .githooks | ||
| .github/workflows | ||
| docs | ||
| examples | ||
| lisp | ||
| scripts | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| CHANGELOG.md | ||
| etaf-ascii-video.el | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
ETAF ASCII Video
ETAF ASCII Video shows a local video or HTTP(S) stream inside an Emacs buffer
as pure characters, in the two character render modes of ETAF's native
etaf-video Component: a density ramp (one character per pixel) and true-color
half blocks (▀, two full-color pixels per cell). The native Component decodes
with ffmpeg and publishes every frame through
ETAF's retained content boundary, so
one displayed frame is one incremental publication of a fixed canvas Host, not
a full re-render. This application owns the buffer, the fitted canvas size,
the render mode, the status line and the keys. For the sharp, full-window
image player with sound, use the companion etaf-video-player.
A local video playing as true-color half blocks:
Capabilities
- Playback of local video files through ffmpeg; the built-in demo generates a
test pattern with ffmpeg's
lavfiinput, so no file is needed. - HTTP(S) video URLs play as streams: ffmpeg decodes them directly, nothing is downloaded first, and a dropped connection is retried for five seconds.
- Two character render modes. The default monochrome mode maps each pixel to
one density-ramp character. True-color half-block mode (
c) renders two full color pixels per character cell with▀(top pixel as foreground, bottom as background), keeping the video's colors at double the vertical resolution. - A canvas that fits the window (and follows resizes), four grid presets, and
explicit
etaf-ascii-video-set-gridfor scripts. - Play, pause, single frame stepping, seeking, and 0.5x to 8x rates.
- Latest-frame-wins display: when decoding outruns display, older frames are dropped instead of replayed as a backlog.
etaf-ascii-video-stateexposes the live player as plain data for scripts and tests.
Prerequisites
| Requirement | Why | Check |
|---|---|---|
| Emacs 29.1 or newer | the ETAF runtime | emacs --version |
etaf, etaf-ui, ebox, ecss |
the framework; each root entry must be on load-path |
every checkout is readable |
| ffmpeg | decoding and downsampling | ffmpeg -version |
| ffprobe | duration, frame rate and video size | ffprobe -version |
ffprobe is optional: without it playback uses the source defaults for
dimensions and rate and the status line shows no total duration. The decoder
programs, the density ramp and the display rate are the etaf-video-*
variables documented in ETAF's manual.
Installation
(add-to-list 'load-path "/path/to/ecss")
(add-to-list 'load-path "/path/to/ebox")
(add-to-list 'load-path "/path/to/etaf")
(add-to-list 'load-path "/path/to/etaf-ui")
(add-to-list 'load-path "/path/to/etaf-ascii-video")
(require 'etaf-ascii-video)
(global-set-key (kbd "C-c a") #'etaf-ascii-video-open-file)
Minimal example
(etaf-ascii-video-demo) ; generated test pattern, no file
(etaf-ascii-video-open-file "clip.mp4") ; a local video
(etaf-ascii-video-open-url "https://example.com/clip.mp4") ; a network stream
(etaf-ascii-video-open '(:file "clip.mp4" :columns 120 :rows 34 :speed 2))
(etaf-ascii-video-open '(:file "clip.mp4" :mode 'color)) ; half-block color
Keys
| Key | Action |
|---|---|
SPC |
play or pause |
n |
pause and present one more frame |
f / b |
seek five seconds forward or backward |
+ / - |
raise or lower the playback rate |
1 .. 4 |
grid presets (64, 96, 128, 176 columns, rows follow the aspect) |
c |
toggle true-color half-block rendering |
F |
fit the canvas to the window |
o / u / d |
open a file / open a URL / replay the built-in demo |
? / C-c h |
searchable help inside the player |
q |
close the player |
Help is read-only and uses the player's dark palette. / searches its effective
bindings; Escape leaves search editing before closing the modal. Clicking the
dimmed background also closes it without changing playback.
Checks
make check # structure + byte compilation (warnings as errors) + acceptance + API boundary
make test # the public acceptance scenarios only
The acceptance suite drives the repository's fake ffmpeg and ffprobe fixtures, so it needs no real decoder, no network and no frame; one scenario runs the real ffmpeg when one is installed.
Documentation
- The manual: playback, canvas fitting, scripting, variables and troubleshooting.
- Architecture: module responsibilities, data flow, invariants and the ownership boundary with ETAF.
- The root entry Commentary: the authoritative list of supported functions and variables.
