From 5d8f3bcaecd92ff340d2d5e9fb05bc49b513c6e6 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:16:49 -0700 Subject: [PATCH] Store original audio details in track provenance (#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add bit_depth, sample_rate, bitrate columns to track_downloads table - Read audio info from file via Mutagen when recording provenance - Source Info popover shows "Audio: 24-bit · 96.0kHz · 2304kbps" - These values are captured from the original file before transcoding, so users can see the original specs even after Blasphemy Mode converts FLAC to lossy format --- database/music_database.py | 20 ++++++++++++++++---- web_server.py | 18 ++++++++++++++++++ webui/static/script.js | 4 ++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/database/music_database.py b/database/music_database.py index 023177c0..71510a87 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -1156,6 +1156,15 @@ class MusicDatabase: cursor.execute("CREATE INDEX IF NOT EXISTS idx_td_file_path ON track_downloads (file_path)") cursor.execute("CREATE INDEX IF NOT EXISTS idx_td_source ON track_downloads (source_username, source_filename)") + # Migration: Add audio detail columns to track_downloads + cursor.execute("PRAGMA table_info(track_downloads)") + td_columns = [c[1] for c in cursor.fetchall()] + if 'bit_depth' not in td_columns: + cursor.execute("ALTER TABLE track_downloads ADD COLUMN bit_depth INTEGER") + cursor.execute("ALTER TABLE track_downloads ADD COLUMN sample_rate INTEGER") + cursor.execute("ALTER TABLE track_downloads ADD COLUMN bitrate INTEGER") + logger.info("Added audio detail columns (bit_depth, sample_rate, bitrate) to track_downloads") + # Discovery artist blacklist — artists users never want to see in discovery cursor.execute(""" CREATE TABLE IF NOT EXISTS discovery_artist_blacklist ( @@ -8626,7 +8635,8 @@ class MusicDatabase: def record_track_download(self, file_path: str, source_service: str, source_username: str, source_filename: str, source_size: int = 0, audio_quality: str = '', track_title: str = '', track_artist: str = '', track_album: str = '', - status: str = 'completed', track_id: str = None) -> Optional[int]: + status: str = 'completed', track_id: str = None, + bit_depth: int = None, sample_rate: int = None, bitrate: int = None) -> Optional[int]: """Record a download with full source provenance. Returns the record ID.""" try: conn = self._get_connection() @@ -8642,10 +8652,12 @@ class MusicDatabase: cursor.execute(""" INSERT INTO track_downloads (track_id, file_path, source_service, source_username, source_filename, - source_size, audio_quality, track_title, track_artist, track_album, status) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + source_size, audio_quality, track_title, track_artist, track_album, status, + bit_depth, sample_rate, bitrate) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, (track_id, file_path, source_service, source_username, source_filename, - source_size, audio_quality, track_title, track_artist, track_album, status)) + source_size, audio_quality, track_title, track_artist, track_album, status, + bit_depth, sample_rate, bitrate)) conn.commit() return cursor.lastrowid except Exception as e: diff --git a/web_server.py b/web_server.py index a18f7e8b..f2d69dd1 100644 --- a/web_server.py +++ b/web_server.py @@ -1728,6 +1728,21 @@ def _record_download_provenance(context): quality = context.get('_audio_quality', '') size = search_result.get('size', 0) + # Read audio details from the file for provenance (survives transcoding) + bit_depth = None + sample_rate = None + bitrate = None + try: + if file_path and os.path.isfile(file_path): + from mutagen import File as MutagenFile + audio = MutagenFile(file_path) + if audio and audio.info: + sample_rate = getattr(audio.info, 'sample_rate', None) + bitrate = getattr(audio.info, 'bitrate', None) + bit_depth = getattr(audio.info, 'bits_per_sample', None) + except Exception: + pass + db = get_database() db.record_track_download( file_path=file_path, @@ -1739,6 +1754,9 @@ def _record_download_provenance(context): track_title=title, track_artist=artist_name, track_album=album_name, + bit_depth=bit_depth, + sample_rate=sample_rate, + bitrate=bitrate, ) except Exception: pass # Non-critical, never block download flow diff --git a/webui/static/script.js b/webui/static/script.js index e759cf1c..2e29f258 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -44658,6 +44658,10 @@ async function showTrackSourceInfo(track, anchorEl) { Quality ${_esc(dl.audio_quality)} ` : ''} + ${dl.bit_depth || dl.sample_rate || dl.bitrate ? `