200 lines
6 KiB
Bash
Executable file
200 lines
6 KiB
Bash
Executable file
#!/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"/".oga"}"
|
|
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
|
|
local item="$(echo "$item" | sed "s/'/'\\\\'/g")"
|
|
if [ -f "$item" ]; then
|
|
new_file="${item/"$INPUT_DIR"/"$OUTPUT_DIR"}"
|
|
new_file="${new_file/.flac/.oga}"
|
|
if [ ! -f "$new_file" ]; then
|
|
if [[ "$item" == *".flac" ]]; then
|
|
((count+=1))
|
|
new_file="${new_file/".flac"/".oga"}"
|
|
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' -map_metadata 0 -map_metadata 0:s:0 -id3v2_version 3 -c:a libopus \
|
|
-vbr \"$VBR\" -b:a \"$BITRATE\" '$new_file' > /dev/null")
|
|
else
|
|
new_dir=$(dirname "${item/"$INPUT_DIR"/"$OUTPUT_DIR"}")
|
|
if [ ! -d "$new_dir" ]; then
|
|
mkdir -p "$new_dir"
|
|
fi
|
|
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"
|
|
}
|
|
|
|
main "$@"
|
|
|