What sounds like this — including what you don’t own.
A public commons of CLAP audio embeddings: one 512-float vector per recording, keyed on a hash any tool can reproduce from the audio. A tool that manages music its user owns can ask what sounds like a track and be shown recordings from every library that has plugged in. What your library contributes is what others can be shown, and the reverse.
from clapback_client import Corpus
for n in Corpus().similar(vector, limit=10): # nearest recordings, every library, ~3 ms
print(n["similarity"], n["recording_mbid"] # a MusicBrainz recording you can open —
or n["fingerprint_hash"]) # or the hash, when nobody has named it yet
Corpus().contribute(fingerprint_hash=key, embedding=vector,
pipeline_version=PIPELINE_VERSION, client_id=client_id)
Why plug your tool in
Recommendations past the edge of one library
A streaming service recommends from a catalogue it holds. A tool that manages music
its user owns has none, so its suggestions stop at the last track. /v1/similar
answers in 3 ms over every library that has plugged in, and
90% of results are a MusicBrainz recording a person can open.
The rest are hashes, shown as hashes. It says sounds like, never will
like; where to hear it is your tool's call.
Somewhere to submit to again
beets and Picard shipped exactly this fetch-and-submit pair and lost it when AcousticBrainz closed in 2022. This corpus carries embeddings — reconcilable between contributors — not the estimates that could not be. What your users contribute is what everyone's users can be shown.
Skip the recompute
A hit is 512 floats. A miss is seconds of CPU and a 600 MB model — minutes per album on a laptop, longer on a Pi. Look up first; run the model only for what nobody has computed. This is the smaller reason: the saving needs the commons to already hold your track, and the catalogue above does not.
What plugging in takes
- Fingerprint the audio and hash it canonically. SHA256 of the AcoustID fingerprint as chromaprint returned it — not as your database stored it.
- Produce the vector through a declared pipeline. The reference is
clapback-embed; your own pipeline identity is allowed, at 512 dimensions. - Look up before you contribute. A repeat submission is recorded as agreement, and one install agreeing with itself is not evidence.
- Send
client_idandpipeline_version. A random UUID minted on first contribution; the identity of everything that can move a vector.
row = corpus.lookup(key, pipeline_version)
if row is not None:
vector = row["embedding"] # the commons already had it — skip the model
else:
vector = my_embedder(path) # your pipeline, declared by pipeline_version
corpus.contribute(fingerprint_hash=key, embedding=vector,
pipeline_version=pipeline_version, client_id=client_id)
Already plugged in
beets
absubmit reborn. Look up, else embed; contribute if you say so;
beet clapback-similar.
Picard
Right-click: look up, name, contribute. Works with no embedder installed, and says so.
Familiar
The self-hosted music server this grew out of. The first contributor, and so far the only one.
clapback-cli
The reference client: index a directory, search it by description, find duplicates, ask what sounds like a track — including what you don’t own — and contribute.
Explore the corpus
Every point is a recording; points that sit together sounded alike to the model. Click one and it becomes a name — resolved in your browser from MusicBrainz, because the commons itself holds no titles — with the twelve recordings that sound most like it. Paste a MusicBrainz recording, or a hash, to jump to it.
Open the explorer →The corpus, dated
Almost every vector here came from one library, so what the corpus can show you today is one collection's worth. The mechanism for finding out whether independent contributors agree is in place ahead of the evidence, on purpose — and a second contributor is the single most valuable thing that could happen to it. For that contributor, every row here they do not hold is already a recording they can be shown; the lookup hit rate, which needs overlap, is the part that has to wait.
Every row declares the pipeline that produced it and is keyed on a hash any client can reproduce from the audio. The corpus is smaller than it has ever been, and the first version where a disagreement is about the recording rather than about whose code ran.
How it keeps its word
One implementation, pinned
Everyone runs clapback-embed. Front-end, windowing, pooling, checkpoint
and precision compose into one identity string that travels with every vector.
A hash, never a filename
The corpus receives the SHA256 of a fingerprint and cannot recover a title, an artist or a path from it. Naming a row is a claim its contributor makes, counted per client — and a name is a MusicBrainz recording, which is a title and an artist one lookup away, so it goes out under the same switch as the vector.
First vector wins, the rest are measured
A repeat contribution is compared, not overwritten. The same audio on two architectures agrees to 6.6e-11; two rips of one recording differ by 3e-4. That gap is the room agreement has.
Asserted, not proven; reported, not ruled
The server believes the pipeline you declare. No threshold calls a vector trustworthy — you are told how many independent submissions matched, and how closely.