feat: use ; as artist separator in downloads, add & handling

navidromeArtist() now writes ; instead of / so Navidrome splits
correctly with the updated Tags.Artist.Split config.
Also handles & (e.g. "Artist A & Artist B" → "Artist A;Artist B").

Add fix-artist-separators.sh — one-time Debian script to update
existing library files from " / " to ";" in artist tags.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-23 14:26:19 +02:00
1 parent a6e6af0333
commit 3a8b879abf
2 files changed
+96 -4

No files matched your search

+5 -4
View File
@@ -9,10 +9,11 @@ function sanitize(s) {
function navidromeArtist(name) { function navidromeArtist(name) {
if (!name) return name; if (!name) return name;
return name return name
.replace(/\s+feat\.?\s+/gi, ' / ') .replace(/\s+feat\.?\s+/gi, ';')
.replace(/\s+ft\.?\s+/gi, ' / ') .replace(/\s+ft\.?\s+/gi, ';')
.replace(/\s+featuring\s+/gi, ' / ') .replace(/\s+featuring\s+/gi, ';')
.replace(/,\s+/g, ' / '); .replace(/\s+&\s+/g, ';')
.replace(/,\s+/g, ';');
} }
// Download hi-res iTunes artwork (1000x1000) to cover.jpg, return path or null // Download hi-res iTunes artwork (1000x1000) to cover.jpg, return path or null
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
# fix-artist-separators.sh
# Replaces " / " (space-slash-space) in audio file artist tags with ";"
#
# Safe: only matches " / " with surrounding spaces, so Au/Ra and HUNTR/X
# (no spaces around the slash) are left completely untouched.
#
# Requires: ffprobe, ffmpeg, python3
#
# Usage:
# bash fix-artist-separators.sh [music_dir] -- dry run (no changes)
# bash fix-artist-separators.sh [music_dir] --apply -- actually modify files
#
# Example:
# bash fix-artist-separators.sh /opt/navidrome/music --apply
MUSIC_DIR="${1:-/opt/navidrome/music}"
APPLY=false
[[ "${2:-}" == "--apply" ]] && APPLY=true
if [[ ! -d "$MUSIC_DIR" ]]; then
echo "Error: directory not found: $MUSIC_DIR"
exit 1
fi
if $APPLY; then
echo "🔧 APPLY mode — files will be modified"
else
echo "🔍 DRY RUN — no files will be changed (add --apply to apply changes)"
fi
echo "📂 Scanning: $MUSIC_DIR"
echo ""
count_found=0
count_ok=0
count_fail=0
get_artist() {
ffprobe -v quiet -print_format json -show_format "$1" 2>/dev/null \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
tags = data.get('format', {}).get('tags', {})
print(next((v for k, v in tags.items() if k.lower() == 'artist'), ''))
" 2>/dev/null
}
while IFS= read -r -d '' file; do
artist=$(get_artist "$file") || continue
[[ "$artist" != *" / "* ]] && continue
new_artist="${artist// \/ /;}"
count_found=$((count_found + 1))
echo "📄 $file"
echo " Before : $artist"
echo " After : $new_artist"
if $APPLY; then
ext="${file##*.}"
tmp="${file%.*}.artist_fix_tmp.$ext"
if ffmpeg -i "$file" -map_metadata 0 -metadata "artist=$new_artist" \
-c copy "$tmp" -y -loglevel quiet 2>/dev/null; then
mv "$tmp" "$file"
echo " ✅ Updated"
count_ok=$((count_ok + 1))
else
rm -f "$tmp"
echo " ❌ Failed"
count_fail=$((count_fail + 1))
fi
fi
echo ""
done < <(find "$MUSIC_DIR" -type f \( \
-name "*.mp3" -o -name "*.flac" -o \
-name "*.m4a" -o -name "*.ogg" -o \
-name "*.opus" \) -print0)
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Files with \" / \" in artist tag: $count_found"
if $APPLY; then
echo "Updated: $count_ok | Failed: $count_fail"
if [[ $count_ok -gt 0 ]]; then
echo ""
echo "💡 Trigger a Navidrome rescan to pick up the changes."
fi
else
echo ""
echo "Run with --apply to fix them:"
echo " bash fix-artist-separators.sh \"$MUSIC_DIR\" --apply"
fi