Generate .mood moodbar files for your whole music collection
10th April 2011
Amarok moodbar wiki page has 2 nice scripts to generate .mood files for your whole music collection (to be displayed by amarok when playing).
Both scripts should be started from the directory where you keep your music. The .mood files will be generated next to the source music files (in the same directories). You can modify the scripts to have the moods stored to $HOME/.kde/share/apps/amarok/moods/, so as not to clutter your music directories.
Script for multicore CPUs (will not overwrite existing mood files):
#!/bin/bash
NUMCPU="$(grep ^processor /proc/cpuinfo | wc -l)"
find . -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma)' | while read i ; do
while [ `jobs -p | wc -l` -ge $NUMCPU ] ; do
sleep 0.1
done
TEMP="${i%.*}.mood"
OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'`
if [ ! -e "$OUTF" ] ; then
moodbar -o "$OUTF" "$i" &
fi
done
Script for single-threaded moods generation (will only overwrite the last-generated mood file from a previous run):
#!/bin/bash
DIR=${1:-.}
LAST=.moodbar-lastreadsong
C_RET=0
control_c() # run if user hits control-c
{
echo "$1" > "$LAST"
echo "Exiting..."
exit
}
if [ -e "$LAST" ]; then
read filetodelete < "$LAST"
rm "$filetodelete" "$LAST"
fi
exec 9< <(find "$DIR" -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac|wma)') # you may need to add m4a and mp4
while read i
do
TEMP="${i%.*}.mood"
OUTF=`echo "$TEMP" | sed 's#\(.*\)/\([^,]*\)#\1/.\2#'`
trap 'control_c "$OUTF"' INT
if [ ! -e "$OUTF" ] || [ "$i" -nt "$OUTF" ]; then
moodbar -o "$OUTF" "$i" || { C_RET=1; echo "An error occurred!" >&2; }
fi
done <&9
exec 9<&-
exit $C_RET
That same page has a link to an older, somewhat more polished ruby script for the same task. It requires a running instance of Amarok, and uses it's media collection to find music files and create mood files for them. This script can potentially (after a little editing) store .mood files either with the music or to the $HOME/.kde/... path mentioned above. It is for an older version of Amarok, and thus is not likely to work with e.g. Amarok 2.4
#!/usr/bin/ruby
# Simple moodbar file management utility by Joe Rabinoff
# This is also my first ever ruby script so bear with me
$moodbar_folder = "#{ENV['HOME']}/.kde/share/apps/amarok/moods/"
def usage()
print "This is the moodbar file management utility\n"
print "\n"
print "Usage is:\n"
print " moodbar_util.rb -rename Rename mood files" \
+ " from any old naming scheme to the current one\n" \
+ " (not applicable when mood" \
+ " files are stored with music)\n"
print " moodbar_util.rb -calcall Calculate all un-calculated" \
+ " mood files\n"
exit(1)
end
def check_amarok_running()
result = `dcop 'amarok*'`.split("\n")
return (result.length > 0)
end
def get_devices()
result = `dcop amarok collection query 'SELECT id, lastmountpoint FROM devices;'`.split("\n")
ret = Hash.new()
result.each_index do |i|
ret[result[i].to_i] = result[i+1] if i % 2 == 0
end
return ret
end
def mood_name(url, deviceid)
ret = url.gsub(/\//, ',')
return deviceid.to_s + "," + ret
end
def rename()
print "Renaming mood files from outdated naming schemes...\n"
# As far as I can tell, the best way to do this is just select all
# tracks, check the old possible moodbar names, and rename them
tracks = `dcop amarok collection query 'SELECT url, deviceid FROM tags;'`.split("\n")
devices = get_devices
0.step(tracks.length-1, 2) do |i|
url = tracks[i].sub(/\.[^\.]*$/, '.mood')
deviceid = tracks[i+1].to_i
path = url.sub(/\./, '')
if devices.has_key?(deviceid)
path = devices[deviceid] + path
end
moodfile = $moodbar_folder + mood_name(url, deviceid)
moodfile1 = $moodbar_folder + path.gsub(/\//, ',')
next if FileTest.exists?(moodfile)
if FileTest.exists?(moodfile1)
system("mv", "-f", moodfile1, moodfile)
print "Moved ", moodfile1, " to ", moodfile, "\n"
end
end
end
def calcall()
print "Calculating all nonexisting moodbars...\n\n"
tracks = `dcop amarok collection query 'SELECT url, deviceid FROM tags;'`.split("\n")
devices = get_devices
withMusic = (`dcop amarok script readConfig MoodsWithMusic`.chomp == "true")
0.step(tracks.length-1, 2) do |i|
url = tracks[i]
deviceid = tracks[i+1].to_i
moodfile = ""
songpath = url.sub(/\./, '')
if devices.has_key?(deviceid)
songpath = devices[deviceid] + songpath
end
if withMusic
moodfile = songpath.sub(/\.[^\.]*$/, '.mood')
moodfile = File.dirname(moodfile) + "/." + File.basename(moodfile)
else
moodfile = $moodbar_folder \
+ mood_name(url.sub(/\.[^\.]*$/, '.mood'), deviceid)
end
next if FileTest.exists?(moodfile) && FileTest.size(moodfile) > 0
next unless FileTest.exists?(songpath)
print "Saving moodbar for ", songpath, "\n"
print " to file ", moodfile, "\n"
system("moodbar", "-o", moodfile, songpath)
print "\n"
end
end
$mode = ARGV[0]
if !check_amarok_running
print "Amarok is not running! Please start Amarok and re-run " \
"this script.\n"
end
if $mode == "-rename"
rename
elsif $mode == "-calcall"
calcall
else
usage
end
August 18th, 2014 at 2:27
The shell script offered on KDE.org for multi-core CPUs will peg all cores at 100% and eventually lock up the machine even without using all available RAM. This version takes steps to avoid that problem.
#!/bin/bash -
# This program creates moodbar files for use with Amarok. It is designed for
# multi-core processors, but will also run on single-core processors. This is
# a modified version of the script offered on KDE's website. Changes in this
# version include using $HOME/Music by default unless a different directory is
# specified on the command line, changing $NUMCPU to $NUMTHREADS, using one-
# less core than is installed in the system, and launching moodbar using nice.
# I found that the version on KDE's site pegged all 8 cores in my CPU and
# locked up my computer after a time while using very little of the 32GB of
# installed RAM. Additionally, I included several more filename extensions to
# the regex in the find command line.
#
# This version is designed to be run from a cron job. Mine is set up to run
# once per week. This version also checks to ensure that moodbar is installed.
#
# On dual-core and single-core processors this program will run one instance
# of moodbar. Effectively, only quad-core, or higher, processors will be used
# with multiple threads of execution. Moodbar is very CPU-intensive. Nice is
# about all that can be done to hold it back on single-core CPUs. On dual-
# core, and higher, CPUs, one core is held in reserve for other tasks as an
# additional measure.
if ! which moodbar &>/dev/null; then
echo 'moodbar must be installed to use this program'
exit 1
fi
MUSIC=${1:-$HOME/Music}
if [[ -d $MUSIC ]]; then
cd $MUSIC
else
echo "$MUSIC is not a directory or does not exist"
exit 1
fi
NUMTHREADS=$(( $(grep ^processor /proc/cpuinfo | wc -l) - 1 ))
[[ $NUMTHREADS -gt 0 ]] || NUMTHREADS=1
find . -type f -regextype posix-awk \
-iregex '.*\.(wav|mp3|ogg|oga|flac|fla|wma|aiff|aac|m4a)' | \
while read i ; do
while [[ $(jobs -p | wc -l) -ge $NUMTHREADS ]] ; do
sleep 0.1
done
TEMP="${i%.*}.mood"
OUTF=$(sed 's#\(.*\)/\([^,]*\)#\1/.\2#' <</dev/null &
fi
done
August 18th, 2014 at 2:37
if [[ ! -e "$OUTF" ]] ; then
nice moodbar -o "$OUTF" "$i" &>/dev/null &
Somehow this code was not included in my previous comment. it goes just above the “fi” at the end of the script
August 18th, 2014 at 23:51
Scott,
thanks for sharing!
I think I haven’t used mood files generation since I’ve switched to Clementine as my primary music player and configured BitTorrent Sync of my music between 3 PCs I’m using the most frequently… This setup seems to only have minor drawbacks, and lots of benefits – including in-file storage of rating, score, play and skip counts, so that every separate Clementine instance will be aware of updates made on other PCs.