Skip to main content

Terminal media engine with pixel-accurate rendering at 60fps

Project description

termflux

Terminal Media Engine — Pixel-Perfect Rendering at 60fps

Render images, play videos, and stream audio entirely inside your terminal. Native C engine with Sixel graphics, Lanczos3 interpolation, and quarter-block Unicode for HD output on any platform.

Author  : MERO:TG@QP4RM
Version : 1.0.0
License : Proprietary (see LICENSE)

Overview

termflux is a Python library backed by a C rendering engine. It decodes media with FFmpeg and draws pixels directly into the terminal — no GUI, no browser, no external windows.

Three render modes:

Mode Resolution Method Terminal Support
Sixel Up to 1920x1080 real pixels Sixel bitmap protocol mlterm, foot, WezTerm, iTerm2
Quarter-Block 2x columns, 2x rows 16 Unicode block patterns All terminals
Half-Block columns, 2x rows Upper/lower half blocks All terminals

Core capabilities:

  • Image display with 24-bit true color
  • Video playback at native framerate (up to 60fps)
  • Audio playback with built-in terminal visualizer (waveform, progress, metadata)
  • URL loading — pass a link, termflux downloads and renders
  • Color filters: brightness, contrast, saturation, grayscale, invert
  • 5 border styles with custom RGB colors, thickness 1-5, configurable padding
  • 9 screen positions (center, top, bottom, left, right, corners)
  • 3 aspect ratio modes (fit, fill, stretch)
  • Cross-platform: Linux, Windows 10+, macOS, Android (Termux / Pydroid / QPython)
  • Pure Python fallback when no C compiler is available

Installation

pip install termflux

Dependencies

  • Python >= 3.8
  • FFmpeg (video/image decoding and audio playback)
# Debian / Ubuntu
sudo apt install ffmpeg

# macOS
brew install ffmpeg

# Windows
# Download from https://ffmpeg.org/download.html and add to PATH

# Android Termux
pkg install python ffmpeg

From Source

git clone https://github.com/6x-u/termflux.git
cd termflux
pip install -e .

The C extensions (_engine and _decoder) build automatically. If compilation fails (e.g., no FFmpeg dev headers), the library falls back to pure Python.


Quick Start

Display an Image

import termflux

img = termflux.Image("photo.jpg")
img.show(
    border_style=termflux.BORDER_ROUND,
    border_r=255, border_g=215, border_b=0,
    render_mode=termflux.RENDER_QUARTER,
)
input()
termflux.reset()

Play a Video

import termflux

vid = termflux.Video("video.mp4")
vid.play(
    render_mode=termflux.RENDER_QUARTER,
    with_audio=True,
    brightness=1.05,
    saturation=1.15,
)

Play Audio (Terminal UI)

import termflux

audio = termflux.Audio("track.mp3")
audio.play()

Displays a full terminal UI with waveform visualization, progress bar, elapsed time, codec info, and playback status.

Load from URL

import termflux

img = termflux.Image("https://example.com/photo.jpg")
img.show()

vid = termflux.Video("https://example.com/clip.mp4")
vid.play(with_audio=True)

CLI

# Basic image display
termflux photo.jpg

# Gold round border
termflux photo.jpg -b round --border-color 255,215,0

# Video with audio
termflux video.mp4

# Sixel mode (pixel-perfect on supported terminals)
termflux photo.jpg -r sixel

# Grayscale with thick double border
termflux photo.jpg --grayscale -b double --border-thick 3

# High contrast vivid video
termflux video.mp4 --contrast 1.4 --saturation 1.6 --brightness 1.1

# Audio playback
termflux song.mp3 -t audio

# Custom position and size
termflux photo.jpg -p top-left -W 60 -H 30 -b single

# Inverted colors with padding
termflux photo.jpg --invert --padding 2 -b round

# Stretch to fill
termflux photo.jpg --aspect stretch

# Loop video
termflux video.mp4 -l

CLI Options

Option Short Default Description
source required File path or URL
--type -t auto Force type: image, video, audio
--width -W auto Width in columns
--height -H auto Height in rows
--position -p center center, top, bottom, left, right, top-left, top-right, bottom-left, bottom-right
--border -b none none, single, double, bold, round
--border-color 255,255,255 RGB values comma-separated
--border-thick 1 Border thickness (1-5)
--padding 0 Padding inside border
--render -r quarter sixel, quarter, half
--aspect fit fit, fill, stretch
--brightness 1.0 0.0 - 3.0
--contrast 1.0 0.0 - 3.0
--saturation 1.0 0.0 - 3.0
--grayscale false Convert to grayscale
--invert false Invert colors
--loop -l false Loop video

Python API

termflux.Image

img = termflux.Image(source)          # file path or URL

img.width                              # source width in pixels
img.height                             # source height in pixels
img.pixels                             # raw RGB bytes (width * height * 3)

img.show(
    border_style=termflux.BORDER_NONE, # BORDER_NONE / SINGLE / DOUBLE / BOLD / ROUND
    border_r=255, border_g=255, border_b=255,
    position="center",
    width=None, height=None,           # override display size
    render_mode=termflux.RENDER_QUARTER,  # RENDER_SIXEL / RENDER_QUARTER / RENDER_HALF
    border_thick=1,
    padding=0,
    brightness=1.0,
    contrast=1.0,
    saturation=1.0,
    grayscale=False,
    invert=False,
    aspect="fit",                      # fit / fill / stretch
)

termflux.Video

vid = termflux.Video(source)

vid.width                              # frame width
vid.height                             # frame height
vid.fps                                # frames per second
vid.duration                           # duration in seconds

vid.play(
    border_style=termflux.BORDER_NONE,
    border_r=255, border_g=255, border_b=255,
    position="center",
    width=None, height=None,
    with_audio=True,                   # sync audio playback
    loop=False,
    render_mode=termflux.RENDER_QUARTER,
    border_thick=1,
    padding=0,
    brightness=1.0,
    contrast=1.0,
    saturation=1.0,
    grayscale=False,
    invert=False,
    aspect="fit",
)

termflux.Audio

audio = termflux.Audio(source)

audio.play()                           # blocking, shows terminal UI
audio.play(show_ui=False)              # blocking, no UI
audio.play_background()                # non-blocking background playback
audio.stop()
audio.is_playing                       # bool

termflux.Player (Unified)

p = termflux.Player(source, media_type=None)  # auto-detects type
p.border(termflux.BORDER_ROUND, 255, 215, 0)
p.border_thickness(2)
p.set_padding(1)
p.position("center")
p.size(width=80, height=40)
p.render_mode(termflux.RENDER_QUARTER)
p.set_aspect("fit")
p.set_brightness(1.1)
p.set_contrast(1.2)
p.set_saturation(1.3)
p.set_grayscale(False)
p.set_invert(False)
p.loop(True)
p.show()

Low-Level Functions

# Terminal control
termflux.clear_screen()
termflux.hide_cursor()
termflux.show_cursor()
termflux.reset()
cols, rows = termflux.get_terminal_size()

# Render raw RGB data to terminal escape sequences
frame = termflux.render_frame(
    pixels, width, height,
    term_width=80, term_height=24,
    offset_x=0, offset_y=0,
    border_style=termflux.BORDER_NONE,
    border_r=255, border_g=255, border_b=255,
    render_mode=termflux.RENDER_QUARTER,
    border_thick=1, padding=0,
    brightness=1.0, contrast=1.0, saturation=1.0,
    grayscale=0, invert=0,
)
termflux.flush_frame(frame)

# Scale pixel data (uses Lanczos3 for large ratios, bilinear otherwise)
scaled = termflux.scale(pixels, src_w, src_h, dst_w, dst_h)

# Precise sleep (nanosleep on POSIX, QueryPerformanceCounter on Windows)
termflux.sleep_precise(0.016)

# Windows ANSI support
termflux.enable_ansi()

Constants

# Border styles
termflux.BORDER_NONE    # 0
termflux.BORDER_SINGLE  # 1 — ┌─┐│└─┘
termflux.BORDER_DOUBLE  # 2 — ╔═╗║╚═╝
termflux.BORDER_BOLD    # 3 — ┏━┓┃┗━┛
termflux.BORDER_ROUND   # 4 — ╭─╮│╰─╯

# Render modes
termflux.RENDER_HALF    # 0 — classic half-block
termflux.RENDER_QUARTER # 1 — HD quarter-block (default)
termflux.RENDER_SIXEL   # 2 — pixel-perfect Sixel bitmap

Render Modes

Sixel (RENDER_SIXEL)

Pixel-level bitmap rendering using the Sixel protocol. Renders actual pixels — not character approximations. Supports up to 256 colors with Floyd-Steinberg dithering and RLE compression. Best quality available.

Supported terminals: mlterm 3.9+, foot, WezTerm, iTerm2 3.3+, xterm (with sixel compiled in), mintty.

Quarter-Block (RENDER_QUARTER)

Uses 16 Unicode quarter-block characters (U+2580-U+259F) to render a 2x2 pixel grid per terminal cell. Each cell maps 4 sub-pixels to 2 colors (foreground + background) using perceptual color distance. Double the horizontal resolution of half-block mode.

Scaling uses Lanczos3 interpolation for downsampling ratios > 1.2x, producing sharper output than bilinear filtering.

Half-Block (RENDER_HALF)

Classic rendering using upper-half (▀) and lower-half (▄) block characters. One cell = 2 vertical pixels. Compatible with every terminal that supports 24-bit ANSI color.


Platform Support

Platform Engine Audio Video Sixel
Linux x86_64 C native ffplay, mpv, aplay FFmpeg C API depends on terminal
Linux aarch64 C native ffplay, mpv, aplay FFmpeg C API depends on terminal
Windows x86 C native ffplay, mpv FFmpeg C API limited
Windows x64 C native ffplay, mpv FFmpeg C API limited
macOS C native ffplay, mpv, play FFmpeg C API iTerm2
Android Termux C native termux-media-player, ffplay FFmpeg C API depends on terminal
Android Pydroid Python fallback limited FFmpeg subprocess limited
Android QPython Python fallback limited FFmpeg subprocess limited

The pure Python fallback (_fallback.py) provides full rendering capabilities without requiring C compilation. It activates automatically when the C extension fails to load.


Architecture

termflux/
├── _engine.c          C rendering engine
│                      - Bilinear + Lanczos3 scaling
│                      - Half-block, quarter-block, Sixel renderers
│                      - Color filters (brightness, contrast, saturation)
│                      - Border drawing with 5 styles
│                      - Perceptual color distance
│
├── _decoder.c         C media decoder (FFmpeg API)
│                      - Video frame extraction (rgb24)
│                      - Seek support
│
├── _fallback.py       Pure Python rendering engine
│                      - Full feature parity with C engine
│                      - Works on Android without C compiler
│
├── image.py           Image display API
├── video.py           Video playback with frame timing + audio sync
├── audio.py           Audio playback with terminal UI visualizer
├── player.py          Unified Player API
├── loader.py          URL fetcher + file resolver
├── cli.py             Command-line interface
└── __init__.py        Package exports

Examples

See the examples/ directory:

Script Description
show_image.py Display image with golden round border
play_video.py Play video with pink bold border and audio
play_audio.py Play audio with terminal visualizer
color_filters.py Demonstrate brightness, contrast, saturation, grayscale, invert
border_styles.py Show all 5 border styles side by side
player_api.py Unified Player API usage
video_with_headers.py Video playback with HUD overlay (title, progress, timer)
demo.py Full feature demo script

Shell Scripts

scripts/quick_image.sh    # One-liner image display
scripts/quick_video.sh    # One-liner video playback
scripts/quick_audio.sh    # One-liner audio playback

Building Wheels

Local Build

pip install build
python -m build

Cross-Platform (CI)

The repository includes GitHub Actions workflow (.github/workflows/build.yml) that builds:

  • Linux: x86_64, aarch64 (manylinux)
  • Windows: AMD64 (x64), x86 (32-bit)
  • Source distribution: universal

Triggered on version tags (v*) or manual dispatch.

git tag v1.0.0
git push origin v1.0.0

Supported Media Formats

Images

.png .jpg .jpeg .bmp .gif .tiff .webp .ico

Video

.mp4 .avi .mkv .mov .webm .flv .wmv .m4v

Audio

.mp3 .wav .ogg .flac .aac .m4a .wma .opus

Any format supported by FFmpeg works. The above are auto-detected by file extension.


License

Proprietary. See LICENSE for terms.

  • Free to use in personal and commercial projects
  • Modification allowed
  • Must retain author attribution: MERO:TG@QP4RM
  • Must retain project name: termflux
  • Cannot remove or change copyright notices
  • Cannot redistribute as standalone library under different name/author

termflux v1.0.0
Author: MERO:TG@QP4RM
https://github.com/6x-u/termflux

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

termflux-1.0.0.tar.gz (40.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

termflux-1.0.0-py3-none-win_amd64.whl (33.4 kB view details)

Uploaded Python 3Windows x86-64

termflux-1.0.0-py3-none-win32.whl (33.4 kB view details)

Uploaded Python 3Windows x86

termflux-1.0.0-py3-none-android_21_armeabi_v7a.whl (33.4 kB view details)

Uploaded Android API level 21+ ARM EABI v7aPython 3

termflux-1.0.0-py3-none-android_21_arm64_v8a.whl (33.4 kB view details)

Uploaded Android API level 21+ ARM64 v8aPython 3

File details

Details for the file termflux-1.0.0.tar.gz.

File metadata

  • Download URL: termflux-1.0.0.tar.gz
  • Upload date:
  • Size: 40.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for termflux-1.0.0.tar.gz
Algorithm Hash digest
SHA256 4c606c4e804755c328efbed69dc4dc6d084bfbd1b64ff7352bb27f20475d3ac0
MD5 573f02b26016ab396a14a1e4c0a6b8be
BLAKE2b-256 4bf3c46d0a2944146f6f80a6b3eeae5d9f80722ca38ba953bfa6dcfc618612b2

See more details on using hashes here.

File details

Details for the file termflux-1.0.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: termflux-1.0.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for termflux-1.0.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 49226c515a952a5feaaa4d8f1c43909655a1890f3ca970ac50668ac373c917a8
MD5 bd2889ae96f1837a3091b6a12c2592b6
BLAKE2b-256 94a592711db94ea809f8f8a1313e3bb6e506ff0fcd889a1cf7814361bfb86991

See more details on using hashes here.

File details

Details for the file termflux-1.0.0-py3-none-win32.whl.

File metadata

  • Download URL: termflux-1.0.0-py3-none-win32.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for termflux-1.0.0-py3-none-win32.whl
Algorithm Hash digest
SHA256 4037eb88d20b4b741ea24dc58316b335b9ca8a08c2589476e4a50548f53bc415
MD5 f11f768239fd63c6182868a3e9795438
BLAKE2b-256 b7dd19b69bffa0823622fd0fcd3017e35897a687c081842fbd28f28b1eb42bca

See more details on using hashes here.

File details

Details for the file termflux-1.0.0-py3-none-android_21_armeabi_v7a.whl.

File metadata

File hashes

Hashes for termflux-1.0.0-py3-none-android_21_armeabi_v7a.whl
Algorithm Hash digest
SHA256 26f65c349759e166afdbc36e3828b5340283fc564069b56085b0462106458718
MD5 f9b23663e07c7d10fb563deb6e7b0dac
BLAKE2b-256 f264157cadf35a43fcec502f0297d04244f0bf7b5b663d8f461b5984a4a44941

See more details on using hashes here.

File details

Details for the file termflux-1.0.0-py3-none-android_21_arm64_v8a.whl.

File metadata

File hashes

Hashes for termflux-1.0.0-py3-none-android_21_arm64_v8a.whl
Algorithm Hash digest
SHA256 9800a082190e40fef81be4facf768261c3d0bc8b62acb5c2e35a53c54344129d
MD5 aca07f97804bafe21d24bb4c26f01af2
BLAKE2b-256 a818349a7118636a7387ebee6da84515045a4532d7b827a738a5e72f0e4782b4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page