Skip to content

About

Album art, timeline and synced lyrics for whatever's playing, right in your terminal.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nowplaying

Shows whatever media is playing right now — album art, the timeline, and the lyrics in time with the song — inside your terminal.

Written in C. It talks to any media player over MPRIS (D-Bus), fetches the cover art, and draws it with the kitty graphics protocol, so the artwork is real pixels, not coloured text.

   ┌──────────────┐        ▶  playing · mpv
   │              │
   │  album art   │        ━━━━━━━━━━━━━━━●────────────────────────
   │              │        1:23                                3:52
   │              │
   │              │        the line that was just sung
   └──────────────┘        the line being sung right now     ← accent
                           the next line
    How to Fight Lonel…    and the one after that
    Wilco                  …
    Summerteeth

The cover sits top-left, the track/artist/album go underneath it, and the timeline sits to its right. When the song has lyrics they scroll along under the timeline, with the line being sung highlighted. The accent colour — the artist line, the status line, the filled part of the bar, the current lyric — is pulled out of the cover art itself, so the whole thing recolours with every track.

nowplaying showing Nirvana – Stay Away, paused in firefox American Football – Never Meant, with synced lyrics in a yellow-green accent fakemink – London Life, with synced lyrics in a purple accent Sematary – Bleed A River, with synced lyrics in a red accent

Build

Needs a C compiler and these libraries (all with pkg-config files):

library why
dbus-1 talking to the player over MPRIS
libcurl downloading cover art and lyrics over http(s)
libpng, libjpeg decoding cover art
libwebp optional — WebP covers, detected at build time

On Arch: sudo pacman -S dbus curl libpng libjpeg-turbo libwebp On Debian/Ubuntu: sudo apt install libdbus-1-dev libcurl4-openssl-dev libpng-dev libjpeg-dev libwebp-dev

make
./nowplaying

sudo make install drops it in /usr/local/bin (make install PREFIX=~/.local if you would rather it went somewhere else).

Use

nowplaying [options]

  -p, --player NAME   prefer this MPRIS player (mpv, vlc, firefox, ...)
  -s, --size COLS     width of the cover art, in terminal columns
  -1, --once          print the current track once and exit
  -b, --blocks        draw the cover with unicode half blocks
  -k, --kitty         force the kitty graphics protocol
  -L, --no-lyrics     do not look for lyrics
  -h, --help          help
  -v, --version       version

Keys, while it is running:

key
q, Esc, Ctrl-C quit
space, p play / pause
n next track
b previous track
← → seek 5 seconds
l show / hide lyrics
+ - lyrics a quarter second earlier / later
r redraw

--once prints one frame inline and exits, which is handy from a script or a shell prompt. Everything else runs full-screen and updates live.

Which player it picks

Any MPRIS2 player will do — music players, mpv, VLC, or a tab playing media in Firefox or Chromium. When several are running it prefers the one you named with --player, then whichever is actually playing, and it sticks with its choice rather than flip-flopping. If nothing is running it waits and picks the player up as soon as one appears.

Lyrics

For each new track it looks, in order, for:

  1. lyrics the player itself publishes (xesam:asText in the MPRIS metadata),
  2. a .lrc file next to a local track — song.flac → song.lrc,
  3. LRCLIB, a free, open lyrics database — this sends the title, artist, album and length of the track to lrclib.net.

Timed (LRC) lyrics follow the song line by line: the sung line is highlighted in the accent colour, and the display updates the moment the next line starts, including after a seek. Untimed lyrics scroll slowly along with the song instead. If the words run early or late for your player, nudge them with + and -. Tracks without lyrics keep the plain layout, and --no-lyrics turns the whole thing off (and with it every request to lrclib.net).

Terminals

Cover art needs kitty graphics: kitty, Ghostty and WezTerm all work, and are detected automatically. Anywhere else it falls back to unicode half blocks with 24-bit colour, which looks surprisingly decent. Force either one with --blocks / --kitty, or set NOWPLAYING_RENDER=blocks|kitty.

The cover is scaled to the exact pixel size of the cell box it occupies, so it stays sharp and square whatever your font size is, and it is re-scaled from the already-decoded original whenever you resize the window — no re-download.

How it is put together

file
src/mpris.c MPRIS2 over D-Bus: find a player, read its metadata, send it commands
src/art.c fetch (file://, http(s)://), decode (PNG/JPEG/WebP), resample, pick the accent colour
src/lyrics.c find lyrics (player, .lrc, LRCLIB), parse LRC, time the lines
src/kitty.c kitty graphics protocol, and the half-block fallback
src/ui.c layout and drawing
src/main.c the loop, the keys, and worker threads that load art and lyrics without stalling the display

Art and lyrics load on their own threads, so a slow download never freezes the timeline. The position is read from the player twice a second and interpolated from the monotonic clock in between, which is what makes the bar move smoothly instead of in half-second steps.

About

Album art, timeline and synced lyrics for whatever's playing, right in your terminal.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages