Skip to content

Instantly share code, notes, and snippets.

@ronau
Created November 26, 2018 19:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ronau/810941080a84e52c29730f19bb15d2c5 to your computer and use it in GitHub Desktop.
Save ronau/810941080a84e52c29730f19bb15d2c5 to your computer and use it in GitHub Desktop.
Convert and merge audio files for kid's audio player

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).

#1 Collect audio files

Collect all the audio files and radio plays that you want to put on the player. Each radio play into a separate folder.

#2 (optionally) Generate introduction audio snippets

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.

#2.1 Audio snippets using Apple Automator

In Automator, use the following two actions to have a text-to-speech-file pipeline:

  • Get specified text (enter here the text you want to have as audio file)
  • Text to Audio File (try out the different voices available, for a voice with good German pronounciation, use "Anna")

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

#3 Merge audio files

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

#4 Convert audio files to mono MP3

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.

#5 Audio normalisation

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:

  • loudnorm
  • dynaudnorm

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

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