haudiotagger_fingerprint

haudiotagger_fingerprint

Perceptual audio fingerprinting for Flutter.

Duplicates · Renames · Re-encodes — matched by content, not filenames

pub.dev CI MIT License Downloads Live Demo

Documentation · GitHub · pub.dev


Why haudiotagger_fingerprint?

Filenames lie and tags go missing — but the audio doesn't. This package fingerprints what a recording sounds like, so this:

Song A.mp3
song_copy.mp3
01 - Song A.mp3
Song A (Remastered).mp3

can be compared by content instead of by name.

Highlights

  • 🧬 Chromaprint-compatible perceptual fingerprints (same algorithm as fpcalc/AcoustID)
  • 🎵 MP3, FLAC, Ogg Vorbis, WAV, AIFF, M4A/AAC/ALAC
  • 🌍 Android, iOS, Linux, macOS, Windows & Web
  • 🦀 100% pure Rust — no C dependencies, builds everywhere including WASM
  • 📦 Separate lightweight package — zero cost unless you depend on it

Live Demo

Try fingerprinting directly in your browser, integrated in the hAudiotagger demo app.

No installation. No server-side processing. Everything runs locally in your browser.

Try Live Demo

Note

Web applications should use the *FromBytes APIs such as fingerprintFromBytes.


Installation

Add haudiotagger_fingerprint to your pubspec.yaml:

dependencies:
  haudiotagger_fingerprint: ^0.3.2

Or install it from the command line:

flutter pub add haudiotagger_fingerprint

Quick Start

Fingerprint a file

import 'package:haudiotagger_fingerprint/haudiotagger_fingerprint.dart';

// Decodes the full stream; tags, filenames, and containers are ignored.
final a = await HaudioFingerprint.fingerprint('Song A.mp3');
final b = await HaudioFingerprint.fingerprint('song_copy.mp3');

print(a.durationSecs);

Compare two fingerprints

// 1.0 is (near-)identical audio, 0.0 is unrelated.
final score = await HaudioFingerprint.similarity(a, b);
print(score); // 1.0

// Or as a method:
print(await a.similarityTo(b));

Fingerprint bytes (Web)

final fp = await HaudioFingerprint.fingerprintFromBytes(bytes);

Unified API with haudiotagger

With both packages installed, fingerprinting is also available through Haudiotagger — no extra imports or init calls. This package self-registers as the backend at app startup:

import 'package:haudiotagger/haudiotagger.dart';

final fp = await Haudiotagger.fingerprint('Song A.mp3');
final score = await Haudiotagger.similarity(a, b);

Without this package installed, those calls throw a StateError telling you to add it. Requires haudiotagger ^2.2.0.

Finding duplicates

Group files with similarity >= 0.8 as the same recording, then use each file's metadata (title/artist/duration) to pick which copy to keep.

Cancelling long scans

Fingerprinting never blocks your UI: native runs on background threads, web yields cooperatively between decode chunks. For library scans, create one token per file and cancel when the work goes stale (e.g. the user changed track). Abandoned calls abort with FingerprintError.cancelled; also drop their results via a generation counter, since an already-finished call can't be un-computed.

final token = await CancellationToken.create();
final future = HaudioFingerprint.fingerprintFromBytes(bytes,
    cancellationToken: token);

// Later, when the user moves on:
await token.cancel();
await token.dispose();

Score interpretation

Score Meaning
1.0 Identical audio (copies, renames)
> 0.8 Same recording, different encode/container
~0.0 Unrelated audio

Supported formats (decoding)

Format Fingerprint
MP3 ✅
FLAC ✅
Ogg Vorbis ✅
WAV ✅
AIFF ✅
M4A / AAC / ALAC ✅
Opus, APE, WavPack, Musepack ❌ (no pure-Rust decoder)

Platform support

Platform Support
Android ✅
iOS ✅
Linux ✅
macOS ✅
Windows ✅
Web ✅

The Web implementation decodes and fingerprints fully in-browser via WebAssembly. Large files are CPU-heavy; prefer short clips or native for bulk library scans.


Documentation

→ Read the full documentation


Requirements

  • Flutter >= 3.0.0
  • Dart SDK >= 3.6.0

Contributing

Contributions are welcome! 🎉

If you find a bug, have an idea, or want to improve haudiotagger_fingerprint:


License

haudiotagger_fingerprint is open-source software licensed under the MIT License.


Made with ❤️ and 🦀 by Hirdaya Shrestha