diff --git a/core/ffmpeg/ffmpeg.go b/core/ffmpeg/ffmpeg.go index ea86978b..0b8a927a 100644 --- a/core/ffmpeg/ffmpeg.go +++ b/core/ffmpeg/ffmpeg.go @@ -23,6 +23,7 @@ type FFmpeg interface { Probe(ctx context.Context, files []string) (string, error) CmdPath() (string, error) IsAvailable() bool + Version() string } func New() FFmpeg { @@ -84,6 +85,24 @@ func (e *ffmpeg) IsAvailable() bool { return err == nil } +// Version executes ffmpeg -version and extracts the version from the output. +// Sample output: ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers +func (e *ffmpeg) Version() string { + cmd, err := ffmpegCmd() + if err != nil { + return "N/A" + } + out, err := exec.Command(cmd, "-version").CombinedOutput() // #nosec + if err != nil { + return "N/A" + } + parts := strings.Split(string(out), " ") + if len(parts) < 3 { + return "N/A" + } + return parts[2] +} + func (e *ffmpeg) start(ctx context.Context, args []string) (io.ReadCloser, error) { log.Trace(ctx, "Executing ffmpeg command", "cmd", args) j := &ffCmd{args: args} diff --git a/scanner/metadata/ffmpeg/ffmpeg.go b/scanner/metadata/ffmpeg/ffmpeg.go index 1139a501..04e7f690 100644 --- a/scanner/metadata/ffmpeg/ffmpeg.go +++ b/scanner/metadata/ffmpeg/ffmpeg.go @@ -49,6 +49,10 @@ func (e *Extractor) CustomMappings() metadata.ParsedTags { } } +func (e *Extractor) Version() string { + return e.ffmpeg.Version() +} + func (e *Extractor) extractMetadata(filePath, info string) (metadata.ParsedTags, error) { tags := e.parseInfo(info) if len(tags) == 0 { diff --git a/scanner/metadata/metadata.go b/scanner/metadata/metadata.go index 54d37982..568ee044 100644 --- a/scanner/metadata/metadata.go +++ b/scanner/metadata/metadata.go @@ -22,6 +22,7 @@ import ( type Extractor interface { Parse(files ...string) (map[string]ParsedTags, error) CustomMappings() ParsedTags + Version() string } var extractors = map[string]Extractor{} @@ -30,6 +31,12 @@ func RegisterExtractor(id string, parser Extractor) { extractors[id] = parser } +func LogExtractors() { + for id, p := range extractors { + log.Debug("Registered metadata extractor", "id", id, "version", p.Version()) + } +} + func Extract(files ...string) (map[string]Tags, error) { p, ok := extractors[conf.Server.Scanner.Extractor] if !ok { diff --git a/scanner/metadata/taglib/taglib.go b/scanner/metadata/taglib/taglib.go index d29fb286..20403189 100644 --- a/scanner/metadata/taglib/taglib.go +++ b/scanner/metadata/taglib/taglib.go @@ -34,6 +34,10 @@ func (e *Extractor) CustomMappings() metadata.ParsedTags { } } +func (e *Extractor) Version() string { + return Version() +} + func (e *Extractor) extractMetadata(filePath string) (metadata.ParsedTags, error) { tags, err := Read(filePath) if err != nil { diff --git a/scanner/metadata/taglib/taglib_wrapper.cpp b/scanner/metadata/taglib/taglib_wrapper.cpp index c28f4643..a3c46e65 100644 --- a/scanner/metadata/taglib/taglib_wrapper.cpp +++ b/scanner/metadata/taglib/taglib_wrapper.cpp @@ -21,6 +21,13 @@ char has_cover(const TagLib::FileRef f); +static char TAGLIB_VERSION[16]; + +char* taglib_version() { + snprintf((char *)TAGLIB_VERSION, 16, "%d.%d.%d", TAGLIB_MAJOR_VERSION, TAGLIB_MINOR_VERSION, TAGLIB_PATCH_VERSION); + return (char *)TAGLIB_VERSION; +} + int taglib_read(const FILENAME_CHAR_T *filename, unsigned long id) { TagLib::FileRef f(filename, true, TagLib::AudioProperties::Fast); diff --git a/scanner/metadata/taglib/taglib_wrapper.go b/scanner/metadata/taglib/taglib_wrapper.go index 81afe5fc..067710f9 100644 --- a/scanner/metadata/taglib/taglib_wrapper.go +++ b/scanner/metadata/taglib/taglib_wrapper.go @@ -25,6 +25,10 @@ import ( const iTunesKeyPrefix = "----:com.apple.itunes:" +func Version() string { + return C.GoString(C.taglib_version()) +} + func Read(filename string) (tags map[string][]string, err error) { // Do not crash on failures in the C code/library debug.SetPanicOnFault(true) diff --git a/scanner/metadata/taglib/taglib_wrapper.h b/scanner/metadata/taglib/taglib_wrapper.h index 8f0a8212..05aed693 100644 --- a/scanner/metadata/taglib/taglib_wrapper.h +++ b/scanner/metadata/taglib/taglib_wrapper.h @@ -17,6 +17,7 @@ extern void go_map_put_int(unsigned long id, char *key, int val); extern void go_map_put_lyrics(unsigned long id, char *lang, char *val); extern void go_map_put_lyric_line(unsigned long id, char *lang, char *text, int time); int taglib_read(const FILENAME_CHAR_T *filename, unsigned long id); +char* taglib_version(); #ifdef __cplusplus } diff --git a/scanner/tag_scanner.go b/scanner/tag_scanner.go index 9195544f..fc01ce8a 100644 --- a/scanner/tag_scanner.go +++ b/scanner/tag_scanner.go @@ -38,6 +38,7 @@ func NewTagScanner(rootFolder string, ds model.DataStore, playlists core.Playlis ds: ds, cacheWarmer: cacheWarmer, } + metadata.LogExtractors() return s } diff --git a/tests/mock_ffmpeg.go b/tests/mock_ffmpeg.go index 31ac7d9a..2d5ef8ac 100644 --- a/tests/mock_ffmpeg.go +++ b/tests/mock_ffmpeg.go @@ -64,6 +64,10 @@ func (ff *MockFFmpeg) CmdPath() (string, error) { return "ffmpeg", nil } +func (ff *MockFFmpeg) Version() string { + return "1.0" +} + func (ff *MockFFmpeg) Read(p []byte) (n int, err error) { ff.lock.Lock() defer ff.lock.Unlock()