A Rust-based audio fingerprinting CLI inspired by Shazam-style matching. It stores a reference track as a set of hashed spectral fingerprints, then identifies unknown clips by voting on the timing offset where the most fingerprints agree.
- Store reference songs into a local SQLite fingerprint database
- Recognize an unknown clip against everything stored
- Record the microphone (
listen) and identify what is playing - Show ranked candidates for a clip (
list-top-matches) - Manage the database from the CLI (
list-songs,remove-song,db-stats) - Layered TOML config (
/etc, user config, local config), with CLI flags overriding all of it - Optional clipping for reference indexing (
--clip-start,--clip-duration,--auto-clip) - Cross-platform: Linux and Windows (PowerShell helper scripts included)
- Rust (edition 2024, needs rustc 1.85+)
- SQLite via
rusqlite(bundled, no system SQLite library required) - Audio capture via
cpal(microphone input forlisten) - FFT via
rustfft - WAV I/O via
hound - TOML config via
serde+toml
- Read WAV samples
- Optionally clip to a sub-range of the track
- STFT spectrogram
- Peak extraction (constellation points)
- Pair each peak with nearby peaks to generate
(hash, anchor_time_ms)fingerprints - Insert song metadata + fingerprints into SQLite
- Read WAV samples
- STFT spectrogram
- Peak extraction
- Fingerprint generation (same hashing as above)
- Look up each hash in the database and record the time offset between query and match
- Rank candidate songs by whichever offset gets the most votes: a real match produces one dominant, consistent offset
choco install resonanceid-cliparu -S resonanceid-cli
# or
yay -S resonanceid-cliRequires Rust 1.85+ (edition 2024). Works on Linux, macOS and Windows — SQLite is compiled in via rusqlite's bundled feature, so no system SQLite development library is needed.
git clone https://github.com/rugbedbugg/ResonanceID-cli.git
cd ResonanceID-cli
cargo build --releaseThe binary is target/release/resonanceid-cli (resonanceid-cli.exe on Windows). During development, run it via cargo run --:
cargo run -- --helpArgs after
--go to the program, not to cargo.
resonanceid-cli store <wav_path> [name] [options]Aliases: remember, index.
The song name defaults to the full filename stem of <wav_path>; pass [name] to override it.
resonanceid-cli recognize <wav_path> [options]Prints the best match (if any), then every candidate ranked by score.
resonanceid-cli list-top-matches <wav_path> [options]Same options as recognize, just prints the ranked list without singling out a "best" match.
resonanceid-cli listen [--duration <seconds>] [options]Aliases: mic, record.
Records from the default input device, downmixes to mono, normalizes to 44.1 kHz, then recognizes against the database — same output as recognize. Recording length defaults to 10s; 10–15s works best since matching quality drops on very short clips.
resonanceid-cli import <folder> [options]Aliases: bulk.
Indexes every supported audio file directly inside <folder> (non-recursive): mp3, wav, flac, m4a, ogg, opus, wma, aac. Non-WAV files are converted via ffmpeg into a throwaway temp folder that is deleted when the run finishes — original files are never modified. The song name is the full filename stem. Unreadable files are skipped with a warning instead of aborting the run.
resonanceid-cli list-songs [--db <db_path>]
resonanceid-cli remove-song <song_id> [--db <db_path>]
resonanceid-cli db-stats [--db <db_path>]Every command also accepts --help for its own usage summary.
| Flag | Description |
|---|---|
--db <path> |
SQLite database file. Default: resonanceid-cli.db in the working directory. |
--config <path> |
Load config from this exact file instead of the default search paths. |
--no-config |
Skip config files entirely and use built-in defaults. |
| Flag | Default | Description |
|---|---|---|
--window-size <n> |
1024 |
STFT window size, in samples. |
--hop-size <n> |
512 |
STFT hop size, in samples. |
--anchor-window <n> |
5 |
How many following peaks each anchor peak pairs with. |
--threshold-db <f32> |
-20.0 |
Minimum peak magnitude to keep. |
| Flag | Default | Description |
|---|---|---|
--min-match-score <n> |
2 |
Minimum offset-vote count for a candidate to count as a match. |
--dynamic-gate-scale <f32> |
0.3 |
Scales the match-score gate relative to query size, so short clips aren't held to the same bar as long ones. |
--small-query-threshold <n> |
1000 |
Fingerprint count below which a query is treated as "small" for gating purposes. |
--max-results <n> |
5 |
How many ranked candidates to return. |
| Flag | Description |
|---|---|
--clip-start <seconds> |
Start offset into the source file. |
--clip-duration <seconds> |
Length of the clip to index. |
--auto-clip |
Center a clip in the middle of the track instead of indexing the whole thing (20s by default, or --clip-duration if given). Overrides --clip-start. |
Indexing less than 15 seconds of audio prints a warning, matching quality gets unreliable below that.
Without --config, these paths are checked in order and merged: later files override fields set by earlier ones.
Linux/macOS:
/etc/resonanceid-cli/config.toml$HOME/.config/resonanceid-cli/config.toml./resonanceid-cli.toml
Windows:
%APPDATA%\resonanceid-cli\config.toml.\resonanceid-cli.toml
Precedence overall: CLI flags > config file(s) > built-in defaults.
Copy resonanceid-cli.toml.example to get started:
[fingerprint]
window_size = 1024
hop_size = 512
anchor_window = 5
threshold_db = -20.0
[recognition]
min_match_score = 2
dynamic_gate_scale = 0.3
small_query_threshold = 1000
max_results = 5bash:
# 1) Convert to WAV: mono, 44.1kHz, 16-bit PCM
ffmpeg -y -i input.mp3 -ac 1 -ar 44100 -sample_fmt s16 input.wav
# 2) Store a reference track
resonanceid-cli store input.wav
# 3) Recognize a clip against it
resonanceid-cli recognize clip.wavPowerShell:
# 1) Convert to WAV: mono, 44.1kHz, 16-bit PCM
ffmpeg -y -i input.mp3 -ac 1 -ar 44100 -sample_fmt s16 input.wav
# 2) Store a reference track
.\target\release\resonanceid-cli.exe store input.wav
# 3) Recognize a clip against it
.\target\release\resonanceid-cli.exe recognize clip.wav
# ...or just play the song out loud and let the mic hear it
.\target\release\resonanceid-cli.exe listen --duration 12Or use the bundled helper scripts (scripts/):
# Convert any audio file to the required WAV format
.\scripts\Convert-ToWav.ps1 -InputFile input.mp3
# Convert + store + recognize in one go
.\scripts\Invoke-ResonanceDemo.ps1 -Reference input.mp3 -Clip clip.wav- Input must be 16-bit integer PCM WAV. Anything else (float WAV, 24-bit, compressed formats) is rejected outright, convert with
ffmpegfirst. - WAV samples are read as a flat, single-channel stream. A stereo file will produce garbage fingerprints unless you downmix to mono first (
-ac 1above). - For stable matching, reference clips of roughly 20–45 seconds work best; the tool will warn if you index under 15 seconds.
cargo testCovers CLI argument parsing, config loading/layering, clip-range resolution, hashing, and DB integration.
MIT, see LICENSE.