67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package files
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
id3v2 "github.com/bogem/id3v2/v2"
|
|
)
|
|
|
|
// applyMP3Tags writes only the provided non-empty tags to the MP3 file at
|
|
// realPath. It preserves existing frames when not overwritten.
|
|
func applyMP3Tags(realPath string, tags map[string]string) error {
|
|
// Open tag for read/write
|
|
tag, err := id3v2.Open(realPath, id3v2.Options{Parse: true})
|
|
if err != nil {
|
|
return fmt.Errorf("open id3v2: %w", err)
|
|
}
|
|
defer tag.Close()
|
|
|
|
// Helper to set a text frame (replace existing)
|
|
setFrame := func(frameID, value string) {
|
|
if strings.TrimSpace(value) == "" {
|
|
return
|
|
}
|
|
tag.DeleteAllFrames(frameID)
|
|
tag.AddTextFrame(frameID, tag.DefaultEncoding(), value)
|
|
}
|
|
|
|
for k, v := range tags {
|
|
if strings.TrimSpace(v) == "" {
|
|
continue
|
|
}
|
|
switch strings.ToLower(k) {
|
|
case "title":
|
|
setFrame("TIT2", v)
|
|
case "artist":
|
|
setFrame("TPE1", v)
|
|
case "album":
|
|
setFrame("TALB", v)
|
|
case "albumartist", "album artist":
|
|
setFrame("TPE2", v)
|
|
case "composer":
|
|
setFrame("TCOM", v)
|
|
case "year", "date":
|
|
setFrame("TDRC", v)
|
|
case "track":
|
|
setFrame("TRCK", v)
|
|
case "disc":
|
|
setFrame("TPOS", v)
|
|
case "genre":
|
|
setFrame("TCON", v)
|
|
default:
|
|
// write custom text frame under TXXX with description = key
|
|
// Use description to store the original key so we don't collide
|
|
// with standard frames.
|
|
// Note: bogem/id3v2 uses AddTextFrame for TXXX as well.
|
|
tag.AddTextFrame("TXXX", tag.DefaultEncoding(), v)
|
|
}
|
|
}
|
|
|
|
if err := tag.Save(); err != nil {
|
|
return fmt.Errorf("save id3v2: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|