nicfit / eyeD3

eyeD3 is a Python module and command line program for processing ID3 tags. Information about mp3 files (i.e bit rate, sample frequency, play time, etc.) is also provided. The formats supported are ID3v1 (1.0/1.1) and ID3v2 (2.3/2.4).
http://eyed3.nicfit.net/
GNU General Public License v3.0
532 stars 58 forks source link

Antiquated ReplayGain tags (RGAD and RVA2) throws exceptions #618

Open michaelkrieger opened 5 months ago

michaelkrieger commented 5 months ago

The RGAD and RVA2 tags are extremely common and well documented.

The ID3v2 tag is divided into frames. The preferred means of storing ReplayGain metadata is use of TXXX key/value pair frames. Two other legacy schemes for storing ReplayGain metadata exist: RGAD and RVA2. These formats are documented in the appendix. Players may choose to look for these formats if metadata in the TXXX format is not found in the ID3v2 tag. New scanners may write these older formats in addition to the newer (TXXX) ones if they wish to remain backwards compatible with older players.

While I'd agree that these are non-standard frames, they appear quite common in the wild, and are supported by some older players. As such, eyeD3 throwing an exception and failing outright seems inappropriate. The options should be to (1) silently remove them, or (2) copy the matching TXXX tag. I'd probably suggest the first (maybe with a warning) that data is being removed, though I note that this would remove tags that older players may use. None of the ReplayGain data isn't replaceable in any case.

The error:

Writing ID3 version v2.3
Uncaught exception: Unable to convert the following frames to version v2.3: RGAD

eyed3:ERROR: Unable to convert the following frames to version v2.3: RGAD
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/eyed3/main.py", line 277, in _main
    retval = mainFunc(args, config)
             ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/eyed3/main.py", line 41, in main
    eyed3.utils.walk(args.plugin, p, excludes=args.excludes, fs_encoding=args.fs_encoding,
  File "/usr/lib/python3/dist-packages/eyed3/utils/__init__.py", line 71, in walk
    handler.handleFile(os.path.abspath(path))
  File "/usr/lib/python3/dist-packages/eyed3/plugins/classic.py", line 504, in handleFile
    self.audio_file.tag.save(
  File "/usr/lib/python3/dist-packages/eyed3/id3/tag.py", line 904, in save
    self.version = version
    ^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/eyed3/id3/tag.py", line 221, in version
    converted = self._convertFrames(std, non, v)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/eyed3/id3/tag.py", line 1346, in _convertFrames
    raise TagException("Unable to convert the following frames to "
eyed3.id3.tag.TagException: Unable to convert the following frames to version v2.3: RGAD

v0.9.7, and I don't see any changes in the GIT history since that point which would remove or handle these frames, so I assume would be an issue in HEAD.

As a note, I have added the eyeD3 --remove-frame "RGAD" ... and it does run as expected. My issue stems with the ungraceful handling with this. Since it is common and acknowledged (_This tag specification is not part of any version of the ID3 specification but is acknowledged as an "in the wild" tag by the ID3 standards organization._), gracefully stripping it out without throwing paragraphs of exceptions might be in order.