trimmed down metadata & own extractor for vobis(flac)

This commit is contained in:
2026-04-15 22:33:36 +02:00
parent 759aa7e08b
commit e9fbd044d0
4 changed files with 127 additions and 28 deletions

View File

@@ -11,18 +11,27 @@ import (
) )
type Metadata struct { type Metadata struct {
Title string Title *string
Artist []string Artist []string
Album string Album *string
AlbumArtist []string AlbumArtist []string
Track int Track int
TotalTracks int TotalTracks int
Disc int Comment *string
TotalDiscs int
Comment string
} }
func ReadAudioTags(filePath string) (*Metadata, error) { func ReadAudioTags(filePath string) (*Metadata, error) {
ext := strings.ToLower(filepath.Ext(filePath))
switch {
case ext == ".flac":
return readVorbisMetadata(filePath)
default:
return readGenericAudioTags(filePath)
}
}
func readGenericAudioTags(filePath string) (*Metadata, error) {
f, err := os.Open(filePath) f, err := os.Open(filePath)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open file: %w", err) return nil, fmt.Errorf("failed to open file: %w", err)
@@ -35,18 +44,19 @@ func ReadAudioTags(filePath string) (*Metadata, error) {
} }
track, totalTracks := m.Track() track, totalTracks := m.Track()
disc, totalDiscs := m.Disc()
title := m.Title()
album := m.Album()
comment := m.Comment()
info := &Metadata{ info := &Metadata{
Title: m.Title(), Title: &title,
Artist: parseSeperatedTag(m.Artist()), Artist: parseSeperatedTag(m.Artist()),
Album: m.Album(), Album: &album,
AlbumArtist: parseSeperatedTag(m.AlbumArtist()), AlbumArtist: parseSeperatedTag(m.AlbumArtist()),
Track: track, Track: track,
TotalTracks: totalTracks, TotalTracks: totalTracks,
Disc: disc, Comment: &comment,
TotalDiscs: totalDiscs,
Comment: m.Comment(),
} }
return info, nil return info, nil

View File

@@ -2,12 +2,89 @@ package metadata
import ( import (
"log/slog" "log/slog"
"os"
"strconv" "strconv"
"github.com/go-flac/flacvorbis/v2" "github.com/go-flac/flacvorbis/v2"
"github.com/go-flac/go-flac/v2" "github.com/go-flac/go-flac/v2"
) )
func readVorbisMetadata(file string) (*Metadata, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
flacFile, err := flac.ParseMetadata(f)
if err != nil {
return nil, err
}
cmt, err := findVobisMetadata(*flacFile)
if err != nil {
return nil, err
}
titles, err := cmt.Get(flacvorbis.FIELD_TITLE)
if err != nil {
return nil, err
}
var title *string
if len(titles) > 0 {
title = &titles[0]
}
albums, err := cmt.Get(flacvorbis.FIELD_ALBUM)
if err != nil {
return nil, err
}
var album *string
if len(albums) > 0 {
album = &albums[0]
}
artists, err := cmt.Get(flacvorbis.FIELD_ARTIST)
if err != nil {
return nil, err
}
albumArtists, err := cmt.Get("ALBUMARTIST")
if err != nil {
return nil, err
}
comments, err := cmt.Get("COMMENT")
if err != nil {
return nil, err
}
var comment *string
if len(comments) > 0 {
comment = &comments[0]
}
metadata := &Metadata{
Title: title,
Artist: artists,
Album: album,
AlbumArtist: albumArtists,
Comment: comment,
}
return metadata, nil
}
func findVobisMetadata(f flac.File) (*flacvorbis.MetaDataBlockVorbisComment, error) {
for _, meta := range f.Meta {
if meta.Type == flac.VorbisComment {
return flacvorbis.ParseFromMetaDataBlock(*meta)
}
}
return nil, nil
}
func updateFlacMetadata(m Metadata, input, output string) error { func updateFlacMetadata(m Metadata, input, output string) error {
f, err := flac.ParseFile(input) f, err := flac.ParseFile(input)
if err != nil { if err != nil {
@@ -36,13 +113,25 @@ func updateFlacMetadata(m Metadata, input, output string) error {
func createVorbisMetaBlock(m Metadata) flacvorbis.MetaDataBlockVorbisComment { func createVorbisMetaBlock(m Metadata) flacvorbis.MetaDataBlockVorbisComment {
vorbisMeta := flacvorbis.New() vorbisMeta := flacvorbis.New()
vorbisMeta.Add(flacvorbis.FIELD_TITLE, m.Title) if m.Title != nil {
vorbisMeta.Add(flacvorbis.FIELD_ALBUM, m.Album) vorbisMeta.Add(flacvorbis.FIELD_TITLE, *m.Title)
vorbisMeta.Add("COMMENT", m.Comment) }
vorbisMeta.Add("TRACKNUMBER", strconv.Itoa(m.Track))
vorbisMeta.Add("TOTALTRACKS", strconv.Itoa(m.TotalTracks)) if m.Album != nil {
vorbisMeta.Add("DISCNUMBER", strconv.Itoa(m.Disc)) vorbisMeta.Add(flacvorbis.FIELD_ALBUM, *m.Album)
vorbisMeta.Add("TOTALDISCS", strconv.Itoa(m.TotalDiscs)) }
if m.Comment != nil {
vorbisMeta.Add("COMMENT", *m.Comment)
}
if m.Track != 0 {
vorbisMeta.Add("TRACKNUMBER", strconv.Itoa(m.Track))
}
if m.TotalTracks != 0 {
vorbisMeta.Add("TOTALTRACKS", strconv.Itoa(m.TotalTracks))
}
for _, artist := range m.Artist { for _, artist := range m.Artist {
vorbisMeta.Add(flacvorbis.FIELD_ARTIST, artist) vorbisMeta.Add(flacvorbis.FIELD_ARTIST, artist)

View File

@@ -23,7 +23,6 @@ func Scan(filePath string) {
fmt.Printf("Album: %s\n", info.Album) fmt.Printf("Album: %s\n", info.Album)
fmt.Printf("Album Artist: %s\n", info.AlbumArtist) fmt.Printf("Album Artist: %s\n", info.AlbumArtist)
fmt.Printf("Track: %d/%d\n", info.Track, info.TotalTracks) fmt.Printf("Track: %d/%d\n", info.Track, info.TotalTracks)
fmt.Printf("Disc: %d/%d\n", info.Disc, info.TotalDiscs)
fmt.Printf("Comment: %s\n", info.Comment) fmt.Printf("Comment: %s\n", info.Comment)
sortPath := pathForFile(filePath, *info) sortPath := pathForFile(filePath, *info)

View File

@@ -61,33 +61,33 @@ func sortSong(src, dst string, updateMeta bool) error {
return nil return nil
} }
func sanitizeName(name string) *string { func sanitizeName(name *string) *string {
if name == "" { if name == nil || *name == "" {
return nil return nil
} }
re := regexp.MustCompile(`[<>:"/\\|?*\x00-\x1F]`) re := regexp.MustCompile(`[<>:"/\\|?*\x00-\x1F]`)
name = re.ReplaceAllString(name, "_") dName := re.ReplaceAllString(*name, "_")
name = strings.Trim(name, " .") dName = strings.Trim(dName, " .")
if name == "" { if dName == "" {
return nil return nil
} }
return &name return &dName
} }
func getArtistName(m metadata.Metadata) string { func getArtistName(m metadata.Metadata) string {
var artist *string var artist *string
if len(m.Artist) > 0 { if len(m.Artist) > 0 {
artist = sanitizeName(m.Artist[0]) artist = sanitizeName(&m.Artist[0])
} }
if artist == nil && len(m.AlbumArtist) > 0 { if artist == nil && len(m.AlbumArtist) > 0 {
if aa := m.AlbumArtist[0]; aa != "" { if aa := m.AlbumArtist[0]; aa != "" {
artist = sanitizeName(aa) artist = sanitizeName(&aa)
} }
} }
@@ -109,7 +109,8 @@ func getAlbumName(m metadata.Metadata) string {
func getTitle(src string, m metadata.Metadata) string { func getTitle(src string, m metadata.Metadata) string {
title := sanitizeName(m.Title) title := sanitizeName(m.Title)
if title == nil { if title == nil {
return *sanitizeName(strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))) filename := strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
return *sanitizeName(&filename)
} }
return *title return *title
} }