Skip to content

Instantly share code, notes, and snippets.

@GwynethLlewelyn
Last active December 19, 2022 14:33
Show Gist options
  • Save GwynethLlewelyn/15a533d4359ee3989e7ea07160f1ae3c to your computer and use it in GitHub Desktop.
Save GwynethLlewelyn/15a533d4359ee3989e7ea07160f1ae3c 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/${ALBUM}"
# 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:
for f in "${ALBUM_PATH}"/*.m4a
do
echo "Before ffprobe... testing ${f}"
bitrate=$(ffprobe -v quiet -of flat=s=_ -show_entries format=bit_rate "${f}" | sed 's/[^0-9]*//g')
new_filename=$(basename "${f}" .m4a).mp3
echo "Reading ${f} and writing to mp3s/${ALBUM}/${new_filename} with bitrate ${bitrate}..."
# echo ffmpeg -y -i "${f}" -codec:a libmp3lame -b:a "${bitrate}" -q:a 2 "mp3s/${ALBUM}/${new_filename}"
ffmpeg -y -i "${f}" -codec:a libmp3lame -b:a "${bitrate}" -q:a 2 "mp3s/${ALBUM}/${new_filename}"
done
Copy link

ghost commented Jul 30, 2022

You might want to change the shebang to a more universal path like /bin/env bash

@GwynethLlewelyn
Copy link
Author

GwynethLlewelyn commented Aug 1, 2022

You might want to change the shebang to a more universal path like /bin/env bash

Thanks for the tip! I've also replaced the pesky backticks...

@GwynethLlewelyn
Copy link
Author

Changed shebang to #!/usr/bin/env bash as per @mashuptwice's suggestion on SuperUser.com

@EmmyGraugans
Copy link

Your ToDo is now done

Thanks for the excellent work, all I did was wrap it in a function and put a find around it to get it to work recursively. I also added a cap to 224k of the bitrate. One note, having looked at the resulting mp3s in my library: I am not entirely sure if the combination of -b:a "${bitrate}" -q:a 2 makes sense. The one tells ffmpeg to use a fixed bitrate of $bitrate, the other tells it to use a VBR of 170-210... I left it in my variant like this however.

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