slhck / ffmpeg-normalize

Audio Normalization for Python/ffmpeg
MIT License
1.28k stars 118 forks source link

Normalize entire music library at same volume #243

Closed blastbeng closed 1 year ago

blastbeng commented 1 year ago

Hello, I have a big music library, a lot of songs have different volume levels, I am trying to use ffmpeg-normalize API to normalize all my mp3 files to the same volume level

this is what I have done so far:

import os
import sys
import shutil
import subprocess
from mutagen.mp3 import MP3
from ffmpeg_normalize import FFmpegNormalize

def usage():
    print("Usage:")
    print("    python normalizemp3.py /path/to/dir")
    exit()

if len(sys.argv) == 1:
    print("Error! Please specify a valid directory.")
    usage()
elif not os.path.isdir(str(sys.argv[1])):
    print("Error! Given directory does not exist.")
    usage()
elif len(sys.argv) != 2:
    print("Error! Wrong number of arguments.")
    usage()

def normalize(mp3file, tmpfile):
    f = MP3(tmpfile)
    normalizer = FFmpegNormalize(progress=True, audio_codec="libmp3lame", audio_bitrate=f.info.bitrate, sample_rate=f.info.sample_rate)
    normalizer.add_media_file(tmpfile, mp3file)
    normalizer.run_normalization()

def check_volume(mp3file):
    command = ['ffmpeg', '-hide_banner', '-i', str(mp3file), '-filter:a', 'volumedetect', '-f', 'null', '/dev/null']
    commandout = subprocess.run(command, check=True, capture_output=True).stderr
    result = commandout.decode('utf-8').split('\n')
    for element in result:
        if "mean_volume" in element:
            mean_volume = (element.split("mean_volume: ",1)[1]).replace(" dB", "")
            print("mean_volume", mean_volume)
        elif"max_volume" in element:
            max_volume = (element.split("max_volume: ",1)[1]).replace(" dB", "")
            print("max_volume", max_volume)
    #TODO How to determine highest volume to check if i have to elaborate this mp3 file!????
    return True

def start(dir: str):
    for file in os.listdir(dir):
        d = os.path.join(dir, file)
        if os.path.isdir(d):
            print(d)
            start(d)
        elif file.endswith(".mp3"):
            mp3file = os.path.join(dir, file)
            print(mp3file)
            if check_volume(mp3file):
                tmpfile = os.path.join(dir, file) + ".tmp"
                shutil.move(mp3file, tmpfile)
                normalize(mp3file, tmpfile)
                os.remove(tmpfile)

start(sys.argv[1])

But still, I don't see any difference normalizing different audio files and I don't really understand how normalization works. Can anyone tell me what's wrong with this code and How to normalize all my files to the same volume level?

Thanks

slhck commented 1 year ago

Before I dig into this, have you read this part of the README?

https://github.com/slhck/ffmpeg-normalize#should-i-use-this-to-normalize-my-music-collection

blastbeng commented 1 year ago

Okay, sorr but i have missed that part

I think I'll use mp3gain then

By the way I have found this: https://github.com/chaudum/rgain3

Maybe it will be useful for someone else