12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- #!/usr/bin/env bash
- set -euo pipefail # bash strict mode
- IFS=$'\n\t'
- display_help(){
- echo "This script converts audio files of specified extensions to another specified extension and maintains directory structure."
- echo "Usage: ${0##*/} -p <output-path> -i <input-extensions> -o <output-extension> [music-path/s]"
- echo "Example: ${0##*/} -p /mnt/16gb_pendrive -i flac,wav,ogg -o mp3 ~/Music/Bjork\ Discography ~/Music/MikeOldfield Discography ..."
- echo "Options: "
- echo -e "\t -i -- Input extensions to search for (default: ${input_ext})"
- echo -e "\t -o -- Output extension to convert to (default: ${output_ext})"
- echo -e "\t -p -- Path to store converted files (default: ${output_path})"
- echo -e "\t -f -- Force overwrite existing files"
- echo -e "\t -h -- Display this help message"
- exit 2
- }
- extract_cover(){
- input_file_path="$1"
- output_file_path="$2"
- # ffmpeg -y -i "$1" -an -vcodec copy "${output_file_path}/cover.jpg"
- find "$input_file_path" -type f -iname "cover*" -exec cp {} "${output_file_path}/" \; || \
- ffmpeg -y -i "$1" -an -vcodec copy "${output_file_path}/cover.jpg"
- }
- cover_present_in(){
- path="$1"
- find "$path" -type f -iregex "\(folder\|cover\)\.\(png\|jpe?g\)"
- }
- ffmpeg_convert(){
- input_file="$1"
- output_file="$2"
- echo "Starting conversion..."
- ffmpeg "${force:--n}" -i "$input_file" \
- -vsync 2 -threads 4 \
- "$output_file" &>/dev/null
- if [[ $? -eq 0 ]]; then
- echo "Converted ${input_file} --> ${output_file}"
- else
- echo "Non zero exit code? Remove &/dev/null"
- fi
- }
- wait_on_max_bg_process(){
- if [[ $(pgrep ffmpeg | wc -w) -ge ${max_processes:-20} ]]; then
- wait $!
- fi
- }
- # default values
- output_path="."
- input_ext=".flac\|.wav\|.ogg\|.m4a"
- output_ext="opus"
- max_processes=10
- while getopts ':p:i:o:fDh' opt; do
- case "$opt" in
- p)output_path="${OPTARG%*/}" ;; # making sure to not end with /
- i)input_ext="${OPTARG//,/\\|}" ;; # substitute "," to "\|" for -regex
- o)output_ext="$OPTARG" ;;
- f)force="-y" ;;
- D)delete_source=1 ;;
- h|\?|:|*) display_help ;;
- esac
- done
- shift $((OPTIND-1)) # next parameters without flags
- # check if nessesary variables are correctly specified
- [[ ! -d $output_path || $# -lt 1 ]] && display_help
- for input_directory in "$@"; do
- [[ ! -d $input_directory ]] && echo "Not a directory: ${input_directory}" && continue
- mapfile -t input_files < <(find "$input_directory" -mount -type f -regex ".*\(${input_ext}\)$")
- for input_file in "${input_files[@]}"; do
- output_file="${output_path}/${input_file%.*}.${output_ext}"
- output_file_path="${output_file%/*}"
- [[ ! -d $output_file_path ]] && mkdir -p "${output_file_path}"
- input_file_path="${input_file%/*}"
- if [[ $output_file_path != "${old_path:-}" && ! $(cover_present_in "$input_file_path") ]]; then
- extract_cover "$input_file" "$output_file_path"
- old_path="$output_file_path"
- fi
- ffmpeg_convert "$input_file" "$output_file" &
- wait_on_max_bg_process
- [[ ${delete_source:-} -eq 1 ]] && rm "$input_file"
- done
- done
- wait
- echo "FINISHED"
|