'How to calculate the ID3v2 tag size from mp3 file correctly?

To my shame, I still don't quite understand byte arithmetic and other manipulations. I am trying to calculate the size of the ID3 tag from mp3 file. Versions 3 or 4 and with no extended header. For simplicity, will return an empty list on any exception.

ID3 description

from functools import reduce


def id3_size_calc(file_path):
    try:
        file_open = open(file_path, 'rb')
    except Exception:
        return print([])
    with file_open:
        id3_header = file_open.read(10)
        if id3_header[0:3] != b'ID3':
            return print([])
        elif id3_header[3] != (3 or 4):
            return print([])
        elif id3_header[5] != 0:
            return print([])
        else:
            size_encoded = bytearray(id3_header[-4:])
            return print(reduce(lambda a, b: a * 128 + b, size_encoded, 0))

I found this piece of code.

size = reduce(lambda a, b: a * 128 + b, size_encoded, 0)

However, I don't understand how it works. In addition, I came across information that function reduce is outdated. Is there a more elegant way to calculate the size of this tag?



Solution 1:[1]

The simplest way would be to use ffmpeg/ffprobe

ffprobe -i file.mp3 -v debug 2>&1 | grep id3v2 should give you the output like so: id3v2 ver:4 flags:00 len:35

But if you do not intend or have the package to use ffprobe, here is a snippet of python to get the size:

file_open = open('file.mp3', 'rb')
data = file_open.read(10)
file_open = open('fly.mp3', 'rb')
if data[0:3] != b'ID3':
    print('No ID3 header present in file.')
else:
    size_encoded = bytearray(data[-4:])
    size = reduce(lambda a,b: a*128+b, size_encoded, 0)
    print(size)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 checkmate101