Note
LMSmusly is obsolete and has been superseded by LMS Recommender.
Musly Integration for the Logitech Media Server
Musly is
a program and library for high performance audio music similarity computation. Musly only uses the audio signal when computing similarities. No metadata is used in the similarity computation process.
LMSmusly makes this functionality (comparable to MusicIP) available for LMS.
Features
- Finds music similar to a specific track and creates a static or dynamic playlist in LMS
- Implemented as a stand-alone CLI application
- Web interface
- Integration with extGUI4LMS
Status
- Musly itself seems stable, and preliminary testing suggests the quality of the results is excellent. It is also very fast, both at analyzing the music, and at finding tracks.
- LMSmusly is feature complete, but beta quality ( i.e. there may be quality issues)
Installation
libmusly v0.2
needs to be installed (specifically, the files libmusly.so
and libmusly_resample.so
) to the location /opt/musly-0.2/lib
If your platform is listed below, you can download a pre-built binary version, otherwise you have to build it yourself.
Binaries
First, make sure ffmpeg is available, since musly depends on it. If not, install it with your OS package management. Note that the binaries have been linked against ffmpeg 3.4.1 - if your version is too old, you'll have to upgrade it (e.g. see this ppa for Ubuntu LTS), or build your own (since only the audio part is required, you could compile a stripped-down version)
For x86 platforms (Intel, AMD), run cat /proc/cpuinfo | grep avx
if you are unsure if your CPU supports AVX instructions.
- Linux x86_64 AVX, ffmpeg linked dynamically: download
- Linux x86_64 no AVX, ffmpeg linked dynamically: download
- Linux arm64 / aarch64, ffmpeg linked dynamically: download
Building from source
Note: only necessary if you haven't installed a binary version already.
Building libmusly is pretty straightforward. Get the master branch from github and follow the instructions there.
Example
Install ffmpeg with your package manager.
Get sources and unpack:
wget https://github.com/dominikschnitzer/musly/archive/master.zip
wget http://bitbucket.org/eigen/eigen/get/3.3.4.tar.bz2
unzip master.zip
tar -C /tmp -xf eigen-eigen-5a0156e40feb.tar.bz2
Edit musly-master/CMakeLists.txt:
add_definitions(-DMUSLY_VERSION="${MUSLY_VERSION}")
# start additions
SET(CMAKE_INSTALL_PREFIX "/opt/musly-0.2")
SET(CMAKE_BUILD_TYPE "Release")
SET(CMAKE_SKIP_INSTALL_RPATH FALSE)
SET(CMAKE_SKIP_RPATH FALSE)
SET(EIGEN3_INCLUDE_DIR "/tmp/eigen-eigen-5a0156e40feb/")
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# end additions
Run cmake and make:
mkdir build; cd build
cmake ../musly-master
make -j4
sudo make install
LMSmusly
is implemented in Python and requires
- python 3
- python requests
- cherrypy, if you want to use the WebUI. Note: needs a fairly recent version ( tested with 13.1.0, <= 3.8 known not to work)
Most likely, these packages are available from your OS package management (e.g. python3
,python-requests
and python-cherrypy
in Debian, dev-lang/python
, dev-python/requests
and dev-python/cherrypy
in Gentoo etc.). Or if you prefer, you can use pip
with a virtual environment:
python3 -m venv ~/python-venv
source ~/python-venv/bin/activate
pip install requests
pip install cherrypy
Remember to execute source ~/python-venv/bin/activate
once per session before running lmsmusly.py
source distribution
The latest version is available here. Download and extract anywhere. It should run without installing it (or you could try installing it with the included setup.py
(read this first if you are unfamiliar with setuptools)).
Example (adjust for version):
wget "https://www.nexus0.net/pub/sw/lmsmusly/dist/LMSmusly-0.1.1.tar.gz"
tar xf LMSmusly-0.1.1.tar.gz
cd LMSmusly-0.1.1/src/
./lmsmusly.py -h
built distribution for python 3.6
The latest version is available for 64 bit Linux. This is basically an archive to be extracted to /
(i.e. the root of the filesystem). Note: not suitable for Debian/Ubuntu without manual adjustment of the location of Python site packages.
Usage Instructions
First, the music collection needs to be analyzed. Once this is done, playlists can be created either statically (i.e. with a fixed length), or the application can keep adding new songs when the player reaches the end of the playlist.
For playlist creation, a track is needed to compute the similarities (the so-called seed track). Default is to use the first track in the current playlist.
Run lmsmusly.py -h
to get help.
Modes of operation
Options for all operations
Option | Description | Example |
---|---|---|
--db-path | Database path. Required. | --db-path /home/user/musly |
--log-level | set log level | --log-level WARN |
--pid-file | write PID to a file | --pid-file /var/run/lmsmusly.pid |
analyze
Analyzes music files and writes the results to the database. The paths to the music files must match those in the LMS library, or the tracks will not be found. If you are running the analysis on a different machine, use the --replace-path
option.
Example: lmsmusly.py --db-path /home/user/musly analyze --replace-path /home/user/tmp/sshfs:/data/music /home/user/tmp/sshfs
There are two options (--extract-length
and --extract-start
) determining which part of the track is analyzed. Defaults should be fine. From the musly documentation:
- excerpt_length: The maximum length in seconds of the excerpt to decode. If zero or greater than the file length, decodes the whole file. Suggested value: 30.
- excerpt_start:The starting position in seconds of the excerpt to decode. If zero, decoding starts at the beginning. If negative, the excerpt is centered in the file, but starts at -excerpt_start the latest. If positive and excerpt_start + excerpt_length exceeds the file length, then the excerpt is taken from the end of the file. Suggested value: -48.
Run lmsmusly.py analyze -h
for a full list of options.
writejukebox
If there are a large number of tracks in the database, the startup time of lmsmusly increases significantly. To avoid this, lmsmusly can write a so-called jukebox (which is basically an initialized version of the similarity component) to the file system, and read it the next time it is started.
Example: lmsmusly.py --db-path /home/user/musly writejukebox
will write the jukebox to /home/user/musly/jukebox.bin
Then, when creating a playlist, you can use the --read-jukebox
option:
Example: lmsmusly.py --db-path /home/user/musly static --read-jukebox --lms lmsserver --lms-player 00:11:22:33:44:55 50
will create a static playlist
The only limitation this method has is that the jukebox file must match the content of the database when it was created. If files are analyzed after the jukebox was written, it will have to be recreated.
static
Creates a playlist with a fixed length starting from one track, then exits. The track can be specified either by having it in the playlist of the target player (default is to take the first track), or by passing the file name as a parameter.
Example: lmsmusly.py --db-path /home/user/musly static --lms lmsserver --lms-player 00:11:22:33:44:55 50
will add 50 tracks to the playlist of player 00:11:22:33:44:55 (based on the first track of the current playlist)
Run lmsmusly.py static -h
for a full list of options.
dynamic
Creates a playlist with a defined length starting from the first track of the current playlist, and keeps adding new songs when the player reaches the end of the playlist. Note that the application will never exit, but can be stopped using the web interface, or killed safely (with ctrl-c
or by sending SIGINT
or SIGTERM
to the process).
Example: lmsmusly.py --db-path /home/user/musly dynamic --lms lmsserver --lms-player 00:11:22:33:44:55
will continue adding tracks to the playlist of player 00:11:22:33:44:55 (based on the first track)
Run lmsmusly.py dynamic -h
for a full list of options.
Web Interface
A web interface can be enabled by passing the --webui
option. By default, it is available at http://hostname:8080
Duplicate tracks
If you don't want tracks being queued more than once in a session, use the --no-duplicates
option, which will avoid adding the same track for a number of tracks (default 100).
Similarity
The default is to find the (length of playlist, --numtracks
(default 10)) most similar tracks, which are added in descending order. Since by default the first track of a playlist is used as a seed, this will result in the most similar tracks being added for a session. If you want more variety, there are 2 options:
- use the
--seedtrack-index
option to select a less similar track as the seed track for the next tracks to be added - use the
--topresults-factor
option to adjust results selection. Normally, the top (length of playlist) tracks are calculated and added. With this option, the the top (length of playlist)*(topresults-factor+1) tracks are calculated, and tracks are added from an offset (length of playlist)*(topresults-factor). Example (length of playlist=10, topresults-factor=2): The top 20 tracks are calculated, and tracks 11-20 are added.
info
Shows information about libmusly and database statistics.
extGUI4LMS Integration
If LMS Musly is running in dynamic mode with the --webui
option, extGUI4LMS can display similar songs to the one playing / selected.
The URL to access it must be configured in Preferences > Technical Parameters > App_muslyURL in this format: http://hostname:8080/api
After a restart of the extGUI4LMS web application, results will be available in Currently Playing / Selected Track > More > LMS Musly.
Note: use the --start-paused
option if you only want LMS Musly functionality in extGUI4LMS without it modifying the playlist.
FAQ
- The music analysis crashes with a
7716 Illegal instruction (core dumped)
error. Why? - Your CPU doesn't support certain instructions (AVX, SSE4), either because it is very old (<2008 (SSE) / < 2011 (AVX) ), or low-end (some Atoms / Celerons / Pentiums). Use the non-AVX version of libmusly.
- Is it possible to run the analysis on a different machine then the one used to run the application afterwards?
- Yes, if the paths to the music files are identical (or the
--replace-path
option is used), simply copy thelmsmusly.db
file to the target. - Is it possible to change the paths to the music files after the analysis?
- Yes,
lmsmusly.db
is a sqlite3 database, so it can be processed with SQL easily. - Is it possible to steer the dynamic mode?
- The selection of the next tracks is always based on the first in the playlist (unless
--seedtrack-index
is used), so moving a different track to the first position will change the next results. Note, however, that a seed track will not be used more than once during one session (to avoid loops).
API
If the application is running in dynamic mode with --webui
, the following commands are available:
http://host:8080/api?cmd=lm-pause | pauses the application |
http://host:8080/api?cmd=lm-unpause | resumes the application |
http://host:8080/api?cmd=lm-exit | exits the application |
http://host:8080/api?cmd=lm-getstats | returns statistics (as JSON) |
http://host:8080/api?cmd=lm-getsimilar&path=/data/music/song.mp3&numres=10 | returns the numres most similar tracks (as JSON) |
License
GNU GPLv3
Reporting Issues
Use the discussion thread in the LMS forum.