Initial commit: susan automation scripts
Overnight transcoding, music discovery/import, system health reports, stats page generator, and bookmark management. Secrets stored in /etc/automation/ — not in repo.
This commit is contained in:
Executable
+131
@@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
# Import, transcode, and organize music from slskd downloads
|
||||
# Usage: ./import_music.sh [--dry-run] [--keep-flac]
|
||||
|
||||
INGEST_DIR="/disks/Plex/Music/_ingest"
|
||||
LIBRARY_DIR="/disks/Plex/Music"
|
||||
GROUP="mediaserver"
|
||||
BITRATE="128k"
|
||||
|
||||
DRY_RUN=false
|
||||
KEEP_FLAC=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--dry-run) DRY_RUN=true ;;
|
||||
--keep-flac) KEEP_FLAC=true ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "=== Music Import Started ==="
|
||||
$DRY_RUN && echo "DRY RUN MODE"
|
||||
|
||||
# Skip these directories
|
||||
shopt -s extglob
|
||||
|
||||
cd "$INGEST_DIR" || exit 1
|
||||
|
||||
for album_dir in */; do
|
||||
[[ ! -d "$album_dir" ]] && continue
|
||||
dir_name="${album_dir%/}"
|
||||
|
||||
# Skip special dirs
|
||||
[[ "$dir_name" == "incomplete" ]] && continue
|
||||
[[ "$dir_name" == "downloads" ]] && continue
|
||||
|
||||
# Count audio files
|
||||
audio_count=$(ls -1 "$album_dir"*.flac "$album_dir"*.mp3 "$album_dir"*.opus 2>/dev/null | wc -l)
|
||||
[[ $audio_count -lt 2 ]] && continue
|
||||
|
||||
echo ""
|
||||
echo "Processing: $dir_name ($audio_count files)"
|
||||
|
||||
# Get first audio file for metadata
|
||||
first_file=$(ls "$album_dir"*.flac "$album_dir"*.mp3 2>/dev/null | head -1)
|
||||
[[ -z "$first_file" ]] && continue
|
||||
|
||||
# Extract metadata
|
||||
artist=$(ffprobe -v quiet -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 "$first_file" 2>/dev/null)
|
||||
album_artist=$(ffprobe -v quiet -show_entries format_tags=album_artist -of default=noprint_wrappers=1:nokey=1 "$first_file" 2>/dev/null)
|
||||
album=$(ffprobe -v quiet -show_entries format_tags=album -of default=noprint_wrappers=1:nokey=1 "$first_file" 2>/dev/null)
|
||||
|
||||
# Prefer album_artist over artist
|
||||
[[ -n "$album_artist" ]] && artist="$album_artist"
|
||||
|
||||
# Clean for filesystem
|
||||
artist=$(echo "$artist" | tr -d '<>:"/\\|?*' | sed 's/\.$//')
|
||||
album=$(echo "$album" | tr -d '<>:"/\\|?*' | sed 's/\.$//')
|
||||
|
||||
if [[ -z "$artist" ]] || [[ -z "$album" ]]; then
|
||||
echo " ⚠ Missing metadata, skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
dest_dir="$LIBRARY_DIR/$artist/$album"
|
||||
echo " → $artist / $album"
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo " [DRY RUN] Would transcode to $dest_dir"
|
||||
continue
|
||||
fi
|
||||
|
||||
mkdir -p "$dest_dir"
|
||||
|
||||
# Transcode FLACs
|
||||
for flac in "$album_dir"*.flac "$album_dir"*.FLAC; do
|
||||
[[ ! -f "$flac" ]] && continue
|
||||
|
||||
base=$(basename "$flac")
|
||||
# Remove .flac extension properly
|
||||
name="${base%.[Ff][Ll][Aa][Cc]}"
|
||||
opus_out="$dest_dir/${name}.opus"
|
||||
|
||||
echo " Transcoding: $name"
|
||||
ffmpeg -hide_banner -loglevel error -i "$flac" \
|
||||
-c:a libopus -b:a "$BITRATE" -vbr on \
|
||||
-map_metadata 0 -y "$opus_out"
|
||||
|
||||
[[ -f "$opus_out" ]] && chgrp "$GROUP" "$opus_out" 2>/dev/null
|
||||
done
|
||||
|
||||
# Remove any FLACs from destination (we only want Opus there)
|
||||
for flac in "$dest_dir"/*.flac "$dest_dir"/*.FLAC; do
|
||||
[[ -f "$flac" ]] && rm "$flac"
|
||||
done
|
||||
|
||||
# Copy non-FLAC audio
|
||||
for audio in "$album_dir"*.mp3 "$album_dir"*.m4a "$album_dir"*.ogg; do
|
||||
[[ -f "$audio" ]] && cp "$audio" "$dest_dir/"
|
||||
done
|
||||
|
||||
# Copy artwork
|
||||
for art in "$album_dir"*.jpg "$album_dir"*.png "$album_dir"cover.* "$album_dir"folder.*; do
|
||||
[[ -f "$art" ]] && cp "$art" "$dest_dir/"
|
||||
done
|
||||
|
||||
# Fix permissions
|
||||
chgrp -R "$GROUP" "$dest_dir" 2>/dev/null
|
||||
chmod -R g+rw "$dest_dir" 2>/dev/null
|
||||
|
||||
# Run beets for tagging
|
||||
echo " Running beets..."
|
||||
beet import -q "$dest_dir" 2>/dev/null
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo " ✓ Beets tagging complete"
|
||||
else
|
||||
echo " ⚠ Beets tagging skipped or failed (check manually)"
|
||||
fi
|
||||
|
||||
# Verify
|
||||
new_count=$(ls -1 "$dest_dir"/*.opus "$dest_dir"/*.mp3 2>/dev/null | wc -l)
|
||||
if [[ $new_count -ge 3 ]]; then
|
||||
echo " ✓ Imported $new_count files"
|
||||
rm -rf "$INGEST_DIR/$dir_name"
|
||||
echo " ✓ Cleaned source"
|
||||
else
|
||||
echo " ✗ Verification failed"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
Reference in New Issue
Block a user