2017-03-28 06:20 CEST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0001398MPDOtherpublic2009-01-27 15:25
ReporterToyKeeper 
Assigned Tocirrus 
PrioritylowSeverityfeatureReproducibilityalways
StatusclosedResolutionfixed 
Product Version 
Target VersionFixed in Versiongit 
Summary0001398: add / use song ratings
DescriptionIn order to automatically choose better music more often, it'd be nice to add support for song ratings.

Song ratings should probably be represented internally as a float between 0.0 and 1.0, as this simplifies the logic involved in picking songs based on ratings, and provides unlimited resolution for subtle value differences.

A simple and effective algorithm for selecting (or skipping) a song based on rating is: choose a random number in the same range (0.0 - 1.0) as the ratings, and in the song rating is greater than the random number, play the song. Otherwise, skip the song.

I've implemented this feature in other music players, and the effect on the playlist is very nice. Better songs get played more often.

To amplify the effect of song ratings, I've found it more effective to multiply the song rating by itself a few times before comparing it to the random number. Cubing (rating ** 3) seems to work well. This doesn't hurt a good song's score much, but it will drop bad songs to nearly zero, so the bad songs get played *far* less often.

Another useful rating mode is to take the cube root of the rating instead. This makes almost all songs get played ... except for the really bad ones. So, it allows users to "blacklist" songs but hear everything else.

It's worth noting that this pretty much makes play-in-order mode impossible. Arbitrarily skipping or playing songs based on a random number is incompatible with that style of playlist handling. The rating-based auto-DJ would need to be optional, to allow users to play in traditional ordered mode.

As for storing the song rating data, the best solution I've found is to attach the ratings as subfiles. So, after rating /foo/bar.mp3, there will be a /foo/.bar.mp3/.rating file, containing a plain-text number. This may seem crazy, but it lacks most of the problems from the other two most common approaches -- a database, and in-file tags.

Specifically, a database has these problems:
  - Any time a song or directory is renamed, all data attached to affected songs goes stale, and will most likely be lost. Song rating data takes a long time to generate, so losing it for reasons as basic as renaming a directory is a big problem.
  - Databases, even in XML or plaintext formats, are difficult to access with standard unix tools. The user may want to do other things with the rating data, such as write a script to sync music to a portable player (but only when the rating is higher than a threshold), generate static playlists or directories-full-of-symlinks based on ratings, generate reports based on rating statistics, or even delete all songs with a too-low rating.
  - Since the ratings are stored in a different place than the songs, the chance of accidental loss is greater. Most users probably don't back up their ~/.mpd/tag_cache, even if they back up their music, so a hardware failure would destroy the ratings they may have spent months or years tuning.

In-song tags (ID3, etc) also have problems:
  - Each format requires special support, and some formats don't allow this type of data at all. Code to access the ratings becomes a large project in itself, and odd limitations and bugs tend to crop up on a per-format basis.
  - Again, it's very difficult to access the rating data with standard unix tools, or create add-on modules for private use.
  - The file changes every time the rating changes, which really screws with backup systems and file metadata. Some people care about the modtime or md5sum of their files, and don't want to change it unless necessary. It's annoying to re-backup a 10M file because three bytes changed.
  - If a file is shared, users will probably disagree about ratings. The rating is not actually a property of the song, but a value associated with individual users. As such, it should not be stored in the song.

Granted, the plain-text subfile approach also has some issues:
  - When renaming individual songs, the corresponding dotfiles should also be renamed.
  - Some filesystems handle small files inefficiently, and you may end up with up to 4000 wasted bytes on disk per song.

I consider those issues to be relatively minor.

In order to remain more or less compatible with how mpd works now, I'd suggest the following approach: Store ratings as subfiles, but cache them in the database for quicker internal access. Re-sync the database with the subfiles during updates, or per-song whenever a song is next in the playlist. This should provide the benefits of both approaches, without a large amount of overhead.

The display of ratings is up to the client. It could be shown as a value of zero to five stars, a percent, or whatever. A 0.0 to 1.0 float is easily mapped onto nearly any style of display.

Unrated songs should probably be treated as if they were rated with a default value, such as 0.5. An "unrated only" playlist mode would also be useful, to assist users in rating songs.
TagsNo tags attached.
Attached Files

-Relationships
has duplicate 0002204closedcirrus Would like new song / rating fields 
+Relationships

-Notes

~0001088

gregf (reporter)

Have wanted something like this for a while myself, a queue option or rating system would be very nice IMHO.

~0001317

beoba (reporter)

Chiming in to say that this would be really awesome. It's pretty much the only thing that I miss with MPD.

It'd probably be better in the long run to figure out a way to store long-term file info on mpd's side in some sort of database. Getting this implemented will open a lot of doors for ratings as well as a lot of other feature improvements (ex: anything involving dynamic playlists that rely on the db to choose what songs should be included).

~0002911

cirrus (administrator)

implemented in git, accessible via gmpc (git)
+Notes

-Issue History
Date Modified Username Field Change
2006-11-19 05:46 ToyKeeper New Issue
2006-11-19 05:46 ToyKeeper Status new => assigned
2006-11-19 05:46 ToyKeeper Assigned To => shank
2006-11-22 23:30 gregf Note Added: 0001088
2007-03-06 06:03 beoba Note Added: 0001317
2008-10-25 19:04 Avuton Olrich Assigned To shank => cirrus
2008-10-25 21:57 Avuton Olrich Category => Other
2008-10-27 11:13 cirrus Priority normal => low
2009-01-21 13:57 cirrus Note Added: 0002911
2009-01-21 13:57 cirrus Status assigned => resolved
2009-01-21 13:57 cirrus Fixed in Version => git
2009-01-21 13:57 cirrus Resolution open => fixed
2009-01-27 15:25 Avuton Olrich Status resolved => closed
2009-03-28 21:53 cirrus Relationship added has duplicate 0002204
+Issue History