FFmpeg Matching decibel level between two audio tracks when mixing?

459 Views Asked by At

I have a collection of mp3 files for various frequencies (i.e. 528hz). I also have a collection of mp3's of ambient background music. So here is the scenario:

I am mixing the tone frequency mp3's with the music mp3's. This works great using the amix filter, no problem. However, some of the ambient music is quiet, which makes the tones sound overpowering. Conversely, some of the ambient music is also fairly loud, making the tones inaudible.

It seems to me, the solution would be to adjust the volume of the tone to match the decibel level of the associated music track. How can this be done programmatically? Perhaps parsing the output of a ffprobe call, but at that point I wouldn't quite be sure how to proceed towards my goal. I figured reaching out on Super User might save me a ton of pain, by turning to more experienced ffmpeg users. Maybe my approach is also flawed, and would be happy if someone can suggest a better method to achieve what I am looking for.

Here is my python code so far.

import ffmpeg
import os

tones = os.listdir('tones')
songs = os.listdir('music')

for tone in tones:
    for song in songs:
        tone_in = ffmpeg.input(f'tones/{tone}', stream_loop=-1)
        music_in = ffmpeg.input(f'music/{song}')
        mixed = ffmpeg.filter([tone_in, music_in], 'amix', inputs=2, duration='shortest')
        out = ffmpeg.output(mixed, f'output/{tone} {song}.mp3')
        out.run()
1

There are 1 best solutions below

0
On

I ran both the tone and music tracks through the same audio normalization filter, and have achieved what I was looking for. Can tweak the values a bit more, but this is absolutely what I needed to be doing.

Updated python code:

import ffmpeg
import os

tones = os.listdir('tones')
songs = os.listdir('music')

for tone in tones:
    for song in songs:
        tone_in = ffmpeg.input(f'tones/{tone}', stream_loop=-1)
        tone_in = ffmpeg.filter(tone_in, 'loudnorm', I=-16, LRA=11, TP=-1.5)
        music_in = ffmpeg.input(f'music/{song}')
        music_in = ffmpeg.filter(music_in, 'loudnorm', I=-16, LRA=11, TP=-1.5)
        mixed = ffmpeg.filter([tone_in, music_in], 'amix', inputs=2, duration='shortest')
        out = ffmpeg.output(mixed, f'output/{tone} {song}.mp3')
        out.run()