misc-scripts/albumsetup

174 lines
5.8 KiB
Plaintext
Raw Normal View History

2023-05-03 17:29:22 -05:00
#!/bin/sh
set -euf
EXT="flac" # default
NL="
"
errecho() { echo "$*" >&2 ; }
die() { errecho "$*" && exit 1 ; }
2023-05-03 17:29:22 -05:00
clean() {
trap 'exit' INT HUP QUIT EXIT
[ -f "${DEFAULT_PICTURE:-}" ] && rm -f "$DEFAULT_PICTURE"
[ -f "${JSON:-}" ] && rm -f "$JSON"
2023-05-03 17:29:22 -05:00
}
# wrapper to grab a specific tag from flac/opus/mp3
grabtag() {
case ${1##*.} in
flac) metaflac --show-tag="$2" "$1" | cut -d '=' -f 2- ;;
opus) opusinfo "$1" | awk -v RS='\n\t' -v FS='=' -v OFS='' "/^$2=/"'{$1=""; print $0}' ;;
mp3)
case "$2" in
ARTIST) id3 -q '%_a' "$1" ;;
ALBUM) id3 -q '%_A' "$1" ;;
TRACKNUMBER) id3 -q '%_###T' "$1" ;;
TITLE) id3 -q '%_t' "$1" ;;
ALBUMARTIST) id3 -2 -q "%|%{TPE2}||%{TXXX:ALBUM ARTIST}|?" "$1" ;;
*) printf 'unknown tag used for mp3' ;;
2023-05-03 17:29:22 -05:00
esac
;;
*) die 'unknown filetype'
2023-05-03 17:29:22 -05:00
esac
}
# grab track info, make tracknumber 3-padded just in case for long albums
# (no album has > 999 tracks. I think.)
grabinfo() {
DURATION="$(ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$1")"
ARTIST="$(grabtag "$1" ARTIST)"
ALBUM="$(grabtag "$1" ALBUM)"
TITLE="$(grabtag "$1" TITLE)"
TRACKNUMBER="$(printf '%03d' "$(grabtag "$1" TRACKNUMBER)")"
}
ffconv() {
IFS=" "
ffmpeg ${VERBOSE--loglevel error} -y -loop 1 -framerate 4 -f image2 -i "$1" ${FULLALBUM:+-safe 0 -f concat} -i "$2" \
-t "${TOTALTIME:-$DURATION}" \
-pix_fmt yuv420p \
${acopy:--c:a libopus -b:a 256k} \
-r 4 \
-b:v 500k \
-c:v libvpx \
-cpu-used -5 \
-deadline realtime \
"$3"
errecho "Successfully converted $2"
2023-05-03 17:29:22 -05:00
}
extract_cover() {
set +e
tmpimg="$(mktemp -u -t ALBUMSETUP_COVER.XXXX)"
case ${1##*.} in
flac) metaflac --export-picture-to="$tmpimg" -- "$1" ;;
opus) opustags --output-cover "$tmpimg" -- "$1" ;;
mp3) ffmpeg -i "$1" -map "0:v:0" -c:v copy "$tmpimg" ;;
*) die 'unknown filetype'
esac
printf '%s' "$tmpimg"
set -e
}
# GET OPTIONS #
SONG="" FULLALBUM="" BANDCAMP=""
2023-05-03 17:29:22 -05:00
OUTDIR="/tmp/albumsetup/${PWD##*/}"
while getopts :ovd:e:p:s:b: OPT; do
2023-05-03 17:29:22 -05:00
case "$OPT" in
o) FULLALBUM=1 ;;
v) VERBOSE="" ;; # can use ${var-rep} for this
d) cd "$OPTARG" && OUTDIR="${OUTDIR%/*}/${PWD##*/}" ;;
e) EXT="$OPTARG" ;;
p) tmpimg="$OPTARG" ;;
s) SONG="$OPTARG" && OUTDIR="${OUTDIR%/*}" ;; # individual song
b) BANDCAMP="$OPTARG" ;; # bandcamp link to extract data
2023-05-03 17:29:22 -05:00
*) die "albumsetup: invalid option: -$OPTARG" ;;
esac
done
shift "$((OPTIND - 1))"
[ ! -f "$tmpimg" ] && die "Default image not specified!"
2023-05-03 17:29:22 -05:00
mkdir -p "$OUTDIR"
# convert cover image. it has to be wider than 1:1 so youtube doesn't convert it to a short
# if image is wider than 1:1, just resize height. if not, pad with black
DEFAULT_PICTURE="$OUTDIR/ALBUMSETUP_IMG.png"
magick convert "$tmpimg" -resize 1280x720 -background black -gravity center -extent 722x720 "$DEFAULT_PICTURE"
2023-05-03 17:29:22 -05:00
trap 'clean' INT HUP QUIT EXIT
2023-05-03 17:29:22 -05:00
[ "$EXT" = "opus" ] && acopy="-c:a copy" # copy audio codec if opus since output codec is opus
# INDIVIDUAL SONG #
2023-05-03 17:29:22 -05:00
if [ "$SONG" ]; then
grabinfo "$SONG"
ffconv "$DEFAULT_PICTURE" "$SONG" "$OUTDIR/SONG ${ARTIST%%/*} - ${TITLE%%/*}.webm" # substitution mods are to not create directories
# CONTINUOUS VIDEO OF WHOLE ALBUM #
2023-05-03 17:29:22 -05:00
elif [ "$FULLALBUM" ]; then
TOTALTIME=0 # keeping track of timestamps
IFS="$NL"
for f in $(fd -d 1 -e "$EXT"); do
grabinfo "$f"
# make timestamp
printf '%02d:%02d:%02d - %s\n' \
"$((${TOTALTIME%%.*} / 3600))" "$((${TOTALTIME%%.*} % 3600 / 60))" "$((${TOTALTIME%%.*} % 60))" \
"$ARTIST - $TITLE" >> "$OUTDIR/metadata.txt"
# add to total time, but this is as a float remember that
TOTALTIME="$(echo "$TOTALTIME + $DURATION" | bc)"
# build ffmpeg concat metadata
sf="$(printf '%s' "$f" | sed "s/'/'\\\\''/g")" # make safe filename for ffmpeg concat; replace all ' with '\''
echo "file '${PWD}/$sf'" >> "$OUTDIR/ffmpeg_tracklist.txt"
done
[ ! -f "$OUTDIR/ffmpeg_tracklist.txt" ] && die "No files found!"
ffconv "$DEFAULT_PICTURE" "$OUTDIR/tracklist.txt" "$OUTDIR/$ARTIST - $ALBUM.webm"
2023-05-03 17:29:22 -05:00
rm "$OUTDIR/ffmpeg_tracklist.txt"
# INDIVIDUAL TRACKS FOR FULL ALBUM (default) #
else
2023-05-03 17:29:22 -05:00
IFS="$NL"
for f in $(fd -d 1 -e "$EXT"); do
grabinfo "$f"
# metadata print
printf '%s %s - %s - %s\n' "${TRACKNUMBER:-000}" "${ARTIST:-unknown artist}" "${ALBUM:-unknown album}" "${TITLE:-unknown title}" >> "$OUTDIR/metadata.txt"
# try making auto pic
tmpimg="$(extract_cover "$f")"
PICTURE="$tmpimg"
[ ! -f "$PICTURE" ] && PICTURE="$(fd -e jpg -e png "^track$TRACKNUMBER")"
[ ! -f "$PICTURE" ] && PICTURE="$DEFAULT_PICTURE"
errecho "Converting $f"
ffconv "$PICTURE" "$f" "$OUTDIR/$TRACKNUMBER ${ARTIST%%/*} - ${TITLE%%/*}.webm"
[ -f "$tmpimg" ] && rm -f "$tmpimg"
2023-05-03 17:29:22 -05:00
done
[ ! -f "$OUTDIR/metadata.txt" ] && die "No files found!"
# sort by correct track numbers then remove track numbers later
sort -o "$OUTDIR/metadata.txt.sorted" "$OUTDIR/metadata.txt"
while read -r line; do
echo "$line" | cut -d ' ' -f 2-
done <"$OUTDIR/metadata.txt.sorted" >"$OUTDIR/metadata.txt"
rm "$OUTDIR/metadata.txt.sorted"
# Bandcamp check and info retrieval
if [ "$BANDCAMP" ]; then
JSON="$(mktemp -t "ALBUMSETUP_JSON.XXXX")"
curl -L -s -o - "$BANDCAMP" | pup 'script[type="application/ld+json"]' 'text{}' > "$JSON"
albumartist="$(jq -r '.byArtist.name' < "$JSON")"
date="$(jq -r '.datePublished' < "$JSON")"
date="$(date -d "$date" -u +'%Y-%m-%d')"
desc="$(jq -r 'if (.description) then .description | gsub("[\\r]"; "") else empty end' <"$JSON")"
creds="$(jq -r 'if (.creditText) then .creditText | gsub("[\\r]"; "") else empty end' <"$JSON")"
{
printf '%s - %s\n\n' "$albumartist" "$ALBUM"
cat "$OUTDIR/metadata.txt"
printf '\nReleased %s\nDOWNLOAD: %s\n\n' "$date" "$BANDCAMP"
[ "$desc" ] || [ "$creds" ] && printf '%s\n' 'Release notes:'
2023-05-20 21:12:08 -05:00
printf '%s\n\n%s' "$desc" "$creds" | sed -e 's/<//g'
} > "$OUTDIR/metadata2.txt"
mv "$OUTDIR/metadata2.txt" "$OUTDIR/metadata.txt"
rm -f "$JSON"
fi
2023-05-03 17:29:22 -05:00
fi