misc-scripts/albumsetup

197 lines
6.2 KiB
Plaintext
Raw Normal View History

2023-05-03 17:29:22 -05:00
#!/bin/sh
2023-09-21 09:00:45 -05:00
set -eu
2023-05-03 17:29:22 -05:00
EXT="flac" # default
errecho() { echo "$*" >&2 ; }
die() { errecho "$*" && exit 1 ; }
2023-05-03 17:29:22 -05:00
clean() {
2023-09-21 09:00:45 -05:00
trap 'exit' INT HUP QUIT EXIT
[ -f "${DEFAULT_PICTURE:-}" ] && rm -f "$DEFAULT_PICTURE"
2023-09-21 09:00:45 -05:00
[ -f "${COVER_PICTURE:-}" ] && rm -f "$COVER_PICTURE"
[ -f "${JSON:-}" ] && rm -f "$JSON"
2023-05-03 17:29:22 -05:00
}
# wrapper to grab a specific tag from flac/opus/mp3
2023-09-21 09:00:45 -05:00
grab_tag() {
2023-05-03 17:29:22 -05:00
case ${1##*.} in
flac) metaflac --show-tag="$2" -- "$1" | cut -d '=' -f 2- ;;
opus) opusinfo -- "$1" | awk -v RS='\n' -v FS='=' -v OFS='' "/^\\t$2=/"'{$1=""; print $0}' ;;
2023-05-03 17:29:22 -05:00
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.)
2023-09-21 09:00:45 -05:00
grab_info() {
2023-06-13 22:02:04 -05:00
set +e
2023-05-03 17:29:22 -05:00
DURATION="$(ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$1")"
2023-09-21 09:00:45 -05:00
ARTIST="$(grab_tag "$1" ARTIST)"
ALBUM="$(grab_tag "$1" ALBUM)"
TITLE="$(grab_tag "$1" TITLE)"
2023-09-30 20:14:38 -05:00
ALBUMARTIST="$(grab_tag "$1" ALBUMARTIST)"
2023-09-21 09:00:45 -05:00
TRACKNUMBER="$(printf '%03g' "$(grab_tag "$1" TRACKNUMBER)")"
2023-06-13 22:02:04 -05:00
set -e
2023-05-03 17:29:22 -05:00
}
2023-09-21 09:00:45 -05:00
convert_vid() {
ffmpeg -nostdin ${VERBOSE--loglevel error} -y -loop 1 -framerate 4 -f image2 -i "$1" -i "$2" \
2023-09-21 09:00:45 -05:00
-t "$DURATION" \
2023-05-03 17:29:22 -05:00
-pix_fmt yuv420p \
${acopy:--c:a libopus -b:a 256k} \
-r 4 \
-b:v 500k \
-c:v libvpx \
-deadline realtime \
"$3"
errecho "Successfully converted $2"
2023-05-03 17:29:22 -05:00
}
2023-09-21 09:00:45 -05:00
# extracts cover from $1 to $2
# returns 0 if $2 (output) exists, 1 if not
extract_cover() {
set +e
2023-06-13 22:02:04 -05:00
{
case ${1##*.} in
2023-06-25 11:27:38 -05:00
flac) metaflac --export-picture-to="$2" -- "$1" ;;
opus) opustags --output-cover "$2" -- "$1" ;;
mp3) ffmpeg -nostdin -i "$1" -map "0:v:0" -c:v copy "$2" ;;
2023-06-13 22:02:04 -05:00
*) die 'unknown filetype' ;;
esac
2023-12-25 11:42:32 -06:00
} >/dev/null 2>&1
set -e
2023-09-21 09:00:45 -05:00
# resize within the bounds of 1280x720
# if it's square then make it 722x720 so youtube doesn't make it a short
2024-01-24 23:44:09 -06:00
[ -f "$2" ] && vipsthumbnail -o "$2" -s '722x720' -c "$2" || true
2023-09-21 09:00:45 -05:00
}
# sets COVER_PIC for use in convert_vid
set_cover() {
2024-01-24 23:44:09 -06:00
COVER_PICTURE="$(mktemp -u -t XXXXXX.png)"
2023-12-25 11:42:32 -06:00
extract_cover "$1" "$COVER_PICTURE"
if [ -f "$COVER_PICTURE" ]; then
:
2023-09-21 09:00:45 -05:00
elif [ -f "track$TRACKNUMBER.png" ]; then
2023-12-25 11:42:32 -06:00
cp "track$TRACKNUMBER.png" "$COVER_PICTURE"
2023-09-21 09:00:45 -05:00
else
2023-12-25 11:42:32 -06:00
cp "$DEFAULT_PICTURE" "$COVER_PICTURE"
2023-09-21 09:00:45 -05:00
fi
}
2023-09-21 09:00:45 -05:00
# SCRIPT START #
trap 'clean' INT HUP QUIT EXIT
SONG="" BANDCAMP="" NO_CONVERT=""
2023-05-03 17:29:22 -05:00
OUTDIR="/tmp/albumsetup/${PWD##*/}"
2023-09-21 09:00:45 -05:00
while getopts :vnd:e:p:s:b: OPT; do
2023-05-03 17:29:22 -05:00
case "$OPT" in
v) VERBOSE="" ;; # can use ${var-rep} for this
d) cd "$OPTARG" && OUTDIR="${OUTDIR%/*}/${PWD##*/}" ;;
e) EXT="$OPTARG" ;;
2023-09-21 09:00:45 -05:00
p) tmpcover="$OPTARG" ;;
2023-05-03 17:29:22 -05:00
s) SONG="$OPTARG" && OUTDIR="${OUTDIR%/*}" ;; # individual song
b) BANDCAMP="$OPTARG" ;; # bandcamp link to extract data
2023-05-23 21:25:29 -05:00
n) NO_CONVERT=1 ;; # don't convert, just get metadata.txt (only affects default albumsetup)
2023-05-03 17:29:22 -05:00
*) die "albumsetup: invalid option: -$OPTARG" ;;
esac
done
shift "$((OPTIND - 1))"
2023-09-21 09:00:45 -05:00
[ ! -f "$tmpcover" ] && die "Default cover not specified! (-p IMG)"
2023-05-03 17:29:22 -05:00
mkdir -p "$OUTDIR"
2023-09-21 09:00:45 -05:00
# default cover image, fallback if tracks don't have embedded art
2024-01-24 23:44:09 -06:00
DEFAULT_PICTURE="$(mktemp -u -t XXXXXX.png)"
vipsthumbnail -o "$DEFAULT_PICTURE" -s '722x720' -c "$tmpcover"
2023-05-03 17:29:22 -05:00
2023-09-21 09:00:45 -05:00
# copy audio codec if opus since output codec is opus
[ "$EXT" = "opus" ] && acopy="-c:a copy"
2023-05-03 17:29:22 -05:00
# INDIVIDUAL SONG #
2023-06-21 17:08:12 -05:00
if [ -n "$SONG" ]; then
2023-09-21 09:00:45 -05:00
grab_info "$SONG"
set_cover "$SONG"
2023-09-21 09:00:45 -05:00
# lots of %%/* as to not accidentally create directories
convert_vid "$COVER_PICTURE" "$SONG" "$OUTDIR/SONG ${ARTIST%%/*} - ${TITLE%%/*}.webm"
2023-05-03 17:29:22 -05:00
2023-09-21 09:00:45 -05:00
# INDIVIDUAL TRACKS FOR FULL ALBUM + COMPLETE VID #
else
# make a sorted list of the files by tracknumber first
# so that we don't have to do it individually for everything later
2023-09-21 09:00:45 -05:00
for f in ./*."$EXT"; do
grab_info "$f"
printf '%s\t%s\n' "$TRACKNUMBER" "$f"
done | sort | cut -f 2- > "$OUTDIR/tmp_sorted_list"
total_time=0 # this var helps for more precise timestamps
while read -r f; do
2023-09-21 09:00:45 -05:00
grab_info "$f"
set_cover "$f"
output_file="$OUTDIR/$TRACKNUMBER ${ARTIST%%/*} - ${TITLE%%/*}.webm"
2023-05-03 17:29:22 -05:00
2023-09-21 09:00:45 -05:00
# STUFF FOR INDIVIDUAL VID #
errecho "Converting $f"
[ -z "$NO_CONVERT" ] && convert_vid "$COVER_PICTURE" "$f" "$output_file"
rm -f "$COVER_PICTURE"
2023-07-05 23:19:10 -05:00
2023-09-21 09:00:45 -05:00
# metadata print to send to metadata.txt
printf '%s - %s - %s\n' "${ARTIST:-unknown artist}" "${ALBUM:-unknown album}" "${TITLE:-unknown title}" \
>> "$OUTDIR/metadata.txt"
# build ffmpeg concat metadata
# make safe filename for ffmpeg concat; replace all ' with '\''
sf="$(printf '%s' "$output_file" | sed "s/'/'\\\\''/g")"
2023-07-05 23:19:10 -05:00
# tracklist
2023-09-21 09:00:45 -05:00
printf '%02d:%02d:%02d - %s\n' \
"$((${total_time%%.*} / 3600))" "$((${total_time%%.*} % 3600 / 60))" "$((${total_time%%.*} % 60))" \
"$ARTIST - $TITLE" >> "$OUTDIR/metadata_fullvid.txt"
total_time="$(printf '%s\n' "$total_time + $DURATION" | bc)"
2023-07-05 23:19:10 -05:00
printf "file '%s'\n" "$sf" >> "$OUTDIR/ffmpeg_tracklist.txt"
done < "$OUTDIR/tmp_sorted_list"
2023-09-21 09:00:45 -05:00
2023-05-03 17:29:22 -05:00
[ ! -f "$OUTDIR/metadata.txt" ] && die "No files found!"
2023-09-21 09:00:45 -05:00
if [ -z "$NO_CONVERT" ]; then
errecho "Building full video..."
ffmpeg -nostdin -safe 0 -f concat -i "$OUTDIR/ffmpeg_tracklist.txt" -c copy "$OUTDIR/${ALBUMARTIST%%/*} - ${ALBUM%%/*}.webm"
2023-09-21 09:00:45 -05:00
fi
rm "$OUTDIR/ffmpeg_tracklist.txt"
2024-03-19 00:17:07 -05:00
# Bandcamp check and info retrieval
2023-06-21 17:08:12 -05:00
if [ -n "$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"
2023-06-21 17:08:12 -05:00
[ -n "$desc" ] || [ -n "$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-06-25 11:27:38 -05:00
rm -f "$DEFAULT_PICTURE"
2023-05-03 17:29:22 -05:00
fi