38

I have multiple (between 40 and 50) MP3 files that I'd like to concatenate into one file. What's the best way to do this in Python?

Use fileinput module to loop through each line of each file and write it to an output file? Outsource to windows copy command?

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Owen
  • 22,247
  • 13
  • 42
  • 47

4 Answers4

52

Putting the bytes in those files together is easy... however I am not sure if that will cause a continuous play - I think it might if the files are using the same bitrate, but I'm not sure.

from glob import iglob
import shutil
import os

PATH = r'C:\music'

destination = open('everything.mp3', 'wb')
for filename in iglob(os.path.join(PATH, '*.mp3')):
    shutil.copyfileobj(open(filename, 'rb'), destination)
destination.close()

That will create a single "everything.mp3" file with all bytes of all mp3 files in C:\music concatenated together.

If you want to pass the names of the files in command line, you can use sys.argv[1:] instead of iglob(...), etc.

Clint
  • 4,255
  • 1
  • 20
  • 19
nosklo
  • 217,122
  • 57
  • 293
  • 297
35

Just to summarize (and steal from nosklo's answer), in order to concatenate two files you do:

destination = open(outfile,'wb')
shutil.copyfileobj(open(file1,'rb'), destination)
shutil.copyfileobj(open(file2,'rb'), destination)
destination.close()

This is the same as:

cat file1 file2 > destination
Community
  • 1
  • 1
Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
  • I tried doing this, but for some reason I just get the first file, and not the second file appended. Both files are mp4 – CMJ Apr 02 '21 at 14:12
  • Works fine for me! You can do this with one line less by using a with statement. – Dobedani Apr 15 '22 at 14:16
6

Hmm. I won't use "lines". Quick and dirty use

outfile.write( file1.read() )
outfile.write( file2.read() )

;)

tuergeist
  • 9,171
  • 3
  • 37
  • 58
2

Improving on Clint and nosklo, knowing context manager, I find it cleaner to write this:

import shutil
import pathlib

source_files = pathlib.Path("My_Music").rglob("./*.mp3")
with open("concatenated_music.mp3", mode="wb") as destination:
    for file in source_files:
        with open(file, mode="rb") as source:
            shutil.copyfileobj(source, destination)
fleetingbytes
  • 2,512
  • 5
  • 16
  • 27