This article introduces how I manage my music on the
command line with cmus and mpv.
mpv is a fork of mplayer and adds
bug patches, an improved command-line interface, and
an experimental Lua scripting option.
I wrote this post in 2014 and still use most of the features in 2016.
Using Python to organize a music directory
This portion introduces a Python script I use to organize my
music directory structure.
Note that this currently only works for mp3 files,
but the project is open to pull requests to support
other media formats.
I have a small collection of Python scripts I add to my PATH
in the bamos/python-scripts GitHub repository,
including music-organizer.py.
music-organizer.py organizes my music into the simple directory
structure of <artist>/<track>, where <artist> and <track> are
lower case strings separated by dashes.
I call these lowercase strings neat and convert them with the toNeat
function below.
Keeping the files as lowercase helps me navigate the music directory
on the command line if I’m trying to synchronize artists between
computers with unison or use mpv.
music-organizer.py can be run on an entire music collection to
create subdirectories, or within an artist directory to only
organize the songs.
Artist Mode.
In artist mode, all songs from subdirectories will be merged into
the current directory.
For example, suppose a user has the following directory structure
for an artist.
Running music-organizer.py --artist in this directory will
produce the following.
Collection Mode.
In collection mode, the artist names will be preserved to allow
the user to override metadata, and only songs in the top level will
be sorted.
For example, suppose a user has the following directory structure
as a collection.
Running music-organizer.py --collection in this directory will
produce the following.
Edge cases.
I’ve encountered two edge cases when running music-organizer.py on
my full music directory. Please try running music-organizer on
a copy or subset of your music directory first to ensure you don’t
run into any others!
Case 1. When two separate files share the same metadata, I will either
change the metadata with a tool like Picard or
use music-organizer.py to delete the conflicts with --delete-conflicts.
Case 2. When the metadata in some artist directory indicates the
tracks have different names, music-organizer.py will halt
and suggest this to be changed.
Use --ignore-multiple-artists to allow this.
Detailed Usage.
Improving mpv as a music player with Lua scripts
This portion introduces a simple Lua script to
add the following functionality using the mpv build
from the master branch.
Delete the current track.
Restore the previously deleted track.
Move the current track into a new subdirectory.
Print an MP3 track’s info.
Share a track’s information using the command-line email client mutt.
mpv reads all Lua scripts in ~/.mpv/lua by default.
If you want to store scripts in a different directory,
set them as lua=<filename> in ~/.mpv/config,
where <filename> is a comma delimited list of scripts to load.
From these scripts, mpv provides an mp class to interface
with the rest of the player, see the implementation on Github.
I only use mp.get_property("path") to get the path to the current track.
The following are snippets from my music.lua script,
which is in my dotfiles repository on Github.
I use the following Lua imports and helper function
to execute a shell command and return the output as a string.
Includes and helper functions.
Delete and restore tracks.
To delete a track, use mv to move the track to a temporary location,
and restore the track by copying back from this location.
This only enables one track to be restored, but can be
modified to use a stack to delete and restore an arbitrary number.
Move the current track into a new subdirectory.
Sometimes I filter through an album and make certain
songs as good by placing them in subdirectory entitled good.
This is added by making the directory if it doesn’t
exist and moving the track into the directory.
Print an MP3 track’s info.
The following uses exiftool to read exif metadata from an mp3
and concisely print the artist and title.
I disable mpv’s messaging by setting
msg-level=demux=no:ad=no:ffmpeg=no:ao=no in
.mpv/config and use this instead.
Share a track’s information using the command-line email client mutt.
This displays an interface prompting for a user’s email or
mutt alias and will send them an email with the song’s info.
Prompting the user for input is different between Linux and OSX
and I’ve included conditionals for both.
Registering keybindings.
Lastly, register the keybindings with mp by specifying
the key to press, the title, and Lua function.
Improving mpv as a music player with Bash/Zsh shell functions
This portion introduces a simple Lua script to add the following
functionality using the mpv build from the master branch.
I source mpv/shellrc.sh in my zshrc and bashrc
files to load the following aliases and functions.
These are all contained in my dotfiles repository on Github.
mpvnova uses mpv with no video for audio only.
mpvshuf uses mpvnova and infinitely shuffles.
mpvp uses mpvshuf to read a playlist.
playcurrentdir or pcd will use mpvshuf to play all the files in the
current directory tree.
playdir or pd will use mpvshuf to play all the files in the
directories provided on the command line.