feat(audio): loudness_cache gains a content_key column (table only)

An ISRC or fingerprint column plus a partial index, with
set_content_key / get_by_content_key helpers, so a local or Plex copy of
the same recording can reuse an analysis. The analyser and every audio
path are untouched; set/get keep their track_id contract.

cc
This commit is contained in:
vicrodh committed 2026-08-28 20:31:05 -06:00
1 parent 4e41e92347
commit 2208ca7a9b
1 file changed
+44
+44
View File
@@ -47,6 +47,17 @@ impl LoudnessCache {
)
.map_err(|e| format!("Failed to create loudness table: {}", e))?;
// Identity beyond the Qobuz id (2026-08-28): an ISRC or a content
// fingerprint, so a local/Plex copy of the same recording can reuse
// the analysis. TABLE ONLY — the analyser and every audio path are
// untouched; `set`/`get` keep their track_id contract. Additive,
// idempotent (the duplicate-column error is the "already there" case).
let _ = conn.execute_batch("ALTER TABLE track_loudness ADD COLUMN content_key TEXT;");
let _ = conn.execute_batch(
"CREATE INDEX IF NOT EXISTS idx_track_loudness_content_key
ON track_loudness(content_key) WHERE content_key IS NOT NULL;",
);
log::info!("[LoudnessCache] Opened at {}", db_path.display());
Ok(Self {
@@ -71,6 +82,39 @@ impl LoudnessCache {
.ok()
}
/// Attach a cross-source content key (ISRC or fingerprint) to an
/// existing row. No-op when the track has no analysis yet.
pub fn set_content_key(&self, track_id: u64, content_key: &str) {
if content_key.trim().is_empty() {
return;
}
if let Ok(conn) = self.conn.lock() {
let _ = conn.execute(
"UPDATE track_loudness SET content_key = ?1 WHERE track_id = ?2",
params![content_key.trim(), track_id as i64],
);
}
}
/// Look up cached loudness by content key (any source's copy of the
/// same recording). Newest analysis wins.
pub fn get_by_content_key(&self, content_key: &str) -> Option<CachedLoudness> {
let conn = self.conn.lock().ok()?;
conn.query_row(
"SELECT gain_db, peak, source FROM track_loudness
WHERE content_key = ?1 ORDER BY created_at DESC LIMIT 1",
params![content_key.trim()],
|row| {
Ok(CachedLoudness {
gain_db: row.get::<_, f64>(0)? as f32,
peak: row.get::<_, f64>(1)? as f32,
source: row.get(2)?,
})
},
)
.ok()
}
/// Store or update loudness data for a track.
pub fn set(&self, track_id: u64, gain_db: f32, peak: f32, source: &str) {
if let Ok(conn) = self.conn.lock() {