Skip to content

Repository files navigation

ResonanceID-cli

CI

GitHub last commit GitHub repo size Stars AUR version

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.

Features

  • 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)

Tech Stack

  • Rust (edition 2024, needs rustc 1.85+)
  • SQLite via rusqlite (bundled, no system SQLite library required)
  • Audio capture via cpal (microphone input for listen)
  • FFT via rustfft
  • WAV I/O via hound
  • TOML config via serde + toml

Pipeline

Store / Remember

  1. Read WAV samples
  2. Optionally clip to a sub-range of the track
  3. STFT spectrogram
  4. Peak extraction (constellation points)
  5. Pair each peak with nearby peaks to generate (hash, anchor_time_ms) fingerprints
  6. Insert song metadata + fingerprints into SQLite

Recognize

  1. Read WAV samples
  2. STFT spectrogram
  3. Peak extraction
  4. Fingerprint generation (same hashing as above)
  5. Look up each hash in the database and record the time offset between query and match
  6. Rank candidate songs by whichever offset gets the most votes: a real match produces one dominant, consistent offset

Install

Windows (Chocolatey)

choco install resonanceid-cli

Arch Linux (AUR)

paru -S resonanceid-cli
# or
yay -S resonanceid-cli

From source

Requires Rust 1.85 or newer (edition 2024). CI uses the stable toolchain. 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 --release

The binary is target/release/resonanceid-cli (resonanceid-cli.exe on Windows). During development, run it via cargo run --:

cargo run -- --help

Args after -- go to the program, not to cargo.

CLI Commands

Store a reference track

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.

Recognize a clip

resonanceid-cli recognize <wav_path> [options]

Prints the best match (if any), then every candidate ranked by score.

Show ranked candidates

resonanceid-cli list-top-matches <wav_path> [options]

Same options as recognize, just prints the ranked list without singling out a "best" match.

Listen to the microphone

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.

Import a whole folder

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.

Database management

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.

Options

Common (all commands)

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.

Fingerprint (store, recognize, list-top-matches)

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.

Recognition (recognize, list-top-matches)

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.

Clipping (store, remember, index)

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.

Config

Without --config, these paths are checked in order and merged: later files override fields set by earlier ones.

Linux/macOS:

  1. /etc/resonanceid-cli/config.toml
  2. $HOME/.config/resonanceid-cli/config.toml
  3. ./resonanceid-cli.toml

Windows:

  1. %APPDATA%\resonanceid-cli\config.toml
  2. .\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 = 5

Quick Demo

bash:

# 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.wav

PowerShell:

# 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 12

Or 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

Notes

  • Input must be 16-bit integer PCM WAV. Anything else (float WAV, 24-bit, compressed formats) is rejected outright, convert with ffmpeg first.
  • WAV samples are read as a flat, single-channel stream. A stereo file will produce garbage fingerprints unless you downmix to mono first (-ac 1 above).
  • For stable matching, reference clips of roughly 20–45 seconds work best; the tool will warn if you index under 15 seconds.

Testing

With mise and rustup installed, use the same tasks as CI:

mise trust
mise run setup
mise run check

mise run check runs formatting, build, Clippy and tests in order. Individual checks are mise run format, mise run build, mise run lint and mise run test. Rustup retains ownership of the existing stable toolchain. Build, lint and test commands use Cargo.lock with --locked; no dependency constraints change.

CI checks Linux and Windows on pull requests, main/ci branch pushes and manual runs. Releases reuse that validation, smoke-test the built release binaries, then publish and verify their downloaded checksums. Only publication receives write permission. Manual release runs on branches validate and build artifacts without publishing; publishing requires a matching v version tag.

The pipeline baseline documents the shared structure. Chocolatey metadata is maintained under SUBMISSIONS/chocolatey; merging it does not submit a package. The package revision there retains the approved 1.0.0 binary independently of the application's development version.

The tests cover CLI argument parsing, config loading/layering, clip-range resolution, hashing, and database integration.

License

MIT, see LICENSE.

Package-channel automation

Packaging

Chocolatey, Winget and AUR packages are prepared from the same published release and validated automatically. Publication is an explicit manual workflow choice; Winget opens an upstream PR and Chocolatey submissions undergo moderation. See packaging instructions for validation, release selection and required publishing credentials.

Links

About

A Rust cli implementation of Shazam-style audio identification

Topics

Resources

Stars

32 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages