๐ฏ ๐๐ฒ๐ฐ๐ถ๐๐ถ๐ผ๐ป๐ ๐๐ฒ๐ต๐ถ๐ป๐ฑ ๐ฎ ๐ ๐๐๐ถ๐ฐ ๐ ๐ฎ๐๐ฐ๐ต ๐ฆ๐ฐ๐ผ๐ฟ๐ฒ
I build OTONAMI. It is a platform that connects independent artists to music curators.
A core part of the product is a match score. It tells an artist how well a track fits a specific curator. I recently turned this engine into an open source library called music-matching-patterns.
The score uses three factors:
- Genre score
- Mood score
- Audio score
Each factor gets a weight. I made three specific design decisions to make this work.
- Use recall instead of Jaccard similarity for genres
Most people use Jaccard similarity for sets. It calculates the intersection over the union. This penalizes broad curators.
If a curator likes ten genres and a track has one matching genre, Jaccard gives a low score. A broad curator should not be punished for having wide tastes.
I changed this. I score genre as recall. I check how many of the track's genres exist in the curator's list. If a track has two genres and the curator likes both, it is a perfect match.
- Use cosine similarity for audio features
I use cosine similarity for audio features like energy and danceability.
I learned that automatic BPM detection is often wrong. Errors in tempo can ruin a match score. I decided to show tempo in the text descriptions instead of using it in the math. This prevents bugs from breaking the matching logic.
- Handle missing data with a neutral score
Independent music often lacks data. Many tracks have no mood tags or audio features.
If data is missing, I assign a score of 0.5. This value is neutral. It does not help the score, but it does not hurt it. Absence of evidence is not evidence of a bad fit.
These are not complex algorithms. They are small guards that make the system reliable.
You can find the full open source code here.
Source: https://dev.to/satoshi_and_claude/three-decisions-behind-a-music-to-curator-matching-score-4903