Add opt-in setting to replace lower quality files on import

New toggle in Settings > Library: "Replace lower quality files on
import". When enabled, if a track already exists in the library at
a lower quality tier (e.g. MP3) and a higher quality version (e.g.
FLAC) is imported from staging, the existing file is replaced.
Comparison uses the existing QUALITY_TIERS system (lossless > opus/
ogg > m4a > mp3). When disabled (default), existing behavior is
unchanged — existing tracks are always kept. Also applies to regular
downloads that land on an existing file.
pull/289/head
Broque Thomas 1 month ago
parent e1c5ae0eb5
commit c6bebd5e09

@ -461,7 +461,8 @@ class ConfigManager:
"poll_interval": 30
},
"import": {
"staging_path": "./Staging"
"staging_path": "./Staging",
"replace_lower_quality": False
},
"m3u_export": {
"enabled": False

@ -20076,15 +20076,37 @@ def _post_process_matched_download(context_key, context, file_path):
has_metadata = existing_file is not None and len(existing_file.tags or {}) > 2 # More than basic tags
if has_metadata and not is_enhance_download:
print(f"⚠️ [Protection] Existing file already has metadata enhancement - skipping overwrite: {os.path.basename(final_path)}")
print(f"🗑️ [Protection] Removing redundant download file: {os.path.basename(file_path)}")
try:
os.remove(file_path) # Remove the redundant file
except FileNotFoundError:
print(f"⚠️ [Protection] Could not remove redundant file (already gone): {file_path}")
except Exception as e:
print(f"⚠️ [Protection] Error removing redundant file: {e}")
return # Don't overwrite the good file
# Check if incoming file is higher quality and setting is enabled
_replace_lower = config_manager.get('import.replace_lower_quality', False)
if _replace_lower:
_existing_tier = _get_quality_tier_from_extension(final_path)
_incoming_tier = _get_quality_tier_from_extension(file_path)
if _incoming_tier[1] < _existing_tier[1]:
# Incoming is higher quality (lower tier number) — replace
print(f"🔄 [Quality Replace] Replacing {_existing_tier[0]} with {_incoming_tier[0]}: {os.path.basename(final_path)}")
try:
os.remove(final_path)
except Exception as e:
print(f"⚠️ [Quality Replace] Could not remove existing file: {e}")
else:
print(f"⚠️ [Protection] Existing file is same or better quality ({_existing_tier[0]} vs {_incoming_tier[0]}) - skipping: {os.path.basename(final_path)}")
try:
os.remove(file_path)
except FileNotFoundError:
pass
except Exception as e:
print(f"⚠️ [Protection] Error removing redundant file: {e}")
return
else:
print(f"⚠️ [Protection] Existing file already has metadata enhancement - skipping overwrite: {os.path.basename(final_path)}")
print(f"🗑️ [Protection] Removing redundant download file: {os.path.basename(file_path)}")
try:
os.remove(file_path)
except FileNotFoundError:
print(f"⚠️ [Protection] Could not remove redundant file (already gone): {file_path}")
except Exception as e:
print(f"⚠️ [Protection] Error removing redundant file: {e}")
return # Don't overwrite the good file
elif is_enhance_download:
# ENHANCE BYPASS: Allow overwrite — backup original, then remove to allow move
print(f"🔄 [Enhance] Quality enhance mode — replacing existing file: {os.path.basename(final_path)}")

@ -5710,6 +5710,24 @@
</div>
<!-- Import Quality Settings -->
<div class="settings-group" data-stg="library">
<h3>📥 Import Settings</h3>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="import-replace-lower-quality">
Replace lower quality files on import
</label>
</div>
<div class="help-text">
When importing from Staging, if a track already exists in your library at a lower quality
(e.g. MP3), it will be replaced with the higher quality version (e.g. FLAC).
If disabled, existing tracks are always kept and the import file is skipped.
</div>
</div>
<!-- M3U Export Settings -->
<div class="settings-group" data-stg="library">
<h3>📋 M3U Playlist Export</h3>

@ -5972,6 +5972,9 @@ async function loadSettingsData() {
// Populate Content Filter settings
document.getElementById('allow-explicit').checked = settings.content_filter?.allow_explicit !== false;
// Populate Import settings
document.getElementById('import-replace-lower-quality').checked = settings.import?.replace_lower_quality === true;
// Populate M3U Export settings
document.getElementById('m3u-export-enabled').checked = settings.m3u_export?.enabled === true;
@ -7076,6 +7079,9 @@ async function saveSettings(quiet = false) {
content_filter: {
allow_explicit: document.getElementById('allow-explicit').checked
},
import: {
replace_lower_quality: document.getElementById('import-replace-lower-quality').checked
},
lossy_copy: {
enabled: document.getElementById('lossy-copy-enabled').checked,
codec: document.getElementById('lossy-copy-codec').value,

Loading…
Cancel
Save