Stage 0: migrate pipeline scripts from /opt/sldl, scaffold repo
Moves all ~30 pipeline scripts, configs, and the vendored sldl binary into this repo (source /opt/sldl left untouched). Removes all docker exec/docker compose dependencies now that beets and sldl run in-process/as a subprocess of this container instead of via soulbeet/on-demand sldl containers. Replaces hardcoded host paths, Navidrome credentials, and Spotify credential sourcing with env-var-driven paths and shared credential loaders. Adds Dockerfile, entrypoint.sh, requirements.txt, docker-compose.snippet.yml, and the initial app DB schema.
This commit is contained in:
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
# Find audio files in the library that have no ALBUM tag, set ALBUM to
|
||||
# "{TITLE} - Single" — matches Spotify / Apple Music's convention for
|
||||
# single-track releases. Otherwise these tracks land as [Unknown Album]
|
||||
# in Navidrome.
|
||||
#
|
||||
# Usage:
|
||||
# fix-empty-album.sh # dry run (default)
|
||||
# fix-empty-album.sh --apply # actually rewrite tags
|
||||
#
|
||||
# Bandcamp single-track downloads are the most common source of this
|
||||
# issue (Bandcamp serves single tracks with no ALBUM tag). New downloads
|
||||
# via sync-bandcamp.py are auto-tagged; this script handles backfill.
|
||||
|
||||
set -u
|
||||
APPLY=0
|
||||
[[ "${1:-}" == "--apply" ]] && APPLY=1
|
||||
|
||||
LOG=${ALEMBIC_CONFIG_DIR:-/config}/logs/fix-empty-album-$(date +%Y%m%d-%H%M%S).log
|
||||
mkdir -p "$(dirname "$LOG")"
|
||||
|
||||
NAVIDROME_ENV="${ALEMBIC_CONFIG_DIR:-/config}/pipeline/navidrome/admin.env"
|
||||
[ -f "$NAVIDROME_ENV" ] && source "$NAVIDROME_ENV"
|
||||
ND_BASE="${ND_BASE:-http://navidrome:4533}"
|
||||
ND_USER="${ND_USER:-andrew}"
|
||||
ND_PASS="${ND_PASS:-}"
|
||||
log() { echo "[$(date -Iseconds)] $*" | tee -a "$LOG"; }
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
log "=== FIX EMPTY ALBUM (APPLY) ==="
|
||||
else
|
||||
log "=== FIX EMPTY ALBUM (DRY RUN — pass --apply to write) ==="
|
||||
fi
|
||||
|
||||
FIXED=0
|
||||
SKIPPED=0
|
||||
|
||||
while IFS= read -r -d '' f; do
|
||||
ext="${f,,}"; ext="${ext##*.}"
|
||||
album="" ; title=""
|
||||
case "$ext" in
|
||||
flac)
|
||||
album=$(metaflac --show-tag=ALBUM "$f" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
title=$(metaflac --show-tag=TITLE "$f" 2>/dev/null | sed -n 's/^[^=]*=//p' | head -1)
|
||||
;;
|
||||
mp3)
|
||||
album=$(id3v2 -l "$f" 2>/dev/null | sed -n 's/^TALB[^:]*: //p' | head -1)
|
||||
title=$(id3v2 -l "$f" 2>/dev/null | sed -n 's/^TIT2[^:]*: //p' | head -1)
|
||||
;;
|
||||
*) continue ;;
|
||||
esac
|
||||
|
||||
if [[ -n "$album" ]]; then
|
||||
continue # already has an album, leave it alone
|
||||
fi
|
||||
if [[ -z "$title" ]]; then
|
||||
log "[skip-no-title] $f"
|
||||
SKIPPED=$((SKIPPED + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
# Some titles have a leading "NN " track-number prefix baked in from a
|
||||
# bad filename parse (e.g. title="01 Domestic Violence"). If we use the
|
||||
# title as-is, the album becomes "01 Domestic Violence - Single" which
|
||||
# is broken. Strip leading 1-3 digits + space, and also fix the title
|
||||
# tag in place so it isn't shown with the prefix in clients.
|
||||
clean_title=$(echo "$title" | sed -E 's/^[[:space:]]*[0-9]{1,3}[[:space:]]+//')
|
||||
if [[ "$clean_title" != "$title" && -n "$clean_title" ]]; then
|
||||
log " trimmed leading track-number from title: \"$title\" -> \"$clean_title\""
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
case "$ext" in
|
||||
flac) metaflac --remove-tag=TITLE --set-tag="TITLE=${clean_title}" "$f" 2>>"$LOG" ;;
|
||||
mp3) id3v2 --TIT2 "${clean_title}" "$f" 2>>"$LOG" ;;
|
||||
esac
|
||||
fi
|
||||
title="$clean_title"
|
||||
fi
|
||||
|
||||
new_album="${title} - Single"
|
||||
log "[$( [[ $APPLY -eq 1 ]] && echo SET || echo WOULD-SET )] album=\"${new_album}\" - $f"
|
||||
|
||||
if [[ $APPLY -eq 1 ]]; then
|
||||
case "$ext" in
|
||||
flac) metaflac --set-tag="ALBUM=${new_album}" "$f" 2>>"$LOG" ;;
|
||||
mp3) id3v2 --TALB "${new_album}" "$f" 2>>"$LOG" ;;
|
||||
esac
|
||||
fi
|
||||
FIXED=$((FIXED + 1))
|
||||
done < <(find ${MUSIC_DATA_DIR:-/data/music}/Library -type f \( -iname "*.flac" -o -iname "*.mp3" \) -print0 2>/dev/null)
|
||||
|
||||
log ""
|
||||
log "=== Summary: $FIXED fixed, $SKIPPED skipped (no title) ==="
|
||||
|
||||
if [[ $APPLY -eq 1 && $FIXED -gt 0 ]]; then
|
||||
log "Syncing beets DB from new tags..."
|
||||
beet update 2>&1 | tail -3 >> "$LOG"
|
||||
log "Moving files to reflect new album in path templates..."
|
||||
beet move 2>&1 | tail -3 >> "$LOG"
|
||||
log "Triggering Navidrome rescan..."
|
||||
curl -s -G "$ND_BASE/rest/startScan.view" \
|
||||
--data-urlencode "u=$ND_USER" \
|
||||
--data-urlencode "p=$ND_PASS" \
|
||||
--data-urlencode 'v=1.16.0' \
|
||||
--data-urlencode 'c=fix-empty-album' \
|
||||
--data-urlencode 'f=json' \
|
||||
--data-urlencode 'fullScan=true' >> "$LOG" 2>&1
|
||||
fi
|
||||
|
||||
log "=== Done. Log: $LOG ==="
|
||||
Reference in New Issue
Block a user