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:
1 parent
a6e6af0333
commit
3a8b879abf
2 files changed
+96
-4
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user