Add granular post-processing toggles for metadata services, cover art, and lyrics
This commit is contained in:
parent
5f72fe79a6
commit
cae2bd0c62
4 changed files with 141 additions and 23 deletions
|
|
@ -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…
Reference in a new issue