mediafile
mediafile copied to clipboard
In MP3s, TXXX fields are always case insensitive
Beets seems to write replaygain tags in upper-case regardless of changelog entry 1.3.2 (https://beets.readthedocs.io/en/stable/changelog.html#december-22-2013) There are music player in the wild which only understand lower-case ReplayGain tags (Poweramp, KODI),
Using an actual version of a of Beets I can only find upper-case ReplayGain tags in my tagged files with a hex editor.
How I reproduced it:
First of all I download a clean WAV file from bandcamp.com for example. I convert the WAV file to a mp3 via Foobar using the Lame mp3 encoder. After that this mp3 goes into Picard. This goes through processing by Beets. For this I use a Docker Beets version (https://hub.docker.com/r/linuxserver/beets). After that I get a mp3 file including replay gain tags: 03 - New Light.mp3
Using a hex editor I only find upper-case ReplayGain tags in the header of the file.

I tried beet write (files have not changed) and beet write -f (files have changed) but the mp3 files still only have upper-case ReplayGain tags.
I also tried: I have completely deleted the ReplayGain tags from a series of files with zero and checked that they are really gone in the library (info) and the mp3 files. After that I re-tagged them with replaygain (replaygain). After that I found the ReplayGain tags again, only in upper-case.
I changed the lines of code in mediafile.py (https://github.com/beetbox/mediafile/blob/edc64145e9e96624f8a77fd3cb929891c946d4dc/mediafile.py#L2202-L2209) to see what tags are written. After applying scrub and relaygain again, I suddenly found two tags in my file, although with different names.
So when both are named differently, all of a sudden both show up. If both have the same name but are capitalized differently, they don't show up.


Thank you for the thorough investigation. This is definitely a bug. The problem is here, in MP3DescStorageStyle:
https://github.com/beetbox/mediafile/blob/edc64145e9e96624f8a77fd3cb929891c946d4dc/mediafile.py#L905-L909
Namely, when storing data into an ID3 TXXX field, which is disambiguated by its desc field, we currently match that desc string case-insensitively. This means that, if we first write the upper-case version of this field, then the second call to store will modify that field—rather than creating a second entry, as intended.
We should probably introduce a mode where these fields can be made case sensitive, as is required in this case.