196 lines
5.6 KiB
Bash
196 lines
5.6 KiB
Bash
|
#!/usr/bin/env bash
|
||
|
|
||
|
# This code is thrown together lazily to just work and never be touched again.
|
||
|
# Do NOT try to learn from this piece of shit
|
||
|
|
||
|
check_dep() {
|
||
|
if [ -z "$(command -v "$1")" ]; then
|
||
|
echo "'$1' is required but not installed."
|
||
|
exit 1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
check_deps() {
|
||
|
deps=("ffmpeg" "opusinfo" "xargs")
|
||
|
for dep in "${deps[@]}"; do
|
||
|
check_dep "$dep"
|
||
|
done
|
||
|
}
|
||
|
|
||
|
args() {
|
||
|
while [ -n "$1" ];do
|
||
|
case "$1" in
|
||
|
"help")
|
||
|
printf "\n\
|
||
|
arguments:\n\
|
||
|
in [input directory] (required) <The flac directory> {default: none}\n\
|
||
|
out [output directory] (required) <The opus directory> {default: none}\n\
|
||
|
verify [on/off] (optional) <Check converted files for corruption> {default: on}
|
||
|
vbr [on/off] (optional) <Toggle variable bit rate> {default: on}
|
||
|
bitrate [{bitrate}k] (optional) <Set the bitrate to be passed to ffmpeg> {default: 128k}\n\n"
|
||
|
exit 0
|
||
|
;;
|
||
|
"in")
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "option '$1' requires an additional argument."
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
INPUT_DIR="$(realpath "$2")"
|
||
|
shift
|
||
|
;;
|
||
|
"out")
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "option '$1' requires an additional argument."
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
OUTPUT_DIR="$(realpath "$2")"
|
||
|
shift
|
||
|
;;
|
||
|
"vbr")
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "option '$1' requires an additional argument."
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
if [ "$2" != "on" ] && [ "$2" != "off" ]; then
|
||
|
echo "Invalid option '$2' for $1. Only accepted options are 'on' or 'off'."
|
||
|
exit 1
|
||
|
fi
|
||
|
VBR="$2"
|
||
|
shift
|
||
|
;;
|
||
|
"verify")
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "option '$1' requires an additional argument."
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
if [ "$2" != "on" ] && [ "$2" != "off" ]; then
|
||
|
echo "Invalid option '$2' for $1. Only accepted options are 'on' or 'off'."
|
||
|
exit 1
|
||
|
fi
|
||
|
VERIFY="$2"
|
||
|
shift
|
||
|
;;
|
||
|
"bitrate")
|
||
|
if [ -z "$2" ]; then
|
||
|
echo "option '$1' requires an additional argument."
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
BITRATE="$2"
|
||
|
if [[ ! $2 =~ ^[0-9]+k$ ]]; then
|
||
|
echo "Invalid bitrate '$2', only accepts string matching pattern '[0-9]\\+k'"
|
||
|
fi
|
||
|
|
||
|
shift
|
||
|
;;
|
||
|
*)
|
||
|
echo "Invalid argument '$1', skipping"
|
||
|
;;
|
||
|
esac
|
||
|
shift
|
||
|
done
|
||
|
|
||
|
if [ -z "$INPUT_DIR" ]; then
|
||
|
echo "Missing input directory"
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
if [ -z "$OUTPUT_DIR" ]; then
|
||
|
echo "Missing input directory"
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
if [ -z "$BITRATE" ]; then
|
||
|
BITRATE="128k"
|
||
|
fi
|
||
|
|
||
|
if [ -z "$VBR" ]; then
|
||
|
VBR="on"
|
||
|
fi
|
||
|
|
||
|
if [ -z "$VERIFY" ]; then
|
||
|
VERIFY="on"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
get_total_count() {
|
||
|
local -n ref_total_count="$2"
|
||
|
total_count="$ref_total_count"
|
||
|
|
||
|
local dir="$1"
|
||
|
for item in "$dir"/*; do
|
||
|
if [ -f "$item" ]; then
|
||
|
new_file="${item/"$INPUT_DIR"/"$OUTPUT_DIR"}"
|
||
|
new_file="${new_file/".flac"/".opus"}"
|
||
|
if [ ! -f "$new_file" ] && [[ "$item" == *".flac" ]]; then
|
||
|
((total_count+=1))
|
||
|
elif [[ "$item" == *".flac" ]]; then
|
||
|
if [ "$VERIFY" = "on" ]; then
|
||
|
printf "Checking \e[93m'%s'\e[0m: " "$(basename "$new_file")"
|
||
|
if ! opusinfo "$new_file" > /dev/null 2>&1; then
|
||
|
((total_count+=1))
|
||
|
printf "\e[31mbad\e[0m\n"
|
||
|
rm "$new_file"
|
||
|
else
|
||
|
printf "\e[32mgood\e[0m\n"
|
||
|
fi
|
||
|
fi
|
||
|
fi
|
||
|
elif [ -d "$item" ]; then
|
||
|
get_total_count "$item" "total_count"
|
||
|
fi
|
||
|
done
|
||
|
}
|
||
|
|
||
|
iterate_dirs() {
|
||
|
local dir="$1"
|
||
|
local conversions=()
|
||
|
local -n ref_count="$2"
|
||
|
local total_count="$3"
|
||
|
count="$ref_count"
|
||
|
for item in "$dir"/*; do
|
||
|
item="${item/\$/"\\$"}"
|
||
|
if [ -f "$item" ]; then
|
||
|
new_file="${item/"$INPUT_DIR"/"$OUTPUT_DIR"}"
|
||
|
new_file="${new_file/".flac"/".opus"}"
|
||
|
if [ ! -f "$new_file" ]; then
|
||
|
if [[ "$item" == *".flac" ]]; then
|
||
|
((count+=1))
|
||
|
conversions+=("printf '[%s/%s] \e[92m%s\e[0m -> \e[93m%s\e[0m\n' $count $total_count \
|
||
|
\"$item\" \"$new_file\" && ffmpeg -hide_banner -loglevel error -i \"$item\" -vbr \"$VBR\" -b:a \"$BITRATE\" \"$new_file\" > /dev/null")
|
||
|
else
|
||
|
echo "Copied $(basename "$item")"
|
||
|
cp -f "$item" "$new_file"
|
||
|
fi
|
||
|
fi
|
||
|
elif [ -d "$item" ]; then
|
||
|
new_dir="${item/"$INPUT_DIR"/"$OUTPUT_DIR"}"
|
||
|
mkdir -p "$new_dir"
|
||
|
iterate_dirs "$item" "count" "$total_count"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
if [ ${#conversions[@]} -gt 0 ]; then
|
||
|
printf '%s\0' "${conversions[@]}" | xargs -0 -P "$(nproc)" -I {} bash -c '{}'
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
main () {
|
||
|
check_deps
|
||
|
|
||
|
args "$@"
|
||
|
|
||
|
count="0"
|
||
|
total_count="0"
|
||
|
get_total_count "$INPUT_DIR" "total_count"
|
||
|
iterate_dirs "$INPUT_DIR" "count" "$total_count"
|
||
|
}
|
||
|
|
||
|
set -e
|
||
|
main "$@"
|
||
|
|