From b7ef29a8886a57aadb787807a7c6cf74c1f0ed3a Mon Sep 17 00:00:00 2001 From: anand Date: Wed, 17 Dec 2025 15:57:55 +0530 Subject: Nixos --- rmpc/utils/fetch_album_lyrics.sh | 109 +++++++++++++++++++++++++++++++++++++++ rmpc/utils/tag_genres.sh | 38 ++++++++++++++ rmpc/utils/tag_music.sh | 38 ++++++++++++++ 3 files changed, 185 insertions(+) create mode 100755 rmpc/utils/fetch_album_lyrics.sh create mode 100755 rmpc/utils/tag_genres.sh create mode 100755 rmpc/utils/tag_music.sh (limited to 'rmpc/utils') diff --git a/rmpc/utils/fetch_album_lyrics.sh b/rmpc/utils/fetch_album_lyrics.sh new file mode 100755 index 0000000..cfc0d90 --- /dev/null +++ b/rmpc/utils/fetch_album_lyrics.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: fetch_album_lyrics_simple.sh "/path/to/Artist/Album" +# Example: fetch_album_lyrics_simple.sh "$HOME/Music/mpd/Anderson .Paak/Ventura" + +LRCLIB_API="https://lrclib.net/api/get" + +if [ $# -ne 1 ]; then + echo "Usage: $0 \"/path/to/Artist/Album\"" + exit 1 +fi + +ALBUM_DIR="$1" +if [ ! -d "$ALBUM_DIR" ]; then + echo "Error: '$ALBUM_DIR' is not a directory." + exit 1 +fi + +ARTIST="$(basename "$(dirname "$ALBUM_DIR")")" +ALBUM="$(basename "$ALBUM_DIR")" + +# Try to fetch synced lyrics (only the [mm:ss.xx] lines) for a given title +# Arguments: +# $1 = artist +# $2 = album +# $3 = title_to_try +# Returns stdout = JSON .syncedLyrics (or "null"/empty) +get_lyrics_for() { + local artist="$1" + local album="$2" + local title_try="$3" + + curl -sG \ + --data-urlencode "artist_name=${artist}" \ + --data-urlencode "track_name=${title_try}" \ + --data-urlencode "album_name=${album}" \ + "$LRCLIB_API" \ + | jq -r '.syncedLyrics' +} + +# Attempt a single fetch: +# 1) Try with TITLE_RAW (may include “(feat ...)”) +# 2) If that yields "" or "null", strip “(…)" and retry +# 3) If still no lyrics, give up +# 4) If we do get lyrics, write them verbatim to the .lrc file +# +# Arguments: +# $1 = ARTIST +# $2 = ALBUM +# $3 = TITLE_RAW +# $4 = OUTPUT_LRC_FILE (full path, e.g. /.../Song.lrc) +fetch_for_plain() { + local artist="$1" + local album="$2" + local title_try="$3" + local out_lrc="$4" + + # 1. First-pass lookup + local lyrics + lyrics="$(get_lyrics_for "$artist" "$album" "$title_try")" + + # 2. If empty or "null", try stripping "(...)" from title + if [ -z "$lyrics" ] || [ "$lyrics" == "null" ]; then + local stripped + stripped="$(echo "$title_try" | sed -E 's/ *\([^)]*\)//g')" + if [ "$stripped" != "$title_try" ]; then + title_try="$stripped" + lyrics="$(get_lyrics_for "$artist" "$album" "$title_try")" + fi + fi + + # 3. If still empty/null → skip + if [ -z "$lyrics" ] || [ "$lyrics" == "null" ]; then + echo "✗ No lyrics for: \"$title_try\"" + return 1 + fi + + # 4. Write only the synced‐lyrics lines (timestamps + text) + # We drop any existing [ar:], [al:], [ti:] lines from the API payload, + # but typically lrclib returns only timestamped lines anyway. + echo "$lyrics" | sed -E '/^\[(ar|al|ti):/d' > "$out_lrc" + echo "✔ Saved lyrics: $(basename "$out_lrc")" + return 0 +} + +echo "▶ Fetching lyrics for all .mp3 in: $ALBUM_DIR" +echo " Artist: $ARTIST" +echo " Album: $ALBUM" +echo + +shopt -s nullglob +for mp3 in "$ALBUM_DIR"/*.mp3; do + TITLE_RAW="$(basename "$mp3" .mp3)" + LRC_FILE="${mp3%.mp3}.lrc" + + if [ -f "$LRC_FILE" ]; then + echo "– Skipping \"$TITLE_RAW\" (already have .lrc)" + continue + fi + + if ! fetch_for_plain "$ARTIST" "$ALBUM" "$TITLE_RAW" "$LRC_FILE"; then + # a failure just prints the “No lyrics for…” message and moves on + continue + fi +done + +echo +echo "Done." diff --git a/rmpc/utils/tag_genres.sh b/rmpc/utils/tag_genres.sh new file mode 100755 index 0000000..9d1e012 --- /dev/null +++ b/rmpc/utils/tag_genres.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +if [[ $# -ne 1 ]]; then + echo "Usage: $0 " + exit 1 +fi + +DIR="$1" + +cd "$DIR" || { echo "❌ Failed to navigate to $DIR"; exit 1; } + +# Get all mp3s sorted by eyeD3 track number +FILES=() +while IFS= read -r line; do + FILES+=("$line") +done < <( + for f in *.mp3; do + track_num=$(eyeD3 "$f" 2>/dev/null | grep -i "^track:" | awk '{print $2}' | cut -d/ -f1) + printf "%03d|%s\n" "${track_num:-999}" "$f" + done | sort | cut -d'|' -f2 +) + +for file in "${FILES[@]}"; do + [[ -f "$file" ]] || continue + + echo "" + echo "🎵 Now tagging: $file" + eyeD3 "$file" | grep -Ei "title:|track:|genre:" + + read -rp "Enter genre(s) for this track (comma-separated): " genre + + if [[ -n "$genre" ]]; then + eyeD3 --genre="$genre" "$file" + echo "✅ Set genre to: $genre" + else + echo "⏭️ Skipped (no genre entered)" + fi +done diff --git a/rmpc/utils/tag_music.sh b/rmpc/utils/tag_music.sh new file mode 100755 index 0000000..32e3b2c --- /dev/null +++ b/rmpc/utils/tag_music.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +ARTIST="Anderson .Paak" +ALBUM="Oxnard" +DIR="$HOME/Music/mpd/Anderson .Paak/Oxnard" + +declare -a TRACKS=( + "The Chase (feat. Kadhja Bonet)" + "Headlow (feat. Norelle)" + "Tints (feat. Kendrick Lamar)" + "Who R U?" + "6 Summers" + "Saviers Road" + "Smile⧸Petty (feat. Sonyae Elise)" + "Mansa Musa (feat. Dr. Dre & Cocoa Sarai)" + "Brother's Keeper (feat. Pusha T)" + "Anywhere (feat. Snoop Dogg & The Last Artful, Dodgr)" + "Trippy (feat. J. Cole)" + "Cheers (feat. Q-Tip)" + "Sweet Chick (feat. BJ The Chicago Kid)" + "Left To Right" +) + +cd "$DIR" || { echo "❌ Failed to navigate to $DIR"; exit 1; } + +# Iterate over the tracks and apply metadata +for i in "${!TRACKS[@]}"; do + track_num=$((i + 1)) + title="${TRACKS[$i]}" + filename="$title.mp3" + + if [[ -f "$filename" ]]; then + echo "✅ Tagging: $filename" + eyeD3 -a "$ARTIST" -A "$ALBUM" -t "$title" -n "$track_num" "$filename" + else + echo "⚠️ File not found: $filename" + fi +done -- cgit v1.2.3