English ·
Deutsch
A terminal music player with retro charm — built with Python and Textual.
Pixel-perfect cover rendering via TGP / Sixel — in the terminal.
BeBox theme — folder browser, file table, lyrics, spectral visualizer
![]() |
![]() |
| Classic Terminal — phosphor green | Boing — blue/orange |
![]() |
![]() |
| Brotkasten — YouTube links | Lyrics — original (English) |
No dependencies needed — no Python, no Git.
Linux / macOS:
curl -fsSL https://github.com/michaelblaess/retro-amp/releases/latest/download/install.sh | bashWindows (PowerShell as Administrator):
irm https://github.com/michaelblaess/retro-amp/releases/latest/download/install.ps1 | iex| Platform | Path |
|---|---|
| Linux | ~/.local/bin/retro-amp |
| macOS | /usr/local/bin/retro-amp |
| Windows | C:\Program Files\retro-amp\retro-amp.exe |
For M4A/AAC playback, ffmpeg is required. Without ffmpeg, all other formats play normally — only M4A/AAC is skipped (with a log message).
# Windows
choco install ffmpeg # or: scoop install ffmpeg / winget install ffmpeg
# Linux
sudo apt install ffmpeg
# macOS
brew install ffmpegpip install git+https://github.com/michaelblaess/retro-amp.git
retro-ampgit clone https://github.com/michaelblaess/retro-amp.git
cd retro-amp
python -m venv .venv
.venv/Scripts/activate # Windows
# source .venv/bin/activate # Linux/macOS
pip install -e ".[dev]"
retro-ampretro-amp # Start with default music folder
retro-amp /path/to/music # Start in a specific folder
retro-amp song.mp3 # Play a file directly
retro-amp --lang en # Start with English UI
retro-amp --version # Show version- Folder browser — Left panel with directory tree, automatically filters audio files
- Favorites view — All favorites as a tree, toggle with TAB
- Playlist view — Playlists as a tree, play or remove songs directly
- File table — Right panel with name, format, bitrate, duration (via mutagen)
- Audio playback — MP3, M4A/AAC, OGG/Opus, FLAC, WAV, MOD/XM/S3M, SID (via pygame.mixer + pyogg + ffmpeg)
- Spectral visualizer — Real FFT analysis, 5 display modes (Bars, Blocks, Scope, Matrix, LCD VU meter in cassette-deck style), theme-aware colors. Switch mode by right-clicking the visualizer or configure it in the "Visualizer" settings tab.
- Synced lyrics — Time-stamped lyrics from lrclib.net, color-synced (played/current/upcoming), click-to-seek on any line, auto-scroll with a 3s timeout after manual scrolling
- Liner notes — Wikipedia info on the current artist (key I), cached automatically
- Album cover art — Embedded covers from audio tags (ID3, FLAC, MP4) or image files in the folder (cover.jpg, folder.jpg, etc.), rendered as Unicode half-blocks via Pillow
- Global search with history — Search files across the whole library; clicking the search field shows the last 20 queries, typing filters matching entries and highlights hits (persisted in SQLite). Hits appear in the "Search" tab on the left as a tree, grouped by parent directory — when several hits share the same album folder, the path is shown only once.
- Playlists — Stored as Markdown files, default playlist "Favorites"
- Shuffle & repeat — Shuffle mode (X) and Repeat Off/All/One (R), combinable
- 31 retro themes — vintage 8-bit, terminal, Unix workstation, watch, comic-pulp and 80s-pastel palettes (see textual-themes)
- Multilingual — German (default) and English, switchable via
--lang - Session recovery — After a crash, the last track and folder are restored (without auto-play)
- Crash guard — An unexpected error opens a dialog with a copyable error report instead of crashing the app — you decide whether to continue or quit
- Debug log — Detailed log with artist/title, paths, events (key L). Right-click the log panel for a context menu — copy, export to a text file, or hide it. A splitter above the panel resizes it
- File management — Rename (U) and delete (DEL) directly from the player
- Settings persistence — Volume, last folder, theme and language are saved
- Resizable panels — The mouse can freely adjust the size between the file browser on the left and the file table/lyrics on the right (vertical splitter), as well as between file table and lyrics (horizontal splitter). The layout is persisted in settings.
- File association — Double-click an audio file to open retro-amp directly
- Single instance — A second double-click sends the track to the running instance
- Terminal tab title — The terminal tab shows the playing track; set before Textual starts and updated live during playback
| Key | Action |
|---|---|
Space |
Play / Pause |
+ - |
Volume |
TAB |
Cycle view: Files → Favorites → Playlists → History |
↑ ↓ |
Navigate list |
Enter |
Play track / Open folder |
F |
Toggle favorite |
P |
Playlist menu |
U |
Rename file |
DEL |
Delete file |
T |
Cycle theme |
S |
Settings |
I |
Info / About |
L |
Toggle debug log |
C |
Copy debug log |
X |
Toggle shuffle |
R |
Repeat: Off → All → One |
Q |
Quit |
Next/previous track, seeking (5 s) and global search are available via the control bar and search field (mouse).
retro-amp can be registered as the default player for audio files.
Windows (PowerShell):
powershell -ExecutionPolicy Bypass -File register-file-types.ps1Windows (CMD):
register-file-types.batLinux:
./register-file-types.shDouble-click an audio file to start retro-amp. If it is already running, the new track is sent to the existing instance (single-instance).
Press T to cycle through themes, or use the theme picker (Ctrl+P → "theme").
retro-amp registers all themes from the textual-themes package (31 themes — dark + light, from 8-bit through terminal phosphor to 80s-pastel and comic-pulp). The full gallery with a live carousel: michaelblaess.github.io/textual-themes.
Migrating from older versions: retro-amp 0.16+ migrates stored theme slugs automatically on load — anyone who previously had e.g.
c64as their favorite theme ends up on the renamedbrotkastenwithout doing anything.
- Real FFT-based analysis (stdlib
cmath, no numpy) - 2048-point FFT with Hann window
- 32 log-scaled frequency bands (20 Hz – 18 kHz)
- Spectral colors: red (bass) → yellow → green → cyan → blue (treble)
- Peak-hold with a falling effect
- 3-row multi-row display (24 height levels)
- PCM loading in a background thread
Playlists are stored as Markdown files in ~/.retro-amp/playlists/:
# Favoriten
- D:\Dropbox\MUSIK\Kraftwerk\autobahn.mp3
- D:\Dropbox\MUSIK\C64\last_ninja.sidF— Add/remove a song to favoritesP— Playlist menu: create a new one, load an existing one, add a song
Clean architecture with a strict dependency rule:
src/retro_amp/
├── domain/ # Models, protocols — no external imports
│ ├── models.py # AudioTrack, PlayerState, Playlist
│ └── protocols.py # AudioPlayer, MetadataReader, PlaylistRepository
├── services/ # Business logic — imports domain/ only
│ ├── player_service.py
│ ├── playlist_service.py
│ └── metadata_service.py
├── infrastructure/ # Implementations — pygame, mutagen, JSON
│ ├── audio_player.py # PygameAudioPlayer
│ ├── spectrum.py # SpectrumAnalyzer (FFT)
│ ├── metadata_reader.py # MutagenMetadataReader + cover-art extraction
│ ├── playlist_store.py # MarkdownPlaylistStore
│ ├── settings.py # JsonSettingsStore
│ ├── session.py # Crash recovery (session.json)
│ └── single_instance.py # Single-instance lock + play request
├── widgets/ # Textual widgets
├── screens/ # Textual ModalScreens
├── i18n.py # Internationalization (de/en)
├── locale/ # JSON language packs (de.json, en.json)
├── themes.py # Re-export from textual-themes
└── app.py # Composition root
# Setup
git clone https://github.com/michaelblaess/retro-amp.git
cd retro-amp
python -m venv .venv
.venv/Scripts/activate # Windows
pip install -e ".[dev]"
# Tests
pytest
# Type check
mypy src/Two ways to build a self-contained binary that runs without a Python install:
PyInstaller — bundles the CPython interpreter, quick to set up:
pip install pyinstaller
pyinstaller retro-amp.spec --noconfirmNuitka — compiles to a native binary (faster cold start, one distributable
archive). One script per OS; each runs uv sync first and writes to dist/:
.\compile-win64.ps1 # Windows -> dist/retro-amp-vX.Y.Z-win64.zip
./compile-linux.sh # Linux -> dist/retro-amp-vX.Y.Z-linux-x86_64.tar.gz
./compile-macos.sh # macOS -> dist/retro-amp-vX.Y.Z-macos-<arch>.tar.gzNuitka needs nuitka in the venv (uv pip install nuitka) and a C compiler —
Windows: MSVC; Linux: gcc patchelf python3-dev; macOS: Xcode Command Line Tools.
Nuitka does not cross-compile — build each OS on that OS.
git tag v0.4.0
git push origin v0.4.0
# GitHub Actions automatically builds the Windows/macOS/Linux installers| Component | Library |
|---|---|
| TUI framework | Textual >= 8.2.6 |
| Rich text | Rich >= 13.0 |
| Audio playback | pygame.mixer >= 2.5 |
| Audio metadata | mutagen >= 1.47 |
| Album cover art | Pillow >= 10.0 |
| Cover rendering (TGP/Sixel) | textual-image >= 0.12 |
| Themes | textual-themes >= 0.8 |
| UI widgets (about dialog, crash guard, search history, context menu, splitter) | textual-widgets >= 0.10 |
| Lyrics API | lrclib.net (synced + plain) |
| Testing | pytest, pytest-asyncio, pytest-cov |
| Type checking | mypy (strict) |
Synced lyrics, album art rendering, and session recovery were inspired by ytm-player — a YouTube Music player built with Textual.
Multiple visualizer modes and the "player-first, keyboard-driven" UX approach were inspired by cliamp (cliamp.stream) by @bjarneo — a Winamp-inspired terminal player written in Go.
Pixel-perfect cover rendering via TGP (Kitty protocol) and Sixel is powered by the wonderful textual-image library by @lnqs — many thanks!
Apache License 2.0 — see LICENSE.
Michael Blaess — GitHub



