Restored recommendations based on acoustic similarities (using musicnn), fixes #301

This commit is contained in:
emeric
2026-06-02 08:32:43 +02:00
parent 1524106124
commit eb7f65878f
227 changed files with 10324 additions and 4673 deletions
@@ -49,6 +49,7 @@
#include "steps/ScanStepCheckForRemovedFiles.hpp"
#include "steps/ScanStepCompact.hpp"
#include "steps/ScanStepComputeClusterStats.hpp"
#include "steps/ScanStepExtractMusicNNEmbeddings.hpp"
#include "steps/ScanStepOptimize.hpp"
#include "steps/ScanStepRemoveOrphanedDbEntries.hpp"
#include "steps/ScanStepScanFiles.hpp"
@@ -123,6 +124,10 @@ namespace lms::scanner
settings->allowArtistMBIDFallback = scanSettings->getAllowMBIDArtistMerge();
settings->artistImageFallbackToRelease = scanSettings->getArtistImageFallbackToReleaseField();
settings->extractMusicNNEmbeddings = scanSettings->getRecommendationEngineType() == db::ScanSettings::RecommendationEngineType::AudioSimilarity;
settings->musicnnModelPath = core::Service<core::IConfig>::get()->getPath("musicnn-model-path", "/usr/share/lms/models/MSD_musicnn_embedding.onnx");
settings->musicnnMaxPatchCountPerTrack = core::Service<core::IConfig>::get()->getULong("musicnn-max-patch-count-per-track", 20);
// TODO, store this in DB + expose in UI
settings->skipDuplicateTrackMBID = core::Service<core::IConfig>::get()->getBool("scanner-skip-duplicate-mbid", false);
@@ -164,6 +169,8 @@ namespace lms::scanner
, _jobScheduler{ core::createJobScheduler("Scanner", getScannerThreadCount()) }
, _cachePath{ cachePath }
{
LMS_LOG(DBUPDATER, INFO, "Starting service...");
_ioService.setThreadCount(1);
LMS_LOG(DBUPDATER, INFO, "Using " << _jobScheduler->getThreadCount() << " thread(s) for jobs");
@@ -186,6 +193,8 @@ namespace lms::scanner
refreshScanSettings();
start();
LMS_LOG(DBUPDATER, INFO, "Service started!");
}
ScannerService::~ScannerService()
@@ -389,7 +398,7 @@ namespace lms::scanner
}
refreshTracingLoggerStats();
LMS_LOG(DBUPDATER, INFO, "Scan " << (_abortScan ? "aborted" : "complete") << ". Changes = " << stats.getChangesCount() << " (added = " << stats.additions << ", removed = " << stats.deletions << ", updated = " << stats.updates << ", failures = " << stats.failures << "), Not changed = " << stats.skips << ", Scanned = " << stats.scans << " (errors = " << stats.errorsCount << "), features fetched = " << stats.featuresFetched << ", duplicates = " << stats.duplicates.size());
LMS_LOG(DBUPDATER, INFO, "Scan " << (_abortScan ? "aborted" : "complete") << ". Changes = " << stats.getChangesCount() << " (added = " << stats.additions << ", removed = " << stats.deletions << ", updated = " << stats.updates << ", failures = " << stats.failures << "), Not changed = " << stats.skips << ", Scanned = " << stats.scans << " (errors = " << stats.errorsCount << "), audio features extracted = " << stats.featureExtractions << ", duplicates = " << stats.duplicates.size());
{
auto transaction{ _db.getTLSSession().createReadTransaction() };
@@ -518,6 +527,10 @@ namespace lms::scanner
_scanSteps.emplace_back(std::make_unique<ScanStepOptimize>(params));
_scanSteps.emplace_back(std::make_unique<ScanStepComputeClusterStats>(params));
_scanSteps.emplace_back(std::make_unique<ScanStepCheckForDuplicatedFiles>(params));
// Audio extraction scan step must be last as it is the most long running
if (_settings.extractMusicNNEmbeddings)
_scanSteps.emplace_back(std::make_unique<ScanStepExtractMusicNNEmbeddings>(params, _settings.musicnnModelPath, _settings.musicnnMaxPatchCountPerTrack));
}
void ScannerService::notifyInProgress(const ScanStepStats& stepStats)