[blog index]

Adding album art to Ncmpcpp

Ncmpcpp is a really nice mpd client for anyone that prefers cli based applications. It has all the functionality one would need, but sadly it has no built-in way of showing album art for the current playing song (to be fair, rendering images via a terminal emulator is pretty tricky).

Here I'll show you how to include album art in your ncmcpp client and include the built-in visualizer while browsing songs.

The final result would be something like this:

ncmpcpp

Prerequisites

To start off, a few dependencies that need to be installed in order for this to work:

tmux           (to encapsulate everything in one window)
inotify-tools  (for changing album art when switching songs)
ueberzug       (for image rendering)
ffmpeg         (used in scaling the album art)
mpc            (cli client for MPD)

You can get Ueberzug here.

Setup

Displaying cover images

The basic idea is that each time the song changes it triggers a script that searches for an album cover and copies it in /tmp as album_cover.png. Another script listens for changes on that file and renders the new image in the terminal.

Start by creating a script named cover.sh in ~/.ncmcpp/:

#!/bin/bash

source "`ueberzug library`"

COVER="/tmp/album_cover.png"

function add_cover {
  ImageLayer::add [identifier]="img" [x]="2" [y]="1" [path]="$COVER"
}

ImageLayer 0< <(
if [ ! -f "$COVER" ]; then
  cp "$HOME/.ncmpcpp/default_cover.png" "$COVER"
fi
#rerender image when changed
while inotifywait -q -q -e close_write "$COVER"; do
  add_cover
done
)

This is going to listen for cover changes and render them.

If no album cover for the current song is found, a default image will be selected. Be sure to add one named default_cover.png in ~/.ncmpcpp/.

Now create cover_obs.sh in the same directory:

#!/bin/bash

COVER="/tmp/album_cover.png"
COVER_SIZE="400"

#path to current song
file="$MUSIC_DIR/$(mpc --format %file% current)"
album="${file%/*}"
#search for cover image
art=$(find "$album"  -maxdepth 1 | grep -m 1 ".*\.\(jpg\|png\|gif\|bmp\)")
if [ "$art" = "" ]; then
  art="$HOME/.ncmpcpp/default_cover.png"
fi
#copy and resize image to destination
ffmpeg -loglevel 0 -y -i "$art" -vf "scale=$COVER_SIZE:-1" "$COVER"

This is the script executed when switching songs. It searches for images in the directory of the current song.

Here I chose a render size of 400 x 400, but it can be anything.

Notice the use of $MUSIC_DIR. You need to export it with the path to your music directory.

Tell ncmpcpp to execute it every time the song changes by adding this to ~/.ncmpcpp/config

execute_on_song_change = "~/.ncmpcpp/cover_obs.sh"

And don't forget to make them executable

chmod +x cover.sh
chmod +x cover_obs.sh

Wrapping everything in one window

As mentioned above, we use tmux to run multiple terminal based programs in a single window so that everything fits nicely (i.e. 2 instances of ncmpcpp and one terminal running our image rendering script).

Create a file named tsession in ~/.ncmpcpp/ to define a tmux session:

neww
set -g status off

#image pane; run cover script, disable text output and remove prompt
send-keys "stty -echo" C-m
send-keys "tput civis -- invisible" C-m
send-keys "export PS1=''" C-m
send-keys "clear" C-m
send-keys "~/.ncmpcpp/cover.sh " C-m

#catalog pane; run instance of ncmpcpp
split-window -v
select-pane -t 1
send-keys "ncmpcpp --config='~/.ncmpcpp/catalog.conf'" C-m
send-keys 1

#visualizer pane; run instance of ncmpcpp in visualizer mode
select-pane -t 0
split-window -h
send-keys "ncmpcpp --config='~/.ncmpcpp/visualizer.conf'" C-m
send-keys 8
send-keys u

#resize image and visualizer pane to fit image
resize-pane -t 0 -x 49 -y 23
resize-pane -t 1 -y 23

#hook for keeping the image pane size constant
set-hook client-resized 'resize-pane -t 0 -x 49 -y 23'

#focus on catalog pane
select-pane -t 2

Here I used some custom configuration for both catalog and visualizer, but it's not mandatory. If you changed the image size from cover_obs.sh, you may want to adjust the pane resize values.

Define an alias in your .bashrc so it's more convenient to start:

alias music='tmux new-session -s $$ "tmux source-file ~/.ncmpcpp/tsession"'

This will create the session and name it after it's PID. One important thing to note is that whenever you close the terminal, the session will keep running in a detached state. To circumvent this, also add the following:

_trap_exit() { tmux kill-session -t $$; }

This way the session will be killed and no resources will be wasted.

Now simply type music into the terminal to launch it.

You can take a look at the complete config files here.

by Radu Mirea