A lightweight TUI music player for your terminal. Play local files or search YouTube Music, all from a keyboard-first Textual interface — with a one-shot CLI for quick control.
- 📂 Local library — scan folders, read ID3/FLAC/MP4 tags, extract embedded art
- 🎵 YouTube Music — search songs and play full-length audio
(metadata:
ytmusicapi, streams:yt-dlp) - 🎚 mpv engine — gapless playback driven over JSON IPC (play/pause/seek/volume), works on Linux / macOS / Windows
- 🗒 Queue engine — shuffle, repeat, add/enqueue, session resume
- 🎨 Album art — cover art rendered in the terminal, dithered via Pillow
- ⏩ Playback effects — speed control (0.5x–2x), reverb, and pitch (tempo / nightcore) modes
- ⌨️ Keyboard-first TUI with an animated mini-EQ and progress bar
- 🚀 One-shot CLI —
enigmatic play "~/Music",enigmatic search "lofi"
- Python 3.10+
- mpv — the audio engine. On Windows it's installed automatically on first
run (official build downloaded into
%LOCALAPPDATA%\enigmatic-player\engines; same forffmpeg, needed for YouTube downloads). No requirement to install it yourself. On Linux/macOS you'll be shown the one command for your package manager (sudo apt install mpv·brew install mpv). - yt-dlp (for YouTube) — typically pulled in automatically
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/lmdelm-dev/music-player/main/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/lmdelm-dev/music-player/main/install.ps1 | iexWindows (cmd):
curl -fsSL https://raw.githubusercontent.com/lmdelm-dev/music-player/main/install.cmd | cmdThen launch with:
epm # or: enigmaticpip install "git+https://github.com/lmdelm-dev/music-player.git"Optional extras:
| Extra | Includes |
|---|---|
youtube |
ytmusicapi, yt-dlp |
art |
pillow (album cover rendering) |
dev |
pytest, ruff |
Run these from your downloaded or cloned checkout. The helpers install the
youtube and art extras into the active virtual environment, or create
.venv in the checkout if none is active. They require Python 3.10+. mpv is
auto-installed on Windows; on other platforms the helpers only warn about it.
Linux/macOS:
bash install.sh
source .venv/bin/activate # unless an existing environment was usedWindows (PowerShell):
.\install.ps1
.\.venv\Scripts\Activate.ps1 # unless an existing environment was usedenigmatic # launch
python -m enigmatic_player| Key | Action |
|---|---|
Enter |
play highlighted |
p |
play / pause |
n b |
next / previous |
j k |
move up / down in list |
/ |
focus search bar |
a |
enqueue highlighted |
t |
toggle queue view |
c |
clear queue |
x |
shuffle on/off |
r |
repeat on/off |
+ - |
volume up / down |
[ ] |
speed down / up |
m |
toggle reverb |
y |
toggle pitch mode (tempo / nightcore) |
h |
focus playlists / leave playlist view |
H |
choose a playlist for the highlighted track |
N |
create playlist |
R |
rename the open playlist |
D |
delete the open playlist |
q |
quit |
The sidebar switches sources (Local / YouTube). For YouTube, type a query in the search bar and press Enter.
Press H (or a result's heart button) to choose a saved playlist with the
arrow keys and Enter; Escape cancels. Open playlists from the sidebar and
use the remove button to delete individual tracks. Playing a playlist track
loads that playlist into the playback queue.
enigmatic tui # launch the TUI (default)
enigmatic play ~/Music/lofi/ # play a folder
enigmatic play song.mp3 # play a file
enigmatic play https://youtu.be/... # play a URL
enigmatic search "lofi" --provider youtube --limit 10
enigmatic formats <video-url> # list YouTube audio formats
enigmatic config --library ~/Music # add a music folder
enigmatic status # show config summaryNothing required — ytmusicapi works anonymously for search/exists, and
yt-dlp resolves stream URLs. A free YT Music account is enough.
- Config: platform config dir (
~/.config/enigmatic-player/config.jsonon Linux) — credentials stored with0600perms. - Session (last queue) auto-saved to the data dir and restored on launch.
pip install -e ".[dev,youtube,art]"
pytest -q # unit + headless TUI smoke tests
ruff check src testssrc/enigmatic_player/
app.py # Textual App: layout, key bindings, orchestration
theme.css # color theme
cli.py # one-shot commands (tui/play/search/formats/config/status)
config.py # config + session persistence
core/
player.py # mpv subprocess + JSON IPC (socket / named pipe)
queue.py # shuffle/repeat logic
track.py # unified Track model
providers/
local.py # folder scan + tag/art extraction
youtube.py # ytmusicapi + yt-dlp
ui/
art.py # album cover rendering for the terminal
now_playing.py # art, meta, progress, mini-EQ, transport
tracklist.py # reusable list of tracks
Audio flows: UI → provider.resolve_stream(track) → stream URL → mpv. A
single long-lived mpv process (started with --idle) is driven over JSON
IPC: Unix socket on POSIX, named pipe on Windows (ctypes, no pywin32).
MIT