feat: extract embedded album artwork during scans
Add a dedicated artwork cache directory and save embedded album art from audio tags during library scans. Prefer embedded artwork for album cover resolution while keeping sidecar image files as the fallback path.
This commit is contained in:
@@ -38,6 +38,7 @@ type Result struct {
|
||||
type Service struct {
|
||||
db *sql.DB
|
||||
mediaRoot string
|
||||
artworkRoot string
|
||||
mu sync.RWMutex
|
||||
status Status
|
||||
}
|
||||
@@ -78,8 +79,8 @@ type scannedTrack struct {
|
||||
ContentType string
|
||||
}
|
||||
|
||||
func NewService(db *sql.DB, mediaRoot string) *Service {
|
||||
return &Service{db: db, mediaRoot: mediaRoot}
|
||||
func NewService(db *sql.DB, mediaRoot, artworkRoot string) *Service {
|
||||
return &Service{db: db, mediaRoot: mediaRoot, artworkRoot: artworkRoot}
|
||||
}
|
||||
|
||||
func (s *Service) HasMediaFiles() bool {
|
||||
@@ -327,7 +328,13 @@ func (s *Service) scanFile(path string) (scannedItem, error) {
|
||||
artistID := hashID("artist", artistName)
|
||||
albumID := hashID("album", artistName, albumTitle, fmt.Sprintf("%d", year))
|
||||
trackID := hashID("track", path)
|
||||
coverArt := findCoverArt(filepath.Dir(path))
|
||||
coverArt := ""
|
||||
if err == nil {
|
||||
coverArt = s.extractEmbeddedCoverArt(metadata, albumID)
|
||||
}
|
||||
if coverArt == "" {
|
||||
coverArt = findCoverArt(filepath.Dir(path))
|
||||
}
|
||||
|
||||
return scannedItem{
|
||||
artist: scannedArtist{
|
||||
@@ -417,6 +424,44 @@ func findCoverArt(dir string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Service) extractEmbeddedCoverArt(metadata tag.Metadata, albumID string) string {
|
||||
if metadata == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
picture := metadata.Picture()
|
||||
if picture == nil || len(picture.Data) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if s.artworkRoot == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(s.artworkRoot, 0o755); err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
filename := albumID + coverExtension(picture.MIMEType)
|
||||
path := filepath.Join(s.artworkRoot, filename)
|
||||
if err := os.WriteFile(path, picture.Data, 0o644); err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func coverExtension(mimeType string) string {
|
||||
switch strings.ToLower(mimeType) {
|
||||
case "image/png":
|
||||
return ".png"
|
||||
case "image/webp":
|
||||
return ".webp"
|
||||
default:
|
||||
return ".jpg"
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) tryMarkStarted() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
Reference in New Issue
Block a user