Skip to main content

textrun

Generalized Wayland-compatible text reader with OCR and TTS. Captures screen content via screenshots, extracts text with OCR, and reads it aloud.

Repository: Codeberg (main) · GitHub (mirror)

Created in heavy cooperation with AI

Features

  • OCR from screen capture any region or full screen, extract text
  • Auto-scroll scrolls and re-captures until no new content appears
  • Text stitching deduplicates overlapping OCR frames into clean text
  • TTS output reads extracted text aloud via system TTS or command fallback
  • Live reading text is spoken while still capturing (tts.live), streaming or chunked
  • Configurable backends every step (screenshot, scroll, OCR, TTS, audio) is swappable
  • Global shortcuts start and stop captures system-wide while the GUI or --shortcuts daemon runs (capture_shortcut, capture_shortcut_stop; Wayland global-shortcuts portal or pynput on X11/Win/Mac)
  • Mixed-DPI aware pixel-accurate captures across monitors with different scales
  • Chain fallback if a backend fails, the next in chain is tried automatically
  • Profiles per-app settings (Firefox, games, terminals) with inheritance from global
  • GUI PySide6 config manager with region picker, profile editor, backend reorder
  • Wayland support dotool/ydotool for scroll, grim for screenshots, speech-dispatcher for TTS

Installation

Recommended: uv

uv is the fastest way to install Python tools.

# Install textrun for your platform
uv tool install 'textrun[wayland]'    # Wayland (Sway, Hyprland, GNOME, KDE)
uv tool install 'textrun[x11]'        # X11
uv tool install 'textrun[mac-win]'    # Windows / macOS

The GUI (PySide6) is a core dependency and always included.

From a local clone

Instead of PyPI you can install straight from a checkout:

git clone https://codeberg.org/marvin1099/textrun
cd textrun

# Same as above, but pointing at the cloned repo (.):
uv tool install --with 'textrun[wayland]' .
uv tool install --with 'textrun[x11]' .
uv tool install --with 'textrun[mac-win]' .

Alternative: pipx

pipx installs Python CLI tools in isolated environments.

# Install textrun for your platform
pipx install "textrun[wayland]"
pipx install "textrun[x11]"
pipx install "textrun[mac-win]"

Last resort: pip

pip install --user "textrun[wayland]"
pip install --user "textrun[x11]"
pip install --user "textrun[mac-win]"

Make sure ~/.local/bin is in your PATH.

Usage

# Basic usage (global profile)
textrun

# Use a specific profile
textrun -p wayland
textrun -p firefox
textrun -p game-terminal

# Capture a specific region
textrun -p wayland --region 100,200,800,600

# Save text to file
textrun -p firefox -o output.txt

# Disable TTS
textrun --no-tts

# Override settings
textrun --scroll-amount 5 --max-scrolls 100

# List available profiles
textrun --list-profiles

# Launch the GUI
textrun --gui
textrun -p wayland --gui

# Daemon-like: wait for global shortcuts only, no window
textrun --shortcuts

# Verbose logging
textrun -v -p wayland

Desktop entry

textrun --install-desktop installs a menu entry, so textrun can also be used from the app launcher without a terminal: launching it opens the GUI, and a secondary "Shortcuts daemon" action starts --shortcuts.

Configuration

Config file: ~/.config/textrun/config.toml

Backend types

Every backend in the config has a type field:

Type Description Example
command Runs an external program via subprocess grim, dotool, piper
library Calls a Python library function directly pytesseract, rapidocr
adapter Calls a textrun adapter for stateful libraries speechd, pyttsx3

Config example

# Global defaults (inherited by all profiles)
[global]
scroll_amount = 3
scroll_delay = 1.0
max_scroll_attempts = 50
language = "eng"
tts_enabled = true
tts_volume = 100               # percent; {tts_volume}/{tts_volume_pa} placeholders

# Screenshot backend chain
[global.screenshot]
chain = ["pyscreenshot", "grim", "spectacle"]

[global.screenshot.backends.grim]
type = "command"
program = "grim"
args = ["{output_path}"]

# Scroll backend chain
[global.scroll]
chain = ["pyautogui", "xdotool", "dotool", "ydotool"]

[global.scroll.backends.dotool]
type = "command"
program = "dotoolc"
args = []
stdin = "wheel -{scroll_amount}"

# OCR backend chain
[global.ocr]
chain = ["tesseract", "rapidocr"]

[global.ocr.backends.tesseract]
type = "library"
library = "pytesseract"
function = "image_to_string"
args = { image = "{image_path}", lang = "{language}" }

# TTS backend chain
[global.tts]
chain = ["speechd", "pyttsx3", "piper", "espeak-ng"]

[global.tts.backends.speechd]
type = "adapter"
adapter = "textrun.adapters"
function = "speechd_say"

Placeholders

Placeholders like {key} are resolved from the runtime context:

Placeholder Source
{scroll_amount} config scroll_amount
{output_path} generated per run
{image_path} generated per run
{text} OCR output
{audio_path} generated per run
{language} config language
{region_str} formatted region

Commands

Command backends support these fields:

[backends.my-command]
type = "command"
program = "dotoolc"           # binary name, resolved via PATH
args = ["arg1", "{var}"]     # list, placeholders resolved
stdin = "text {var}"         # string template: piped to stdin
env = { KEY = "val" }        # extra environment variables
stdout = true                # capture stdout
stderr = true                # capture stderr

stdin accepts a string template (recommended, e.g. "{text}" for TTS) or true (pipes the internal stdin_text context key). Stream backends (type = "stream") are fed incrementally by the live reader and don't use stdin.

Profiles

Profiles inherit from global by default. Override only what differs.

Built-in profiles

Profile Description
global Base defaults for all settings
wayland dotool scroll, grim screenshots
firefox Larger scroll amount, slower delay
game-terminal Arrow key scroll, no TTS, fast timing

Profile example

[profiles.firefox]
inherits = "global"
scroll_amount = 5
scroll_delay = 1.5

[profiles.firefox.scroll]
chain = ["dotool"]

Region in profiles

Set a capture region per profile:

[profiles.firefox]
inherits = "global"
scroll_amount = 5

[profiles.firefox.region]
x = 100
y = 200
width = 800
height = 600

The GUI also saves two companion keys for pixel-accurate captures:

[profiles.firefox.screen_size]
width = 2560
height = 1440

[[profiles.firefox.monitors]]
x = 0
y = 0
width = 2560
height = 1440
scale = 1.5

region uses logical desktop coordinates; monitors records each monitor's layout and scale so crops stay correct on mixed-DPI setups. Both are written by the GUI region picker, set them by hand only if you must.

GUI

Ships with PySide6 as a core dependency, no extra install needed.

textrun --gui

Features:

  • Profile selector switch between profiles
  • Region picker click and drag to select capture area
  • Backend reorder drag and drop to change fallback order
  • Start/Stop buttons + global shortcuts capture without touching the CLI
  • Copy command copies textrun -p <profile> to clipboard
  • Save config writes settings to ~/.config/textrun/config.toml

Headless variant: textrun --shortcuts registers the global shortcuts (capture_shortcut, capture_shortcut_stop) and waits without showing a window; captures run with the selected profile's saved config.

Tip: run textrun --install-desktop once. The Wayland global-shortcuts portal attributes shortcuts to the launching app, started from a terminal they appear under e.g. "Konsole"; with the desktop entry installed and textrun launched from the app menu, they register under "textrun" with its own icon.

Backend defaults

Screenshot

Order Backend Type Notes
1 pyscreenshot adapter Auto-detects Wayland/X11
2 grim command Wayland native (wlroots)
3 spectacle command KDE native

Scroll

Order Backend Type Notes
1 pyautogui adapter X11, may prompt on Wayland
2 xdotool command X11 only
3 dotool command Wayland, needs /dev/uinput
4 ydotool command Wayland, needs ydotoold

Wayland profile order: dotool → ydotool → pyautogui → xdotool

OCR

Order Backend Type Notes
1 tesseract library Fast, good for clean text
2 rapidocr library Better accuracy, heavier

TTS

Order Backend Type Notes
1 speechd adapter Linux system standard
2 pyttsx3 adapter Cross-platform (Win/Mac/Linux)
3 piper command Neural quality, needs model
4 espeak-ng command Robotic, always available

Audio playback

Order Backend Type Notes
1 playsound3 adapter Cross-platform via GStreamer (no volume support)
2 mpv command Plays anything, honors tts_volume
3 ffplay command Fallback, honors tts_volume

Volume

tts_volume (percent, default 100) is set in [global] and inherited by profiles. It reaches backends as template placeholders:

  • {tts_volume} percent, for ffplay (-volume) and mpv (--volume=)
  • {tts_volume_pa} linear 0–65536, for paplay (--volume=) and pactl

The piper-stream player and the mpv/ffplay audio backends use these by default. Native TTS engines (speechd, pyttsx3) and playsound3 ignore it.

Live reading

With tts.live = true in [global.tts], text starts playing while capture is still running instead of after the last frame:

[global.tts]
live = true             # read incrementally during capture
live_queue_chunks = true  # see below
  • Streaming TTS (piper-stream): synthesis and playback run as a continuous pipeline words come out as lines are confirmed stable.
  • Chunked TTS (all other backends): confirmed text is queued and spoken chunk-by-chunk; live_queue_chunks controls whether chunks are pre-synthesized ahead of playback.

The stitcher holds back the last two lines until later frames confirm them; when capture ends they are flushed and read too. The stop shortcut cuts off reading immediately. If live playback never produced audio, textrun falls back to one batch read at the end.

Optional dependencies

Platform bundles include everything needed for that platform:

uv pip install "textrun[wayland]"     # OCR + screenshots for Wayland
uv pip install "textrun[x11]"         # OCR + pyautogui for X11
uv pip install "textrun[mac-win]"     # OCR + pyttsx3 for Windows/macOS
uv pip install "textrun[all]"         # Everything

Or install individual extras:

uv pip install "textrun[ocr-tesseract]"     # Tesseract OCR
uv pip install "textrun[ocr-rapid]"         # RapidOCR
uv pip install "textrun[scroll-pyautogui]"  # pyautogui scroll
uv pip install "textrun[tts-pyttsx3]"       # pyttsx3 TTS
uv pip install "textrun[screenshots-pyscreenshot]"  # pyscreenshot

PySide6 (GUI), Pillow, imagehash and playsound3 are core dependencies and always installed.

Download files

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

Source Distribution

textrun-0.1.1.tar.gz (72.3 kB view details)

Uploaded Source

Built Distribution

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

textrun-0.1.1-py3-none-any.whl (65.7 kB view details)

Uploaded Python 3

File details

Details for the file textrun-0.1.1.tar.gz.

File metadata

  • Download URL: textrun-0.1.1.tar.gz
  • Upload date:
  • Size: 72.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textrun-0.1.1.tar.gz
Algorithm Hash digest
SHA256 1b0a4434ff2a9483fe3a0315e4c59731449a005f0038eeb2c47e4d35a0e442a6
MD5 382fbd7284bec8b14e43fcb34d3e7a28
BLAKE2b-256 da9e5a8fd32af5424ff55600066b7474702193a10bd1fd0566ddbe7bc047f658

See more details on using hashes here.

File details

Details for the file textrun-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: textrun-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 65.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textrun-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 caa28aa260176c073c9cadb0699130e429fdeca5f7d74da7c2cd308358a1009f
MD5 b942c269b57107252a9a64620e63fb87
BLAKE2b-256 aae739aec8d5dff6cbdb8ce6b47e86f8db48b44d060b6bba75ef4373bef383df

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page