Convert and merge audio files for kid's audio player
This is how I convert and adjust the audio files for the kid's audio player (e.g. hörbert or custom-made). For such kind of audio player, certain adjustments make sense, e.g. convert to mono and normalise (i.e. adjust gain).
Collect all the audio files and radio plays that you want to put on the player. Each radio play into a separate folder.
It may be helpful to put some short audio at the beginning of each radio play containing the name of the play. This can be spoken by yourself or generated using e.g. Apple Automator.
In Automator, use the following two actions to have a text-to-speech-file pipeline:
Automator generates mono .aiff files. They can be converted to 44.1 kHz stereo M4A files using ffmpeg:
ffmpeg -i input.aiff -ar 44100 -ac 2 output.m4a
If you have multiple of those files e.g. in subfolders, do this as a batch (zsh style):
for f in */*.aiff; do ffmpeg -i $f -ar 44100 -ac 2 $f.m4a; done
You can merge several audio files (e.g. all files of one radio play) using ffmpeg:
ffmpeg -f concat -safe 0 -i <(for f in ./*.m4a; do echo "file '$PWD/$f'"; done) -c copy output.m4a
For more details, see https://trac.ffmpeg.org/wiki/Concatenate
Again, if you have several folders and you want to do this as a batch (zsh style):
for f in *(/); do cd $f; ffmpeg -f concat -safe 0 -i <(for f in ./*.m4a; do echo "file '$PWD/$f'"; done) -c copy -vn ../$f.m4a; cd ..; done
For this I also generated a small Automator app. I can then simply drop my audio files on the Automator app and the app will create a mono MP3 version of each file next to the location of the originial file (with -mono suffix).
In Automator, use the "Run Shell Script" Action (using /bin/bash shell and pass input as arguments) and paste the following:
for f in "$@"
do
dirname=$(dirname "$f")
filename=$(basename "$f")
extension="${filename##*.}"
filename="${filename%.*}"
cd "${dirname}"
#FFREPORT="file=monofy.log:level=24"
echo "${filename}.${extension}" >> monofy.log
/usr/local/bin/ffmpeg -i "$f" -codec:a libmp3lame -qscale:a 2 -ac 1 -vn -vsync 2 -loglevel warning "${filename}-mono.mp3" 2>> monofy.log
echo $'\n-------------------------------------------------------------------------------\n\n' >> monofy.log
done
As you can see, the ffmpeg output will be redirected into a monofy.log file.
In case you have files from various sources they probably have different "loudness". You can even out those differences by letting ffmpeg apply its normalisation filters. This way, each file will be adjusted with a certain gain, so that in the end all files should have similar loudness.
ffmpeg has 2 filters for this:
For more details, see https://superuser.com/questions/323119/how-can-i-normalize-audio-using-ffmpeg/323127
If you want to automatically use e.g. dynaudnorm filter, the Automator script from #4 would look like this:
for f in "$@"
do
dirname=$(dirname "$f")
filename=$(basename "$f")
extension="${filename##*.}"
filename="${filename%.*}"
cd "${dirname}"
#FFREPORT="file=monofy.log:level=24"
echo "${filename}.${extension}" >> monofy.log
/usr/local/bin/ffmpeg -i "$f" -codec:a libmp3lame -qscale:a 2 -ac 1 -vn -vsync 2 -af dynaudnorm -loglevel warning "${filename}-mono.mp3" 2>> monofy.log
echo $'\n-------------------------------------------------------------------------------\n\n' >> monofy.log
done
However, the best way to normalise is to do 2 passes: At the first run the loudness of all files (looking for peaks, etc.) should be analysed. At only at the second run the appropriate gain will be set for each file.
For those 2 passes there is the ffmpeg-normalize tool, which completely automates this.
For more details and usage, see https://superuser.com/questions/323119/how-can-i-normalize-audio-using-ffmpeg/323127 (again) or https://github.com/slhck/ffmpeg-normalize