n10v / id3v2

🎵 ID3 decoding and encoding library for Go
https://pkg.go.dev/github.com/bogem/id3v2/v2
MIT License
337 stars 52 forks source link

Clearing TCON #26

Closed shilch closed 7 years ago

shilch commented 7 years ago

Hi, thank you for this nice library!

I have problems clearing (not setting) the TCON (= genre) Frame. For every written MP3 VLC as well as exiftool show "Blues". According to https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres Blues has the identifier 0 which probably is the default value when writing. I would like to set this identifier to 255 as mentioned here: https://en.wikipedia.org/wiki/ID3#Layout

I was able to set the genre to Classic Rock (id: 1) doing

tag.AddFrame("TCON", id3v2.TextFrame{
    Encoding: id3v2.ENUTF8,
    Text: "1"
})

However, setting to 255 does not work. So far I tried:

tag.DeleteFrames("TCON")
tag.AddFrame("TCON", id3v2.TextFrame{
    Encoding: id3v2.ENUTF8,
    Text: "255"
})
tag.AddFrame("TCON", id3v2.TextFrame{
    Encoding: id3v2.ENUTF8,
    Text: "FF"
})
tag.AddFrame("TCON", id3v2.TextFrame{
    Encoding: id3v2.ENUTF8,
    Text: string(255)
})
tag.AddFrame("TCON", id3v2.PictureFrame{
    Picture: []byte{ 255 },
})

I do not know much about how id3 works so some tries might be pointless. Do you know, how to unset the genre?

Thank you in advance!

Edit: I wrote this to list all frames:

tag, err := id3v2.Open("test.mp3", id3v2.Options{ Parse: true })
if err != nil {
    panic(err)
}
defer tag.Close()

for k, v := range tag.AllFrames() {
    fmt.Println(k)
    for _, f := range v {
        fmt.Printf("    %T\n", f)
    }
}

I tested it with two MP3s: one for which exiftool (and VLC) shows 'Blues' as Genre and one for which none of the tools show a Genre. For both it does not list TCON as frame. Here is the output:

The one from id3v2 where it says 'Blues':

TRCK
    id3v2.TextFrame
TPE1
    id3v2.TextFrame
TALB
    id3v2.TextFrame
TIT2
    id3v2.TextFrame
TYER
    id3v2.TextFrame
APIC
    id3v2.PictureFrame

Another one where the tools do not show a genre:

TIT2
    id3v2.TextFrame
TPE1
    id3v2.TextFrame
TPE2
    id3v2.TextFrame
TALB
    id3v2.TextFrame
TYER
    id3v2.TextFrame
TRCK
    id3v2.TextFrame

(BTW: why is there no APIC frame, if the player shows a picture?)

n10v commented 7 years ago

Hi!

According to https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres

as mentioned here: https://en.wikipedia.org/wiki/ID3#Layout

The problem is, what you are looking for ID3v1 genres and they're totally different than in ID3v2. Documentation says:

  TCON
   The 'Content type', which ID3v1 was stored as a one byte numeric
   value only, is now a string. You may use one or several of the ID3v1
   types as numerical strings, or, since the category list would be
   impossible to maintain with accurate and up to date categories,
   define your own. Example: "21" $00 "Eurodisco" $00

   You may also use any of the following keywords:

     RX  Remix
     CR  Cover

This library supports only ID3v2 tags and can't work with ID3v1, so you should use just a numeric string ("0") for setting genre, not a byte:

tag.SetGenre("0")

Do you know, how to unset the genre?

Yes:

tag.DeleteFrames(tag.CommonID("Genre"))

(BTW: why is there no APIC frame, if the player shows a picture?)

It depends on many things, I can't say you now why it's so. I should debug this track to understand the problem. Very likely what the size of APIC is non-standard (related to #13). This library unfortunately can't parse it.

shilch commented 7 years ago

Thank you for the quick response! Sadly, delete Frames did not work. However, I was able to manage it:

I read the MP3 to a byte slice. Then I search for the 0xFF, 0xBB (magic number) and the "TAG" sequences in the slice and remove everything before the magic number and everything after "TAG" (including). Next I create an empty tag using your library, write this tag to the new file and append the just edited byte slice. Now genre is set to none! I do not now the reason of this problem but now it works.

Thank you!

n10v commented 7 years ago

Sorry, but I forgot to say, what after deleting you should save the tag:

tag.DeleteFrames(tag.CommonID("Genre"))
if err := tag.Save(); err != nil {
    panic(err)
}
tag.Close()

This should work.

tag.DeleleFrames deletes frames only in tag, but not in underlying file.

shilch commented 7 years ago

Yeah, I did save. I do not know the problem, however it is working now. Thank you!