Audio similarity engine: do not treat silent songs as errors

This commit is contained in:
emeric
2026-06-11 22:09:32 +02:00
parent 6825f6130d
commit 309c39a572
3 changed files with 28 additions and 8 deletions
@@ -48,10 +48,10 @@ namespace lms::recommendation
session.checkReadTransaction();
const db::TrackMusicNNEmbeddings::pointer embeddings{ db::TrackMusicNNEmbeddings::find(session, trackId) };
if (embeddings)
if (embeddings && !embeddings->getData().empty())
readEmbeddings(embeddings, vec);
return embeddings;
return embeddings && !embeddings->getData().empty();
}
void MusicNNEmbeddingProvider::visitVectors(db::Session& session, const std::function<void(db::TrackId, Vector&)>& visitor)
@@ -60,6 +60,8 @@ namespace lms::recommendation
Vector vec;
db::TrackMusicNNEmbeddings::find(session, [&](const db::TrackMusicNNEmbeddings::pointer& embeddings) {
if (embeddings->getData().empty())
return;
readEmbeddings(embeddings, vec);
visitor(embeddings->getTrackId(), vec);
});
@@ -40,7 +40,6 @@ namespace lms::recommendation
static constexpr std::size_t DimCount{ 200 };
using Vector = math::Vector<DimCount, FloatType>;
static std::size_t getCount(db::Session& session);
static bool getVector(db::Session& session, db::TrackId trackId, Vector& vec);
static void visitVectors(db::Session& session, const std::function<void(db::TrackId, Vector&)>& visitor);
};
@@ -92,6 +92,7 @@ namespace lms::scanner
ExtractMusicNNEmbeddingsJob& operator=(const ExtractMusicNNEmbeddingsJob&) = delete;
const TrackLocation& getTrackLocation() const { return _trackLocation; }
bool isSuccess() const { return _success; }
const audio::TrackMusicNNEmbeddings* getEmbeddings() const { return _embeddings ? &_embeddings.value() : nullptr; }
std::string_view getErrorMessage() const { return _errorMessage; }
@@ -107,6 +108,8 @@ namespace lms::scanner
if (result.patchCount > 0)
_embeddings.emplace(result.embeddings);
LMS_LOG(DBUPDATER, DEBUG, "MusicNN extraction complete for " << _trackLocation.trackPath << " (" << result.patchCount << " patches)");
_success = true;
}
catch (const audio::Exception& e)
{
@@ -116,6 +119,7 @@ namespace lms::scanner
const audio::IMusicNNEmbeddingExtractor& _extractor;
const TrackLocation _trackLocation;
bool _success{};
std::optional<audio::TrackMusicNNEmbeddings> _embeddings;
std::string _errorMessage;
};
@@ -125,11 +129,14 @@ namespace lms::scanner
db::Track::pointer track{ db::Track::find(session, assoc.trackId) };
assert(track);
db::TrackMusicNNEmbeddings::pointer entry{ session.create<db::TrackMusicNNEmbeddings>(track) };
if (assoc.embeddings)
{
std::vector<std::byte> blob(sizeof(audio::TrackMusicNNEmbeddings));
audio::trackMusicNNEmbeddingsToBlob(*assoc.embeddings, blob);
db::TrackMusicNNEmbeddings::pointer entry{ session.create<db::TrackMusicNNEmbeddings>(track) };
entry.modify()->setData(blob);
}
}
void writeEmbeddings(ScanContext& context, db::Session& session, TrackEmbeddingAssociationContainer& pendingAssocs, bool forceFullBatch)
{
@@ -202,11 +209,23 @@ namespace lms::scanner
{
const auto& extractJob{ static_cast<const ExtractMusicNNEmbeddingsJob&>(*job) };
if (extractJob.isSuccess())
{
if (const audio::TrackMusicNNEmbeddings * embeddings{ extractJob.getEmbeddings() })
{
pendingAssocs.push_back(TrackEmbeddingAssociation{ .trackId = extractJob.getTrackLocation().track, .embeddings = *embeddings });
}
else
{
LMS_LOG(DBUPDATER, INFO, "No patch extracted from " << extractJob.getTrackLocation().trackPath);
pendingAssocs.push_back(TrackEmbeddingAssociation{ .trackId = extractJob.getTrackLocation().track, .embeddings = std::nullopt });
}
}
else
{
addError<MusicNNEmbeddingsExtractError>(context, extractJob.getTrackLocation().trackPath, extractJob.getErrorMessage());
}
}
context.currentStepStats.processedElems += jobs.size();
writeEmbeddings(context, dbSession, pendingAssocs, true);