Search code examples
pythonglobpydub

How to join multiple mp3 files?


Reading other questions I was wondering how to join multiple mp3 files like this. I tried this code but I'm getting as an output just the 2 latest mp3 files in the output.mp3... The expected output should be all the files into 1 mp3 file.

from pydub import AudioSegment
from os import getcwd
import glob

cwd = (getcwd()).replace(chr(92), '/')
export_path = f'{cwd}/result.mp3'

MP3_FILES = glob.glob(pathname=f'{cwd}/*.mp3', recursive=True)
silence = AudioSegment.silent(duration=15000)
count, lenght = 0, len(MP3_FILES)

for n, mp3_file in enumerate(MP3_FILES):
    mp3_file = mp3_file.replace(chr(92), '/')
    print(n, mp3_file)

    count += 1
    if count == 1:
        # We get here upon fetching the first audio file from the list.
        # So we load it into `audio1`
        audio1 = AudioSegment.from_mp3(mp3_file)
        print('audio1')

    elif count == 2:
        # We get here upon fetching the second audio file from the list.
        # So we load it into `audio2`
        audio2 = AudioSegment.from_mp3(mp3_file)
        print('audio2')

    elif count == 3:
        # We get here upon fetching the THIRD audio file from the list.
        # Instead of loading it, we SET `res` to the sum of `audio1+silence+audio2`
        # We don't do anything with the third file, in fact we skip it
        #
        res = (audio1 + silence + audio2)
        print('Merging')

        # Here we reset `count`, so we basically start over the same cycle:
        #  - read the NEXT two audio files, skip the third, and REPLACE `res` to the NEW sum
        #    of the current `audio1`/`audio2` files
        count = 0

    if (n + 1) == lenght:
        res.export(export_path, format='mp3')
        print('\ndone!')

Solution

  • From what I can see, there is an issue with looping. I am commenting below the original code (just the for loop though) to give some insights:

    for n, mp3_file in enumerate(MP3_FILES):
        mp3_file = mp3_file.replace(chr(92), '/')
        print(n, mp3_file)
    
        count += 1
        if count == 1:
            # We get here upon fetching the first audio file from the list.
            # So we load it into `audio1`
            audio1 = AudioSegment.from_mp3(mp3_file)
            print('audio1')
    
        elif count == 2:
            # We get here upon fetching the second audio file from the list.
            # So we load it into `audio2`
            audio2 = AudioSegment.from_mp3(mp3_file)
            print('audio2')
    
        elif count == 3:
            # We get here upon fetching the THIRD audio file from the list.
            # Instead of loading it, we SET `res` to the sum of `audio1+silence+audio2`
            # We don't do anything with the third file, in fact we skip it
            #
            res = (audio1 + silence + audio2)
            print('Merging')
    
            # Here we reset `count`, so we basically start over the same cycle:
            #  - read the NEXT two audio files, skip the third, and REPLACE `res` to the NEW sum
            #    of the current `audio1`/`audio2` files
            count = 0
    
        if (n + 1) == lenght:
            res.export(export_path, format='mp3')
            print('\ndone!')
    

    If you want - as you mention - just concatenate all the files into a single audio, with silence in between, you shouldn't need to check the count, nor enumerate. I will keep enumerate because it can print nicely to show a bit more context. So, here's my take:

    from pydub import AudioSegment
    from os import getcwd
    import glob
    
    cwd = (getcwd()).replace(chr(92), '/')
    export_path = f'{cwd}/result.mp3'
    
    MP3_FILES = glob.glob(pathname=f'{cwd}/*.mp3', recursive=True)
    
    silence = AudioSegment.silent(duration=15000)
    full_audio = AudioSegment.empty()    # this will accumulate the entire mp3 audios
    
    for n, mp3_file in enumerate(MP3_FILES):
        mp3_file = mp3_file.replace(chr(92), '/')
        print(n, mp3_file)
    
        # Load the current mp3 into `audio_segment`
        audio_segment = AudioSegment.from_mp3(mp3_file)
    
        # Just accumulate the new `audio_segment` + `silence`
        full_audio += audio_segment + silence
        print('Merging ', n)
    
    # The loop will exit once all files in the list have been used
    # Then export    
    full_audio.export(export_path, format='mp3')
    print('\ndone!')