aimusic-attribution / ml /fingerprinting.py
emresar's picture
Upload folder using huggingface_hub
6678fa1 verified
"""
Audio Fingerprinting using Chromaprint/fpcalc
Generates acoustic fingerprints for audio files that can be used
for identification and similarity matching.
Requires: fpcalc CLI tool (from chromaprint package)
- macOS: brew install chromaprint
- Ubuntu: apt install libchromaprint-tools
- Windows: Download from https://acoustid.org/chromaprint
"""
import subprocess
import json
from pathlib import Path
from typing import Optional
def generate_fingerprint(
audio_path: str,
duration: Optional[int] = None
) -> dict:
"""
Generate an acoustic fingerprint for an audio file using fpcalc (Chromaprint).
Args:
audio_path: Path to audio file
duration: Optional max duration in seconds to fingerprint (default: full file)
Returns:
dict with:
- success: bool
- fingerprint: str (raw fingerprint data)
- duration: float (audio duration in seconds)
- algorithm: str ("chromaprint")
- error: str (if failed)
"""
audio_path = Path(audio_path)
if not audio_path.exists():
return {
"success": False,
"error": f"Audio file not found: {audio_path}"
}
try:
# Build fpcalc command
cmd = ["fpcalc", "-json"]
if duration:
cmd.extend(["-length", str(duration)])
cmd.append(str(audio_path))
# Run fpcalc
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=120 # 2 minute timeout
)
if result.returncode != 0:
return {
"success": False,
"error": f"fpcalc failed: {result.stderr}"
}
# Parse JSON output from fpcalc
fpcalc_output = json.loads(result.stdout)
return {
"success": True,
"fingerprint": fpcalc_output.get("fingerprint", ""),
"duration": fpcalc_output.get("duration", 0),
"algorithm": "chromaprint",
"version": "1.5" # Chromaprint version
}
except subprocess.TimeoutExpired:
return {
"success": False,
"error": "Fingerprint generation timed out"
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Failed to parse fpcalc output: {e}"
}
except FileNotFoundError:
return {
"success": False,
"error": "fpcalc not found. Install chromaprint: brew install chromaprint (macOS) or apt install libchromaprint-tools (Ubuntu)"
}
except Exception as e:
return {
"success": False,
"error": f"Fingerprint generation failed: {str(e)}"
}
def compare_fingerprints(fp1: str, fp2: str) -> dict:
"""
Compare two fingerprints and return similarity score.
Note: This is a basic comparison. For production use,
consider using the AcoustID web service or implementing
proper fingerprint comparison algorithms.
Args:
fp1: First fingerprint string
fp2: Second fingerprint string
Returns:
dict with:
- success: bool
- similarity: float (0-1)
- error: str (if failed)
"""
try:
# Basic comparison: Decode fingerprints and compute similarity
# Chromaprint fingerprints are base64-encoded integers
# For now, we'll use a simple string-based similarity
# In production, use proper audio fingerprint comparison
if not fp1 or not fp2:
return {
"success": False,
"error": "Empty fingerprint(s) provided"
}
# Simple character overlap similarity (placeholder)
# Real implementation would decode the fingerprints and compare bit patterns
common = sum(1 for a, b in zip(fp1, fp2) if a == b)
max_len = max(len(fp1), len(fp2))
similarity = common / max_len if max_len > 0 else 0
return {
"success": True,
"similarity": similarity,
"note": "Basic string comparison - use AcoustID API for accurate matching"
}
except Exception as e:
return {
"success": False,
"error": f"Fingerprint comparison failed: {str(e)}"
}
if __name__ == "__main__":
# Test fingerprinting
import sys
if len(sys.argv) > 1:
result = generate_fingerprint(sys.argv[1])
print(json.dumps(result, indent=2))
else:
print("Usage: python fingerprinting.py <audio_file>")