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.
This commit is contained in:
parent
e1c5ae0eb5
commit
c6bebd5e09
4 changed files with 57 additions and 10 deletions
|
|
@ -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…
Reference in a new issue