trimmed down metadata & own extractor for vobis(flac)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user