Fallback extracting tags using ffmpeg

This commit is contained in:
Deluan
2022-12-20 12:25:47 -05:00
committed by Deluan Quintão
parent abd3274250
commit 92b42b35b3
10 changed files with 148 additions and 74 deletions
+33 -6
View File
@@ -12,6 +12,8 @@ import (
"io"
"os"
"path/filepath"
"reflect"
"runtime"
"strings"
"time"
@@ -19,6 +21,7 @@ import (
"github.com/disintegration/imaging"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/core/ffmpeg"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/resources"
@@ -31,13 +34,14 @@ type Artwork interface {
Get(ctx context.Context, id string, size int) (io.ReadCloser, error)
}
func NewArtwork(ds model.DataStore, cache cache.FileCache) Artwork {
return &artwork{ds: ds, cache: cache}
func NewArtwork(ds model.DataStore, cache cache.FileCache, ffmpeg ffmpeg.FFmpeg) Artwork {
return &artwork{ds: ds, cache: cache, ffmpeg: ffmpeg}
}
type artwork struct {
ds model.DataStore
cache cache.FileCache
ds model.DataStore
cache cache.FileCache
ffmpeg ffmpeg.FFmpeg
}
func (a *artwork) Get(ctx context.Context, id string, size int) (io.ReadCloser, error) {
@@ -95,6 +99,7 @@ func (a *artwork) extractAlbumImage(ctx context.Context, artID model.ArtworkID)
fromExternalFile(al.ImageFiles, "albumart.png", "albumart.jpg", "albumart.jpeg", "albumart.webp"),
fromExternalFile(al.ImageFiles, "front.png", "front.jpg", "front.jpeg", "front.webp"),
fromTag(al.EmbedArtPath),
fromFFmpegTag(ctx, a.ffmpeg, al.EmbedArtPath),
fromPlaceholder(),
)
}
@@ -112,6 +117,7 @@ func (a *artwork) extractMediaFileImage(ctx context.Context, artID model.Artwork
return extractImage(ctx, artID,
fromTag(mf.Path),
fromFFmpegTag(ctx, a.ffmpeg, mf.Path),
a.fromAlbum(ctx, mf.AlbumCoverArtID()),
)
}
@@ -135,8 +141,9 @@ func (a *artwork) resizedFromOriginal(ctx context.Context, artID model.ArtworkID
usePng := strings.ToLower(filepath.Ext(path)) == ".png"
r, err = resizeImage(r, size, usePng)
if err != nil {
log.Warn("Could not resize image", "artID", artID, "size", size, err)
r, path := fromPlaceholder()()
return r, path, err
return r, path, nil
}
return r, fmt.Sprintf("%s@%d", path, size), nil
}
@@ -145,7 +152,7 @@ func extractImage(ctx context.Context, artID model.ArtworkID, extractFuncs ...fu
for _, f := range extractFuncs {
r, path := f()
if r != nil {
log.Trace(ctx, "Found artwork", "artID", artID, "path", path)
log.Trace(ctx, "Found artwork", "artID", artID, "path", path, "from", getFunctionName(f))
return r, path
}
}
@@ -153,6 +160,13 @@ func extractImage(ctx context.Context, artID model.ArtworkID, extractFuncs ...fu
return nil, ""
}
func getFunctionName(i interface{}) string {
name := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
name = strings.TrimPrefix(name, "github.com/navidrome/navidrome/core.")
name = strings.TrimSuffix(name, ".func1")
return name
}
// This is a bit unoptimized, but we need to make sure the priority order of validNames
// is preserved (i.e. png is better than jpg)
func fromExternalFile(files string, validNames ...string) func() (io.ReadCloser, string) {
@@ -199,6 +213,19 @@ func fromTag(path string) func() (io.ReadCloser, string) {
}
}
func fromFFmpegTag(ctx context.Context, ffmpeg ffmpeg.FFmpeg, path string) func() (io.ReadCloser, string) {
return func() (io.ReadCloser, string) {
if path == "" {
return nil, ""
}
r, err := ffmpeg.ExtractImage(ctx, path)
if err != nil {
return nil, ""
}
return r, path
}
}
func fromPlaceholder() func() (io.ReadCloser, string) {
return func() (io.ReadCloser, string) {
r, _ := resources.FS().Open(consts.PlaceholderAlbumArt)