feat: add flac2opus_collection.bash

This commit is contained in:
caem 2024-04-12 15:51:46 +02:00
commit 66c860bcc5
No known key found for this signature in database
GPG key ID: 3BCEDBB0C38805DA
2 changed files with 220 additions and 0 deletions

25
README.md Normal file
View file

@ -0,0 +1,25 @@
# scripts
This repository contains some of my scripts. Feel free to use, modify or share as you wish.
Quality of the script and or code might or might not be questionable. I am not responsible
for any accidental rimraffing of your home or any other directories nor for any other damage.
## Index
### `flac2opus_collection.bash`
This script converts a copy of a directory containing `.flac` files and converts them all to opus.
The source folder remains unmodified and the whole directory structure, including non-flac files, will
be simply copied over to the output directory. This serves the purpose of being able to compress
your whole lossless library to copy over to devices which are storage limited and or unable to playback
the lossless files at a quality where they are distinguishable from the compressed files.
#### Overview of arguments
```
arguments:
in [input directory] (required) <The flac directory> {default: none}
out [output directory] (required) <The opus directory> {default: none}
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}
```

195
flac2opus_collection.bash Executable file
View file

@ -0,0 +1,195 @@
#!/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 "$@"