Downloads: verify a grab by audio fingerprint before import #277

Open
opened 2026-09-27 03:01:30 +00:00 by yonlu · 1 comment
Owner

Phase 2 of .planning/plans/active/022-audio-fingerprinting.md. Depends on #96 (the fingerprint + AcoustID primitive).

The problem

A download can be the wrong recording and nothing notices. backend/download/rank.go scores a candidate on filename, title and length; Staging.Verify (backend/download/staging.go) confirms the files exist inside staging and are non-empty. Nothing ever looks at the audio. A Soulseek folder named for the album you asked for, containing something else, imports cleanly; a truncated file that still parses headers imports cleanly.

Reproduction

  1. Request any album whose tracklist resolves (ExpectedTrack rows).
  2. Serve a candidate whose files have the right names and roughly the right lengths but different audio (or test_data/music_library_broken/truncated.mp3 renamed as track 1).
  3. The item goes verifying → tagging → importing → complete with no warning, and the wrong files are tagged as the requested recordings.

What to build (summary; the plan has the detail)

  • ExpectedTrack.RecordingMBID, filled from MBTrack.MBID in backend/downloadcatalog.go (it already is the recording MBID) and from Download.RecordingMBID for a track request.
  • In the StateVerifying window, after Staging.Verify: fully decode each staged audio file (true duration + integrity), fingerprint, one batched AcoustID lookup, compare against the expected MBIDs.
  • A verdict per file stored in a new table (download_items is Authored, so staleshape never retires it and a new column would never reach an existing install).
  • Verdicts are information, never a gate: the import proceeds in every case. Not asked, no network, not in AcoustID, undecodable, matches, probable, matches a different track of this release, and a different recording are distinct states, surfaced on the item in the Downloads view.

Done when

The reproduction above leaves the item complete and visibly flagged in the Downloads view, and a correct download shows as verified; both asserted through the rendered item, not a returned struct.

Phase 2 of `.planning/plans/active/022-audio-fingerprinting.md`. Depends on #96 (the fingerprint + AcoustID primitive). ## The problem A download can be the wrong recording and nothing notices. `backend/download/rank.go` scores a candidate on filename, title and length; `Staging.Verify` (`backend/download/staging.go`) confirms the files exist inside staging and are non-empty. Nothing ever looks at the audio. A Soulseek folder named for the album you asked for, containing something else, imports cleanly; a truncated file that still parses headers imports cleanly. ## Reproduction 1. Request any album whose tracklist resolves (`ExpectedTrack` rows). 2. Serve a candidate whose files have the right names and roughly the right lengths but different audio (or `test_data/music_library_broken/truncated.mp3` renamed as track 1). 3. The item goes `verifying → tagging → importing → complete` with no warning, and the wrong files are tagged as the requested recordings. ## What to build (summary; the plan has the detail) - `ExpectedTrack.RecordingMBID`, filled from `MBTrack.MBID` in `backend/downloadcatalog.go` (it already is the recording MBID) and from `Download.RecordingMBID` for a track request. - In the `StateVerifying` window, after `Staging.Verify`: fully decode each staged audio file (true duration + integrity), fingerprint, one batched AcoustID lookup, compare against the expected MBIDs. - A verdict per file stored in a **new** table (`download_items` is `Authored`, so `staleshape` never retires it and a new column would never reach an existing install). - Verdicts are information, never a gate: the import proceeds in every case. *Not asked*, *no network*, *not in AcoustID*, *undecodable*, *matches*, *probable*, *matches a different track of this release*, and *a different recording* are distinct states, surfaced on the item in the Downloads view. ## Done when The reproduction above leaves the item complete **and** visibly flagged in the Downloads view, and a correct download shows as verified; both asserted through the rendered item, not a returned struct.
yonlu self-assigned this 2026-09-27 03:43:04 +00:00
yonlu added the
Status
In Progress
label 2026-09-27 03:43:05 +00:00
Author
Owner

Claiming; same batch branch as #96 (feat/96-audio-fingerprint). Approach per plan 022 Phase 2: RecordingMBID on ExpectedTrack, full decode + one batched AcoustID lookup inside Import after planFiles, per-file verdicts in a new download_verifications table (download_items is Authored), surfaced on the Downloads item. Information, never a gate.

Claiming; same batch branch as #96 (`feat/96-audio-fingerprint`). Approach per plan 022 Phase 2: RecordingMBID on ExpectedTrack, full decode + one batched AcoustID lookup inside Import after planFiles, per-file verdicts in a new `download_verifications` table (download_items is Authored), surfaced on the Downloads item. Information, never a gate.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yonlu/yellowjacket#277