Skip to content

Instantly share code, notes, and snippets.

@NotWadeGrimridge
Last active April 5, 2025 09:53
Show Gist options
  • Select an option

  • Save NotWadeGrimridge/f7f581f5a0b974930d34f241b712b079 to your computer and use it in GitHub Desktop.

Select an option

Save NotWadeGrimridge/f7f581f5a0b974930d34f241b712b079 to your computer and use it in GitHub Desktop.
AAC converter (Apple Digital Master)
#!/usr/bin/env bash
set -eu
if [[ $# -eq 0 ]]; then
echo "Usage: $0 [-d] [-s] [-o output_dir] files..."
echo "Options:"
echo " -d Delete original files after processing (default: off)"
echo " -s Downsample to 44100 Hz if applicable (default: off)"
echo " -o dir Set output directory (default: aac)"
exit 1
fi
if ! command -v afconvert &>/dev/null; then
echo "Error: afconvert not found. This script only works on macOS." >&2
exit 1
fi
if ! command -v ffprobe &>/dev/null; then
echo "Error: ffprobe not found. Please install it using 'brew install ffmpeg'." >&2
exit 1
fi
if ! command -v ffmpeg &>/dev/null; then
echo "Error: ffmpeg not found. Please install it using 'brew install ffmpeg'." >&2
exit 1
fi
delete_files=false
downsample=false
output_dir="aac"
while getopts "dso:" opt; do
case $opt in
d) delete_files=true ;;
s) downsample=true ;;
o) output_dir="$OPTARG" ;;
*)
echo "Usage: $0 [-d] [-s] [-o output_dir] files..." >&2
exit 1
;;
esac
done
shift "$((OPTIND - 1))"
mkdir -p "$output_dir"
for input in "$@"; do
base_name=$(basename "$input")
echo "Processing: $base_name"
output="$output_dir/${base_name%.*}.m4a"
temp_caf="./.${base_name}.caf"
sample_rate=$(ffprobe -v error -select_streams a:0 -show_entries stream=sample_rate -of default=noprint_wrappers=1:nokey=1 "$input" || echo "0")
if [[ $downsample == true && $sample_rate -gt 44100 ]]; then
temp_args="-d LEI24@44100 --src-complexity bats -r 127"
elif [[ $downsample == false && $sample_rate -gt 48000 ]]; then
temp_args="-d LEF32@48000 --src-complexity bats -r 127"
else
temp_args="-d 0"
fi
afconvert "$input" "$temp_caf" $temp_args -f caff --soundcheck-generate
afconvert "$temp_caf" "$output" -d aac -f m4af -ue pgcm 2 --soundcheck-read -b 256000 -q 127 -s 2
rm -f "$temp_caf"
temp_m4a="./.tmp${base_name}.m4a"
ffmpeg -hide_banner -v error -i "$output" -i "$input" -map 0:a -map_metadata 1 -c:a copy "$temp_m4a" -y
mv "$temp_m4a" "$output"
[[ $delete_files == true ]] && rm -f "$input"
echo "Processed: $output"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment