Add granular post-processing toggles for metadata services, cover art, and lyrics

pull/253/head
Broque Thomas 2 months ago
parent 5f72fe79a6
commit cae2bd0c62

@ -4198,7 +4198,7 @@ def handle_settings():
if 'active_media_server' in new_settings:
config_manager.set_active_media_server(new_settings['active_media_server'])
for service in ['spotify', 'plex', 'jellyfin', 'navidrome', 'soulseek', 'download_source', 'settings', 'database', 'metadata_enhancement', 'file_organization', 'playlist_sync', 'tidal', 'tidal_download', 'qobuz', 'listenbrainz', 'acoustid', 'lastfm', 'genius', 'import', 'lossy_copy', 'ui_appearance', 'youtube', 'content_filter', 'itunes', 'm3u_export']:
for service in ['spotify', 'plex', 'jellyfin', 'navidrome', 'soulseek', 'download_source', 'settings', 'database', 'metadata_enhancement', 'file_organization', 'playlist_sync', 'tidal', 'tidal_download', 'qobuz', 'listenbrainz', 'acoustid', 'lastfm', 'genius', 'import', 'lossy_copy', 'ui_appearance', 'youtube', 'content_filter', 'itunes', 'm3u_export', 'musicbrainz', 'deezer', 'audiodb']:
if service in new_settings:
for key, value in new_settings[service].items():
config_manager.set(f'{service}.{key}', value)
@ -14314,6 +14314,8 @@ def _generate_lrc_file(file_path: str, context: dict, artist: dict, album_info:
Generate LRC lyrics file using LRClib API.
Elegant addition to post-processing - extracts metadata from existing context.
"""
if not config_manager.get('metadata_enhancement.lrclib_enabled', True):
return False
try:
# Extract track information from existing context (same as metadata enhancement)
original_search = context.get("original_search_result", {})
@ -14698,7 +14700,9 @@ def _embed_source_ids(audio_file, metadata: dict):
# ── 2d. Tidal lookup for ISRC fallback, copyright, and source IDs ──
tidal_isrc = None
tidal_copyright = None
if track_title and artist_name:
if not config_manager.get('tidal.embed_tags', True):
pass
elif track_title and artist_name:
try:
if tidal_client and tidal_client.is_authenticated():
td_result = tidal_client.search_track(artist_name, track_title)
@ -14729,7 +14733,9 @@ def _embed_source_ids(audio_file, metadata: dict):
qobuz_isrc = None
qobuz_copyright = None
qobuz_label = None
if track_title and artist_name:
if not config_manager.get('qobuz.embed_tags', True):
pass
elif track_title and artist_name:
try:
qz_client = qobuz_enrichment_worker.client if qobuz_enrichment_worker else None
if qz_client and qz_client.is_authenticated():
@ -14768,7 +14774,9 @@ def _embed_source_ids(audio_file, metadata: dict):
# ── 2f. Last.fm lookup for tags (genre merge) and URL ──
lastfm_tags = []
lastfm_url = None
if track_title and artist_name:
if not config_manager.get('lastfm.embed_tags', True):
pass
elif track_title and artist_name:
try:
lf_client = lastfm_worker.client if lastfm_worker else None
if lf_client:
@ -14794,7 +14802,9 @@ def _embed_source_ids(audio_file, metadata: dict):
# state directly and skip immediately if Genius is rate-limited, rather
# than entering search_song which would sleep for up to 120s.
genius_url = None
if track_title and artist_name:
if not config_manager.get('genius.embed_tags', True):
pass
elif track_title and artist_name:
try:
import core.genius_client as _genius_module
if time.time() < _genius_module._rate_limit_until:
@ -14980,6 +14990,8 @@ def _embed_source_ids(audio_file, metadata: dict):
def _download_cover_art(album_info: dict, target_dir: str):
"""Downloads cover.jpg into the specified directory."""
if not config_manager.get('metadata_enhancement.cover_art_download', True):
return
try:
cover_path = os.path.join(target_dir, "cover.jpg")
if os.path.exists(cover_path):

@ -4210,25 +4210,82 @@
<!-- Metadata Enhancement Settings -->
<div class="settings-group">
<h3>🎵 Metadata Enhancement</h3>
<h3>🎵 Post-Processing</h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="metadata-enabled" checked>
Enable metadata enhancement with Spotify data
<input type="checkbox" id="metadata-enabled" checked
onchange="document.getElementById('post-processing-options').style.display = this.checked ? 'block' : 'none'">
Enable post-processing on downloaded files
</label>
<small class="settings-hint">Master toggle — disabling this skips all metadata, artwork, and lyrics processing</small>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="embed-album-art" checked>
Embed high-quality album art from Spotify
</label>
</div>
<div id="post-processing-options">
<!-- Core Features -->
<div class="post-processing-section">
<div class="post-processing-section-title">Core Features</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="embed-album-art" checked>
Embed album art into file
</label>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="cover-art-download" checked>
Download cover.jpg to album folder
</label>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="lrclib-enabled" checked>
Generate .lrc lyrics files (LRClib)
</label>
</div>
</div>
<div class="form-group">
<label>Supported Formats:</label>
<div class="supported-formats">MP3, FLAC, MP4/M4A, OGG</div>
<!-- Metadata Services -->
<div class="post-processing-section">
<div class="post-processing-section-title">Metadata Services</div>
<small class="settings-hint" style="margin-bottom: 8px; display: block;">Choose which services embed IDs, genres, and metadata into your files during download</small>
<div class="post-processing-grid">
<label class="checkbox-label">
<input type="checkbox" id="embed-musicbrainz" checked>
MusicBrainz
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-deezer" checked>
Deezer
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-audiodb" checked>
AudioDB
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-tidal" checked>
Tidal
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-qobuz" checked>
Qobuz
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-lastfm" checked>
Last.fm
</label>
<label class="checkbox-label">
<input type="checkbox" id="embed-genius" checked>
Genius
</label>
</div>
</div>
<div class="form-group">
<label>Supported Formats:</label>
<div class="supported-formats">MP3, FLAC, MP4/M4A, OGG</div>
</div>
</div>
</div>

@ -4827,9 +4827,19 @@ async function loadSettingsData() {
// Populate Database settings
document.getElementById('max-workers').value = settings.database?.max_workers || '5';
// Populate Metadata Enhancement settings
// Populate Post-Processing settings
document.getElementById('metadata-enabled').checked = settings.metadata_enhancement?.enabled !== false;
document.getElementById('embed-album-art').checked = settings.metadata_enhancement?.embed_album_art !== false;
document.getElementById('cover-art-download').checked = settings.metadata_enhancement?.cover_art_download !== false;
document.getElementById('lrclib-enabled').checked = settings.metadata_enhancement?.lrclib_enabled !== false;
document.getElementById('embed-musicbrainz').checked = settings.musicbrainz?.embed_tags !== false;
document.getElementById('embed-deezer').checked = settings.deezer?.embed_tags !== false;
document.getElementById('embed-audiodb').checked = settings.audiodb?.embed_tags !== false;
document.getElementById('embed-tidal').checked = settings.tidal?.embed_tags !== false;
document.getElementById('embed-qobuz').checked = settings.qobuz?.embed_tags !== false;
document.getElementById('embed-lastfm').checked = settings.lastfm?.embed_tags !== false;
document.getElementById('embed-genius').checked = settings.genius?.embed_tags !== false;
document.getElementById('post-processing-options').style.display = settings.metadata_enhancement?.enabled !== false ? 'block' : 'none';
// Populate File Organization settings
document.getElementById('file-organization-enabled').checked = settings.file_organization?.enabled !== false;
@ -5571,7 +5581,8 @@ async function saveSettings(quiet = false) {
tidal: {
client_id: document.getElementById('tidal-client-id').value,
client_secret: document.getElementById('tidal-client-secret').value,
redirect_uri: document.getElementById('tidal-redirect-uri').value
redirect_uri: document.getElementById('tidal-redirect-uri').value,
embed_tags: document.getElementById('embed-tidal').checked
},
plex: {
base_url: document.getElementById('plex-url').value,
@ -5604,10 +5615,12 @@ async function saveSettings(quiet = false) {
enabled: document.getElementById('acoustid-enabled').checked
},
lastfm: {
api_key: document.getElementById('lastfm-api-key').value
api_key: document.getElementById('lastfm-api-key').value,
embed_tags: document.getElementById('embed-lastfm').checked
},
genius: {
access_token: document.getElementById('genius-access-token').value
access_token: document.getElementById('genius-access-token').value,
embed_tags: document.getElementById('embed-genius').checked
},
itunes: {
country: document.getElementById('itunes-country').value || 'US'
@ -5621,14 +5634,26 @@ async function saveSettings(quiet = false) {
quality: document.getElementById('tidal-download-quality').value || 'lossless'
},
qobuz: {
quality: document.getElementById('qobuz-quality').value || 'lossless'
quality: document.getElementById('qobuz-quality').value || 'lossless',
embed_tags: document.getElementById('embed-qobuz').checked
},
database: {
max_workers: parseInt(document.getElementById('max-workers').value)
},
metadata_enhancement: {
enabled: document.getElementById('metadata-enabled').checked,
embed_album_art: document.getElementById('embed-album-art').checked
embed_album_art: document.getElementById('embed-album-art').checked,
cover_art_download: document.getElementById('cover-art-download').checked,
lrclib_enabled: document.getElementById('lrclib-enabled').checked
},
musicbrainz: {
embed_tags: document.getElementById('embed-musicbrainz').checked
},
deezer: {
embed_tags: document.getElementById('embed-deezer').checked
},
audiodb: {
embed_tags: document.getElementById('embed-audiodb').checked
},
file_organization: {
enabled: document.getElementById('file-organization-enabled').checked,

@ -2067,6 +2067,30 @@ body {
padding: 6px 10px;
}
/* Post-Processing Settings */
.post-processing-section {
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 10px;
padding: 14px 16px;
margin-bottom: 12px;
}
.post-processing-section-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1.2px;
color: rgba(var(--accent-rgb), 0.8);
margin-bottom: 10px;
}
.post-processing-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px 16px;
}
/* Read-only Fields */
.readonly-field {
padding: 8px 12px;

Loading…
Cancel
Save