mutagen icon indicating copy to clipboard operation
mutagen copied to clipboard

Cannot write tags to certain WAV files

Open Christilut opened this issue 3 years ago • 13 comments

I'm writing tags to WAV files and most seem to work but a small number has trouble writing tags.

I'm simply writing this tag: mutagen.id3.TIT2(encoding=3, text="test") and then calling save()

There must be something in the file because most WAV files do work and other string tags also work.

I uploaded the file here

The following error occurs:

Traceback (most recent call last):
  File "../tagger.py", line 89, in <module>
    tags_modified = write.write_tags(file_path, track)
  File "C:\Users\user\workspace\project\write.py", line 34, in write_tags
    tags_modified = filetypes.wav.write_tags(tagfile, json)
  File "C:\Users\user\workspace\project\filetypes\wav.py", line 94, in write_tags
    tags_all.save()
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_util.py", line 156, in wrapper
    return func(self, h, *args, **kwargs)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_file.py", line 132, in save
    return self.tags.save(filething, **kwargs)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_util.py", line 185, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_util.py", line 156, in wrapper
    return func(self, h, *args, **kwargs)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\wave.py", line 129, in save
    wave_file.insert_chunk(u'id3')
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_iff.py", line 338, in insert_chunk
    return self.root.insert_chunk(id_, data)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_iff.py", line 260, in insert_chunk
    insert_bytes(self._fileobj, size, next_offset)
  File "C:\Users\user\workspace\project\.venv\lib\site-packages\mutagen\_util.py", line 788, in insert_bytes
    raise ValueError
ValueError

Christilut avatar Sep 30 '20 08:09 Christilut

What do you mean by "trouble writing tags"?

lazka avatar Sep 30 '20 08:09 lazka

Sorry, was a bit fast posting there. Added the error.

Christilut avatar Sep 30 '20 08:09 Christilut

I see, thanks. Is this using the latest mutagen release?

lazka avatar Sep 30 '20 08:09 lazka

Yes mutagen 1.45.1

Christilut avatar Sep 30 '20 09:09 Christilut

ok, thanks

lazka avatar Sep 30 '20 09:09 lazka

Looking at the file I notice there is a mismatch in sizes in the LIST INFO chunk.

The LIST INFO chunk reports a size of 124 bytes, It contains two subchunks, IPRT with a size of 10 and ISFT with a size of 22. This makes together with 12 bytes header for the LIST INFO a toal of 44 bytes, which is less then the 124 bytes.

The empty space is probably intentional as a padding. I am not sure, but maybe this is what causes some miscalculation.

I am also not sure if this is strictly speaking a valid file. Usually for padding a JUNK chunk gets added. But if this is indeed the cause for the issue I think mutagen should be able to deal with this.

phw avatar Sep 30 '20 10:09 phw

Now that I wrote this I see what's actually wrong: The file seems to be truncated. It is 75391073 bytes long, but the data sizes inside sum up to 75391144 bytes. That's 71 missing bytes.

Adding those 71 bytes to the end of the file with:

truncate -s +71 "broken tags.wav"

fixes the file for me and I can save it with mutagen. It's the question how this should be handled in mutagen. What to do if the size inside the file is larger than the actual file size? Check this in advance and fail with a clear error? Or silently append null bytes?

phw avatar Sep 30 '20 11:09 phw

Two strategies come to mind:

  1. If the contained content is valid (and not truncated) we could somehow recover (we do this in flac where programs used to write wrong sizes a lot)
  2. Somehow make the stack trace of OP end up with and exception that states "truncated file", so next time we see this we know what's going on.

I'd guess (2) is easier?

lazka avatar Sep 30 '20 12:09 lazka

1. If the contained content is valid (and not truncated) we could somehow recover (we do this in flac where programs used to write wrong sizes a lot)

In this case the contained content is valid. And in this special case we could in theory even tell, because the last element in this file is a list which reports a size that is larger than the sum of its children. And the children all fit into the actual available space.

But it might be a bit tricky to always say this for sure in all cases. How do you know for sure that a container saying it is larger then available space really had only null bytes truncated and not actual data?

So I'd be for (2) for now.

phw avatar Sep 30 '20 12:09 phw

Just to be complete here and share my analysis: I verified the broken file using the script at https://gist.github.com/phw/07f2828cb1e04ba04f908b1473b07aac

This outputs the structure of the WAVE file with offsets and sizes and checks the size information:

RIFF WAVE	(offset: 0, size: 75391144, data-size: 75391136)
  fmt	(offset: 12, size: 24, data-size: 16)
  data	(offset: 36, size: 75390984, data-size: 75390976)
  LIST INFO	(offset: 75391020, size: 124, data-size: 116)
    IPRT	(offset: 75391032, size: 10, data-size: 2)
    ISFT	(offset: 75391042, size: 22, data-size: 14)
  Total: 44 bytes !SIZE MISMATCH!
Total: 75391144 bytes

File size: 75391073 bytes !SIZE MISMATCH!

The first !SIZE MISMATCH! warning for LIST INFO is not critical. This is just a warning that there is empty space after the last child, likely intentionally added for padding. This will not cause any trouble for mutagen. Apart from that the chunk sizes all neatly sum up to what is set as the size of the outer most container (75391144 bytes).

The real trouble is really the file being smaller then the reported sizes. For adding the ID3 chunk it attempts to seek to the position after the last chunk, and that would be 75391144.

phw avatar Sep 30 '20 12:09 phw

So I observed a similar problem with AIFF files. I had just ripped my entire CD collection using iTunes and some files would fail on being saved in MusicBrainz due to the file size being exactly one byte less than expected. Since for me it was always the case that the file was off by 1 byte, I made the following changes in my local mutagen library. This allowed me to completely tag my entire collection. I created a version of the above script that works for AIFF files at https://gist.github.com/Cars-10/c8a7f715ab38c1ff8618f95b9872a784

Not a complete solution, but at least another data point.

image

Cars-10 avatar Nov 11 '20 14:11 Cars-10

Does the script above for AIFF files actually fix the file size mismatch so that Picard can save the tag information? If so, how do I use it? I am assuming I run this on every file that has the problem? Forgive me if these are basic questions, I'm new to Picard and Plex, and just wanting to get my music library (on my FreeNas box) to work with Plex. The entire library is rips of my CD collection in the native format.

PaulMGibson avatar Dec 14 '20 20:12 PaulMGibson

The script only show you the expected size versus the measured size of the AIFF file. In my case all of the files where off by one byte. To actually fix the issue I installed a local copy of picard and changed the local copy of the mutagen file _util.py count <-1 and movesize <-1 they were using 0 before. Then picard had no issues processing my files.

Cars-10 avatar Dec 15 '20 12:12 Cars-10