Skip to content

Instantly share code, notes, and snippets.

@EmmyGraugans
Forked from GwynethLlewelyn/m4atomp3.sh
Last active February 24, 2024 03:32
Show Gist options
  • Save EmmyGraugans/40c1f1e3c91f48a353b4bfd46a1bd5c6 to your computer and use it in GitHub Desktop.
Save EmmyGraugans/40c1f1e3c91f48a353b4bfd46a1bd5c6 to your computer and use it in GitHub Desktop.
Converts M4A to MP3 respecting the original bitrate (uses ffmpeg)
#!/usr/bin/env bash
# Takes a directory as parameter and converts everything inside it
# from M4A to MP3, respecting the bitrate, and creating a directory
# for the converted files.
#
# MIT Licensed by Gwyneth Llewelyn (2022)
#
# Based on https://superuser.com/a/1211902/127382 by @jbowman (2017)
if [ -d "${1}" ]
then
echo "Doing conversions from directory \"${1}\"..."
else
echo "Source directory not found! Please add it as a parameter, e.g.:"
echo " ${0} path/to/album/containing/mp3/files"
exit 1
fi
# Get the album's name from the first parameter
ALBUM_PATH="${1}"
ALBUM=$(basename "${ALBUM_PATH}")
echo "Attempting to process album \"${ALBUM}\" in source directory
\"${ALBUM_PATH}\"..."
# Create a directory for this run
mkdir -p "mp3s"
# Check if mkdir succeeded
if [[ $? -ne 0 ]]
then
echo "Could not create directory mp3s/${ALBUM} for output. Exiting..."
exit 2
fi
# Loop across the filnames in that directory that end in *.m4a, invoke
# ffprobe to extract the bitrate, then use ffmpeg to convert it into MP3
# and place the result inside the mp3s/${ALBUM}/ directory:
transcode_file() {
f=$1
p=${f%/*}
ALBUM=${p##*/}
[ -d "mp3s/$ALBUM" ] || {
echo "====================================="
echo "starting album $ALBUM"
echo "====================================="
mkdir "mp3s/$ALBUM"
}
orgbitrate=$(ffprobe -v quiet -of flat=s=_ -show_entries format=bit_rate "${f}" | sed 's/[^0-9]*//g')
[[ orgbitrate > 229376 ]] && bitrate=224k || bitrate=$orgbitrate
new_filename=$(basename "${f}" .m4a).mp3
printf "Reading %s\n\tand writing to %s\n\twith bitrate %s... (original: %s)\n" \
"$f" "mp3s/${ALBUM}/${new_filename}" "$bitrate" "$((orgbitrate / 1024))k"
ffmpeg -v warning -y -i "${f}" -codec:a libmp3lame -b:a "${bitrate}" -q:a 2 "mp3s/${ALBUM}/${new_filename}"
}
find ${ALBUM_PATH} -name "*.m4a" | while read m4a
do
transcode_file "$m4a" < /dev/null
done
@innocente205
Copy link

Use default=nk=1:nw=1 (no key, no wrappers) in place of flat=s=_ in the -of (output format) for ffprobe to get only the value and remove the need for the sed substitution.

ffprobe -v quiet -of default=nk=1:nw=1 -show_entries format=bit_rate "${f}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment