Tag Formats & Spec Deviations


Quod Libet deviates from several of the standards it claims to support. We’ll document them here, but most of the time we won’t change them; we had a good reason for violating them in the first place.

General Deviations

Since we translate to and from many formats, sometimes we’re forced to accept the lowest common denominator among tag formats. Don’t worry; if it’s too low we’ll figure out some way around it.

  • Dates are restricted to YYYY or YYYY-MM-DD formats. Blame ID3.

  • = and ~ are not allowed in tag names, and tag names must also be pure ASCII.

  • Tag names are always case-insensitive.

  • Newlines are not allowed in tag values. If you use a newline in a tag value, it will instead be treated as two values for the tag.


UTF-8 and ID3 Tags

If Quod Libet finds data in an MP3 claiming to be “latin 1”, it won’t trust it. It’ll try UTF-8 and some other encodings before it gives up and actually considers it Latin 1. On the other hand, when it writes tags, it saves purely ASCII values as UTF-8 and any non-ASCII values as UTF-16. This means it won’t try to “guess” when it reloads them, and other programs shouldn’t either.

Using a format like Ogg Vorbis, FLAC, or Musepack, the tag encoding is known and Unicode is perfectly supported.

Genre and TCON

The ID3 standard is ambiguous in its specification for the TCON frame. If you try to use a numeric genre in the form of 02 or (23) (for example) it will get translated into a text genre. This means there’s no way to have a genre actually start with (xx) for MP3s.

QuodLibet::TXXX Frames

ID3 doesn’t let you have frames named whatever you want like Ogg Vorbis and APEv2 do. However, it does let you create “TXXX” frames which are text data with an associated “description”. Quod Libet uses these frames with a `QuodLibet``::<tagname> description to store tags that don’t have ID3 counterparts. For example, labelid is stored as `QuodLibet`::labelid.

RVA2 / ReplayGain

Quod Libet implements ReplayGain using MP3’s RVA2 frame. Unfortunately there is no standard on how to read RVA2 frames to support RG properly. If the description string is “album” the gain is treated as the album/audiophile value. Any other value is read as the track/radio value, but an actual description of “track” will preempt other values.

I’ve passed this information along to the GStreamer guys and their RVA2 support should match this, once it’s completed.

foobar2000-style TXXX:replaygain_* tags are also supported, but migrated to the proper RVA2 format on save.

COMM Frame Language codes

Language codes in COMM frames with empty descriptors are replaced by x00x00x00 on save. These tend to contain garbage rather than valid language codes anyway, and empty descriptors are usually a sign of comments migrated ID3v1 or other formats that do not support language markers.

Legacy Stuff

Multiframe Hack:

Since versions of ID3 prior to 2.4 did not support multiple values in a single text frame, we stored multiple text frames of the same type with one value for each if you tried to save more than one value per frame. This was strictly a violation of the ID3 spec, but we never encountered an ID3 reader that had trouble reading the tags saved this way (and still haven’t).

Now that we use Mutagen, we store multiple values in the standard ID3v2.4 format. Old tags are migrated when you edit them.

QuodLibet:: COMM Frames:

Quod Libet used to use COMM frames instead of TXXX frames for its extended tag names. It will still load old COMM tags, but clears then when you save the file again.


Naming Conflicts

Since we turn APEv2’s Subtitle tag into version, you can’t edit a tag named subtitle in MPC files. Similar problems exist for Track, Catalog, Year, and Record location tags.


This is a list of Ogg Vorbis tags Quod Libet uses that require special handling. They are presented here in the hopes that other applications will adopt them.


The rating tag has a subkey of an email address, and is formatted as e.g. rating:quodlibet@sacredchao.net. The email is used as a unique identifier to allow multiple users to share the same files (it need not actually be an email address, but having it as such ensures that it’s unique across users). It represents how much a user likes a song. Its value is a string representation of a floating point number between 0.0 and 1.0, inclusive. This format is chosen so the application may decide what precision it offers to the user, and how this information is presented. If no value is present, the rating should be assumed to be 0.5.

Example: rating:quodlibet@sacredchao.net=0.67


The playcount tag has a subkey of an email address, and is formatted as e.g. playcount:quodlibet@sacredchao.net. It stores how many times the user has played the song all the way through, as a numeric string. If no value is present, it should be assumed to be 0.

Example: playcount:quodlibet@sacredchao.net=3


The website tag stores an absolute IRI (Internationalized Resource Identifier), as per RFC 3987. The intent is that it hold an IRI suitable for opening in a standard web browser (e.g. http, https, or ftp scheme). As it is an IRI, and not a URI, it should be stored in unescaped form. If an application needs a URI, it should follow the procedure in RFC 3987 section 3.1 to convert a valid IRI to a valid URI. As per the Vorbis comment specification, the tag must be a UTF-8 representation of the Unicode string.

This tag may occur any number of times in a file.

Performer Roles

This is similar to the ID3v2 IPLS (involved person list) frame. Quod Libet displays these tags by putting the role after the name, parenthesized (e.g. Béla Fleck (banjo)), but in other supporting programs the role can be associated with the name in any understandable way, or simply ignored and treated like an ordinary performer tag.