dedup: modulo audio fingerprinting via fpcalc + cache SQLite
Nuovo modulo core.dedup per rilevare brani audio duplicati usando Chromaprint (fpcalc): scan cartella (opzionalmente ricorsivo), fingerprint acustico via fpcalc -json, cache SQLite in _get_config_dir()/dedup_cache.db per non ricalcolare al re-scan, raggruppamento per fingerprint identico + ordering per bitrate DESC. move_to_trash() usa send2trash (reversibile via Finder/Explorer). - core/paths.py: find_fpcalc() con fallback dev su project bundle_bin - core/dedup.py: scan_folder, compute_fingerprint, move_to_trash - tests/test_dedup.py: 9 unit test (mock fpcalc + send2trash) - requirements.txt: send2trash>=1.8.0 - build_macos.py: download fpcalc universal binary da GitHub releases - build_windows.py: download fpcalc.exe da GitHub releases
This commit is contained in:
1 parent
e09ee1382b
commit
fb13b0f70e
6 files changed
+635
No files matched your search
@@ -31,6 +31,8 @@ BUNDLE_DIR = ROOT / "bundle_bin"
|
||||
|
||||
YTDLP_URL = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe"
|
||||
FFMPEG_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip"
|
||||
FPCALC_URL = ("https://github.com/acoustid/chromaprint/releases/download/"
|
||||
"v1.5.1/chromaprint-fpcalc-1.5.1-windows-x86_64.zip")
|
||||
|
||||
|
||||
def log(msg):
|
||||
@@ -87,6 +89,33 @@ def download_ffmpeg():
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# 2b. Scarica fpcalc.exe (Chromaprint) — usato dal tab Dedup
|
||||
# =========================================================================
|
||||
def download_fpcalc():
|
||||
dest = BUNDLE_DIR / "fpcalc.exe"
|
||||
if dest.exists():
|
||||
log("fpcalc.exe gia presente")
|
||||
return
|
||||
|
||||
log(f"Scarico fpcalc.exe ...")
|
||||
BUNDLE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
response = urllib.request.urlopen(FPCALC_URL)
|
||||
zip_data = io.BytesIO(response.read())
|
||||
with zipfile.ZipFile(zip_data) as zf:
|
||||
for member in zf.namelist():
|
||||
basename = Path(member).name
|
||||
if basename == "fpcalc.exe":
|
||||
data = zf.read(member)
|
||||
dest.write_bytes(data)
|
||||
log(f" Estratto: fpcalc.exe ({len(data) // 1024} KB)")
|
||||
|
||||
if not dest.exists():
|
||||
print("ERRORE: fpcalc.exe non trovato nello zip!")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# =========================================================================
|
||||
# 3. PyInstaller
|
||||
# =========================================================================
|
||||
@@ -187,6 +216,7 @@ def main():
|
||||
|
||||
download_ytdlp()
|
||||
download_ffmpeg()
|
||||
download_fpcalc()
|
||||
run_pyinstaller()
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
|
||||
Reference in new issue
Block a user