๐Ÿฏ ๐——๐—ฒ๐—ฐ๐—ถ๐˜€๐—ถ๐—ผ๐—ป๐˜€ ๐—•๐—ฒ๐—ต๐—ถ๐—ป๐—ฑ ๐—ฎ ๐— ๐˜‚๐˜€๐—ถ๐—ฐ ๐— ๐—ฎ๐˜๐—ฐ๐—ต ๐—ฆ๐—ฐ๐—ผ๐—ฟ๐—ฒ

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:

Each factor gets a weight. I made three specific design decisions to make this work.

  1. 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.

  1. 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.

  1. 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