answerSeeker
answerSeeker

Reputation: 2772

How can I truncate an mp3 audio file by 30%?

I am trying to truncate an audio file by 30%, if the audio file was 4 minutes long, after truncating it, it should be around 72 seconds. I have written the code below to do it but it only returns a 0 byte file size. Please tell me where i went wrong?

def loadFile():
    with open('music.mp3', 'rb') as in_file:
        data = len(in_file.read())
        with open('output.mp3', 'wb') as out_file:
            ndata = newBytes(data)
            out_file.write(in_file.read()[:ndata])

def newBytes(bytes):
    newLength = (bytes/100) * 30
    return int(newLength)

loadFile()

Upvotes: 1

Views: 522

Answers (2)

Brad
Brad

Reputation: 163593

You cannot reliably truncate an MP3 file by byte size and expect it to be equivalently truncated in audio time length.

MP3 frames can change bitrate. While your method will sort of work, it won't be all that accurate. Additionally, you'll undoubtedly break frames leaving glitches at the end of the file. You will also lose ID3v1 tags (if you still use them... better to use ID3v2 anyway).

Consider executing FFmpeg with -acodec copy instead. This will simply copy the bytes over while maintaining the integrity of the file, and ensuring a good clean cut where you want it to be.

Upvotes: 0

Martin Evans
Martin Evans

Reputation: 46779

You are trying to read your file a second time which will result in no data, e.g. len(in_file.read(). Instead read the whole file into a variable and then calculate the length of that. The variable can then be used a second time.

def newBytes(bytes):
    return (bytes * 70) / 100

def loadFile():
    with open('music.mp3', 'rb') as in_file:
        data = in_file.read()

    with open('output.mp3', 'wb') as out_file:
        ndata = newBytes(len(data))
        out_file.write(data[:ndata])

Also it is better to multiply first and then divide to avoid having to work with floating point numbers.

Upvotes: 2

Related Questions