Find Duplicate Audio (Essentia HPCP)

Select a folder to scan. Uses Essentia.js HPCP (Harmonic Pitch Class Profile) chroma features to find duplicate and similar audio files — especially effective for cover versions and harmonic similarities.

Supported: MP3, WAV, FLAC, OGG, M4A, AAC
Ready
0 items

📖 How Audio Duplicate Detection Works (Essentia HPCP)

A complete guide to finding duplicate and similar audio files using harmonic fingerprinting. Covers the Essentia.js HPCP algorithm, the Similarity Threshold slider, the custom player, and every button in the interface.

100% Private — Your Audio Files Never Leave Your Computer Everything runs inside your browser using Essentia.js WASM and the Web Audio API. No uploads, no accounts, no tracking. Close the tab and all data is gone.

🎵 What This Tool Does

This tool finds duplicate and similar audio files by analysing the actual harmonic content of each file — not file names or metadata. It extracts a Harmonic Pitch Class Profile (HPCP) from each audio file using Essentia.js and compares profiles using cosine similarity, capturing the chord and pitch class structure that makes two recordings sound like the same song.

Unlike image duplicate finders, which compare visual pixels, HPCP audio comparison works in the harmonic domain. The tool can detect the same song re-encoded at a different bitrate, performed in a different key, or covered with different instrumentation — as long as the underlying chord progression and pitch content are similar.

Harmonic Fingerprinting

Uses Essentia.js to extract 12-bin Harmonic Pitch Class Profiles — one per overlapping frame — capturing the chord and pitch class structure of the audio.

Cosine Similarity Matching

Compares HPCP vector sequences using cosine similarity. A score near 1.0 = nearly identical harmonic content. The slider controls how strict matching is.

Runs in Background

Audio decoding and HPCP extraction continue even when you switch browser tabs — no pausing, unlike video scanning. Essentia.js WASM initialises once and is reused for every file.

Built-In Audio Player

Every card has a custom play/pause/seek/mute player. Playing one track automatically pauses all others.

🧠 How the Essentia HPCP Algorithm Works

The algorithm uses Essentia.js — a WebAssembly-compiled C++ music analysis library — to extract Harmonic Pitch Class Profiles (HPCP) from each audio file. Here is what happens step by step when you scan a file:

  1. Load Essentia.js WASM

    Before any file is processed, Sakarto initialises the Essentia.js WebAssembly module. This downloads the WASM binary from cdn.jsdelivr.net and compiles it in the browser. The process takes 1–3 seconds and happens once per session. The progress bar stays at 0% until initialisation completes.

  2. Decode Each Audio File at 44,100 Hz

    Each file is decoded using AudioContext.decodeAudioData() at the native 44,100 Hz sample rate. Only the left channel is used. Files larger than 100 MB are skipped.

  3. Split Into Overlapping Frames (4,096 samples, hop 2,048)

    The decoded audio stream is divided into overlapping 4,096-sample frames with a 2,048-sample hop, giving ~50% overlap. At 44,100 Hz each frame is about 93 ms. More overlap means finer temporal resolution and more precise harmonic tracking than hash-based approaches.

  4. Extract HPCP via extractor.hpcpExtractor()

    For each frame, Essentia's built-in hpcpExtractor(frame, sampleRate, false) method computes a 12-element Harmonic Pitch Class Profile — one bin per semitone of the chromatic scale (C, C#, D…B). This captures the relative harmonic energy at each pitch class, making the profile robust against loudness differences, bitrate changes, and minor re-encoding.

  5. Store the Full HPCP Sequence

    One 12-element vector is produced per frame. A 3-minute song at hop 2,048 produces roughly 3,800 vectors. The full sequence is stored in memory for comparison. This uses more RAM than a compact hash, but captures harmonic progression over time rather than just an average.

  6. Compare Using Cosine Similarity

    To compare two files, their HPCP sequences are aligned (using the shorter length) and the average cosine similarity is computed frame by frame. Cosine similarity of 1.0 means identical harmonic content; 0.0 means completely orthogonal. If the average meets or exceeds the threshold set by the slider, the files are grouped as duplicates. A duration pre-check rejects pairs where one file is shorter than 50% of the other.

Why cosine similarity for HPCP? Cosine similarity measures the angle between two 12-dimensional chroma vectors, ignoring absolute energy. Two performances of the same chord progression produce near-identical HPCP vectors even if one is louder, quieter, or recorded on a different instrument. Identical harmonic content produces similarity 1.0; completely unrelated content approaches 0.0.

🎚️ Understanding the Similarity Threshold Slider

The slider labeled Similarity Threshold (50–95) controls how strictly two HPCP profiles must match to be grouped as duplicates. It is the most important control on this page. Higher values are stricter — cosine similarity of 1.0 means a perfect match.

High values (81–95) — Very strict

Only nearly identical files match. Use for exact duplicates, same file at different bitrates, or lossless vs. lossy exports of the same master. Very few false positives.

Medium values (66–80) — Balanced (default: 75)

Catches cover versions, different-bitrate re-encodes of the same master, and transposed recordings. The default of 75 is a good starting point for music libraries. Some false positives are possible for songs with the same chord progression.

Low values (50–65) — Loose

Groups files sharing broad harmonic character — same key, same genre, similar chord patterns. Useful for exploring harmonic relationships across a collection, but expect more false positives. Always review before deleting.

Re-clustering is instant. When you adjust the slider and release it, all already-computed HPCP sequences are re-compared using the new threshold immediately — no re-scanning needed. The WASM computation only runs once per session.
The slider uses a linear scale. Slider value 75 = cosine similarity ≥ 0.75. Each step of 1 is exactly 0.01 cosine units. The slider runs high-to-low where high = stricter — the opposite direction from Hamming distance sliders.

✅ What It Finds — and What It Might Miss

✅ Finds Well
  • The same track at different bitrates (e.g. 320k MP3 vs 128k MP3)
  • Lossless vs. lossy exports of the same master (WAV vs MP3)
  • Cover versions with the same chord progression
  • Transposed recordings (same song, different key)
  • Different arrangements sharing the same harmonic structure
  • Re-mastered versions with similar harmonic content
⚠️ May Struggle With
  • Spoken word, podcasts, sound effects (no harmonic pitch content)
  • Heavily distorted or processed recordings
  • Very short clips (under ~15 seconds)
  • Files with very different duration vs. their pair
  • Atonal or noise-based music
  • WASM load failure on slow or restricted networks
For spoken word, podcasts, and sound effects, use Meyda MFCC instead — Mel-Frequency Cepstral Coefficients capture timbral texture and work well for non-musical audio where there is no clear harmonic pitch content.

▶️ The Custom Audio Player

Every audio card has a built-in player. Here's how to use it:

All audio player controls and their functions
ControlWhat it does
▶️ Play buttonStarts playback. Automatically pauses any other playing track on the page.
⏸️ Pause buttonPauses playback. Audio position is remembered.
Progress barClick anywhere on the bar to seek to that position. Drag left/right to scrub.
🔊 / 🔇 Mute buttonMutes or unmutes this individual track.
🔇 Audio (toolbar)Mutes or unmutes all audio on the page at once.
Time displayShows current position / total duration (e.g. 1:23 / 3:45).
← / → arrow keysWhen the progress bar is focused, seeks backward or forward 5 seconds.
Exclusive playback. When you press play on any card, all other currently-playing tracks pause automatically. This makes it easy to audition multiple candidates from a duplicate group one by one.

📋 Step-by-Step: How to Use the Audio Duplicate Finder

Step 1

Select a Folder to Scan

Click 📁 Select Folder to Scan. A native folder picker opens (Chrome / Edge). Or drag and drop a folder onto the page. All audio files inside the folder and its subfolders are collected. If this is your first scan, allow 1–3 seconds for the Essentia.js WASM module to initialise before the progress bar advances.

Supported formats: MP3, WAV, FLAC, OGG, M4A, AAC. Files over 100 MB are skipped. Non-audio files are silently ignored.

HPCP extraction runs fully in the background — you can switch browser tabs freely. Unlike video scanning, the Web Audio API does not pause when the tab is hidden. Essentia.js WASM initialises once and is reused for every file in the session.
Step 2

Wait for the Scan

A progress bar shows how many files have been processed. Processing speed depends on file length and your CPU — expect roughly 2–5 seconds per track for typical music files, as HPCP extraction at 44,100 Hz is more CPU-intensive than hash-based methods. Duplicate groups appear live as they're found — you don't have to wait for the full scan to finish before reviewing results.

Click Stop at any time to halt the scan. Results found so far remain visible.

Step 3

Adjust the Similarity Threshold

After scanning, use the Similarity Threshold slider to control matching sensitivity. Moving the slider re-groups all already-processed HPCP sequences instantly — no re-scanning is needed.

  • Start at the default of 75 (balanced — good for cover versions and bitrate differences)
  • Raise to 80–85 if you see false positives (unrelated songs grouped)
  • Lower to 60–65 if expected duplicates are not appearing
Step 4

Review the Groups

Results appear in numbered groups. Each group contains audio files that the algorithm considers similar. Use the built-in players to listen to each file before making decisions.

  • Click a card to select it (blue border)
  • Ctrl+Click (Cmd+Click on Mac) to add to the compare list (purple border)
  • Click the 🔍 icon on hover to open a full-screen preview with the modal-size player
  • Right-click any card for the context menu
  • Click & drag on empty space to box-select multiple cards
Step 5

Compare Files Side-by-Side

Ctrl+Click two or more cards, then click ⚖️ Compare in the toolbar. A modal opens showing each file with its own modal-size player, file metadata (duration, size, type, path), and a similarity percentage. For 3+ files, a full pairwise similarity matrix is shown.

Each file in the compare modal also has Copy Name, Move, and Delete buttons for quick actions without closing the modal.

Step 6

Move, Delete, or Copy

Select files and use the toolbar. With Queue Mode on (recommended), files are staged for review first:

📋 CopyCopy filename(s) to clipboard
📂 MoveStage for move to Audio-Duplicates folder
🗑️ DeleteStage for permanent deletion
⚖️ CompareView and listen side-by-side
Step 7

Queue Mode — Review Before You Commit

Queue Mode (enabled by default) stages files instead of acting immediately. Switch to the Move Queue or Delete Queue tab in the sidebar. Review the queued files, listen to them, remove any you change your mind about, then click Move All Files or Delete All Files to execute.

The default destination folder for Move is Audio-Duplicates, created inside the scanned folder. You can rename it in the queue input field.

🏛️ Quick Reference — All Controls

All toolbar buttons and keyboard shortcuts for the audio duplicate finder
Button / ControlWhat it does
🔄 New SearchReload the page and start a fresh scan
📋 Copy (N)Copy selected filenames to clipboard. N = count.
📂 Move (N)Move selected files or stage them in Move Queue
🗑️ Delete (N)Delete selected files or stage in Delete Queue
✕ Deselect AllRemove selection from all cards
⚖️ Compare (N)Open compare modal for Ctrl+clicked files. Needs 2+.
🔇 AudioMute / unmute all audio players on the page
Queue Mode checkboxStage files for review before executing. Recommended on.
Similarity Threshold sliderControls matching strictness (50–95, higher = stricter). Re-clusters instantly on release without re-scanning.
Click cardSelect / deselect the file
Ctrl + Click cardAdd / remove from compare list (purple border)
Click & drag (empty area)Box-select multiple cards
Ctrl + dragAdd to existing selection with box
Right-click cardContext menu: Copy / Move / Delete / Compare
🔍 hover icon on cardOpen full-size preview with modal-size player
▶️ on card playerPlay audio. Pauses all other players on page.

💡 Tips for Best Results

Back Up First

Always back up your audio library before deleting anything. Deleted files bypass the recycle bin and cannot be recovered.

Listen Before Deleting

Play both tracks using the built-in players before removing one. The algorithm is good but not perfect — always verify by ear for important files.

Start at Default 75

The default of 75 is well-calibrated for most music. Raise toward 85 if you see unrelated songs grouped. Lower toward 65 if expected duplicates are not appearing.

Compare the Metadata

In the Compare modal, check file size and duration. A larger file is usually higher quality. Keep the FLAC or high-bitrate version; delete the compressed copy.

Move, Don't Delete

Use Move to an "Audio-Duplicates" folder rather than deleting outright. Review the moved files after a few days before permanently removing them.

Scan One Genre at a Time

For very large libraries, scan by genre or artist subfolder. This reduces false positives from tracks with similar instrumentation and keeps groups manageable.

No Matches? Try a Lower Threshold or Different Algorithm

If Essentia HPCP finds nothing, lower the threshold toward 60–65. For spoken word or sound effects, try Meyda MFCC. For exact copy detection without WASM, use Chromaprint.

⚠️ Known Limitations

WASM initialisation adds startup latency.

Essentia.js loads from CDN and compiles in the browser before the first file can be processed. This 1–10 second pause is unavoidable and happens once per session. If it never completes, check that your network can reach cdn.jsdelivr.net — some firewalls and ad-blockers block CDN requests.

No undo for file deletion.

The File System Access API bypasses the OS recycle bin entirely. Deleted audio files are gone permanently. Queue Mode exists for exactly this reason — always review before executing.

Higher memory usage than hash-based methods.

HPCP stores a full array of 12-element vectors per file (one per frame). For very large libraries, RAM usage is significantly higher than compact hash methods. Scan in subfolders rather than entire drives.

Single folder at a time.

You can't scan two separate folders in one session. Workaround: scan their common parent directory so both are included in the same scan.

Move and Delete require Chrome or Edge.

The File System Access API is only available in Chrome 86+ and Edge 86+. Firefox and Safari can scan and display results but cannot move or delete files. Use "Download List" to export results in those browsers.

Not designed for spoken word or sound effects.

HPCP relies on harmonic pitch structure. Audio without clear pitch content (speech, noise, drums, ambient) produces near-random chroma vectors. Use Meyda MFCC for those file types.

🔒 Privacy & Security

Only the Essentia.js library loads from the network. Three script files are loaded from cdn.jsdelivr.net at page load. After that, all audio decoding and HPCP computation run locally. Open DevTools → Network tab during a scan: zero outbound requests to any server.
No accounts, no cookies, no analytics. The only localStorage data is your Queue Mode preference. No file names, paths, or HPCP data are ever saved or transmitted.
Folder access is scoped and session-only. Browser permission covers only the folder you selected, lasts only while the tab is open, and can be revoked from browser site settings at any time.
Purely static — no backend. Sakarto is HTML, CSS, and JavaScript. There is no server-side component, database, or API endpoint receiving any data from you.

❓ Frequently Asked Questions

The progress bar is stuck at 0% and nothing is scanning. What's happening?
Sakarto is waiting for the Essentia.js WebAssembly module to download and compile. This normally takes 1–4 seconds on a fast connection. If it takes more than 15 seconds, the most likely cause is a firewall or ad-blocker blocking requests to cdn.jsdelivr.net. Try disabling your ad-blocker for this page, or open DevTools → Network and look for a blocked or failed request to Essentia. If the CDN is unreachable on your network, switch to Chromaprint — it's pure JavaScript, has no CDN dependency, and works completely offline.
Why is Essentia's threshold inverted? Higher = stricter feels backwards.
Chromaprint and Meyda measure distance (how different two fingerprints are), so lower threshold = fewer differences allowed = stricter. Essentia HPCP measures cosine similarity (how similar two HPCP vectors are), which is a value between 0 and 1 where 1 means identical. So a threshold of 0.9 means "the two files must be at least 90% harmonically similar" — very strict. A threshold of 0.5 means "accept anything 50% or more similar" — loose. The slider direction is different, but the logic is the same: move the slider toward strict to reduce false positives, loosen it to catch more approximate matches.
The same song in MP3 and FLAC isn't being grouped. Why?
Try lowering the Similarity Threshold slider toward 0.65–0.70. Lossless and lossy formats differ slightly in harmonic content because MP3 compression can alter the spectral envelope even though the music sounds the same to the ear. A threshold of 0.65–0.75 usually catches lossless vs. lossy pairs. Also confirm both files have similar duration — the duration pre-check silently excludes pairs where one file is shorter than 50% of the other.
Can Essentia HPCP find cover versions? How well does it work?
Yes — this is HPCP's core strength and what distinguishes it from Chromaprint and Meyda. A cover version that shares the same chord progression and melody will produce a similar 12-bin chroma profile regardless of what instrument performs it or how it was recorded. At threshold 0.65–0.75 you can reliably detect covers, live recordings, and alternate studio takes of the same song. Heavily rearranged covers or remixes with significantly different chord structures may score lower and require a threshold of 0.55–0.60 to appear. Always listen before deleting — songs in the same key with similar chord progressions can occasionally match even when they're different compositions.
Two different songs are being grouped together. How do I fix it?
Raise the Similarity Threshold slider (remember: higher = stricter for Essentia). At low threshold values, songs sharing a key or similar chord progressions can score high enough to appear as matches even when they're completely different compositions. Pop songs in C major, for example, often share enough harmonic content that their HPCP vectors are closer than you'd expect. Try raising the threshold to 0.80–0.85 if false positives are common. Always use the built-in player to audition both tracks before taking action.
Why is scanning slower than Chromaprint?
HPCP extraction at 44,100 Hz is more computationally intensive than Chromaprint's 11,025 Hz spectral hashing. Each frame requires computing a full FFT and mapping it to 12 pitch class bins. A typical 3-minute track takes 2–5 seconds. Add 1–4 seconds on first use for the WASM module to load and JIT-compile — this happens once per session and then stays cached. Closing other browser tabs frees up CPU and significantly speeds up scanning. Unlike video scanning, audio processing continues fully in the background regardless of tab focus.
What exactly is a Harmonic Pitch Class Profile, and why is it better for music than spectral fingerprinting?
A Harmonic Pitch Class Profile (HPCP) is a 12-element vector — one bin for each musical pitch class (C, C#, D, D#, E, F, F#, G, G#, A, A#, B) — that measures how strongly each note is present in a frame of audio. Two recordings of the same song will activate the same pitch class bins in similar proportions, regardless of what instrument is playing or how the audio was recorded. Chromaprint by contrast compares raw frequency band energy, which changes dramatically when the instrument changes. HPCP is instrument-agnostic; spectral fingerprinting is not. That's why HPCP finds covers and alternate recordings while Chromaprint misses them.
Does Essentia HPCP work for speech, podcasts, or sound effects?
Poorly — HPCP was designed for pitched musical content and extracts harmonic structure that simply doesn't exist in speech or non-pitched sounds. A podcast episode analysed with HPCP will produce a chroma vector dominated by noise rather than musical notes, making comparison unreliable. For speech, podcasts, and voice memos, use Chromaprint (good spectral match for re-encoded speech) or Meyda MFCC (specifically designed for timbral texture and is the standard in speech recognition research). For sound effects, Meyda MFCC is the better choice.
Does this work on Firefox or Safari?
Scanning, HPCP extraction, the built-in player, result display, and the Compare modal all work in Firefox and Safari. The limitation is Move and Delete, which require the File System Access API (Chrome 86+ and Edge 86+ only). In Firefox and Safari, scan and review results normally, then use Download List to export a report and manage files manually in your OS file manager.