import struct

def read_uint32(data, offset):
    return struct.unpack('>I', data[offset:offset+4])[0]

def patch_duration(data, box_type, new_duration_sec, start=0, end=None):
    if end is None:
        end = len(data)
    offset = start
    while offset < end:
        if offset + 8 > len(data):
            break
        size = read_uint32(data, offset)
        if size < 8:
            break
        typ = data[offset+4:offset+8]
        if typ == box_type:
            version = data[offset+8]
            if version == 0:
                timescale_offset = offset+20
                duration_offset = offset+24
                timescale = read_uint32(data, timescale_offset)
                # 如果 timescale 异常大，强制修正
                if timescale > 100000:
                    print(f'{box_type.decode()} timescale异常({timescale})，强制设为1000')
                    timescale = 1000
                    data[timescale_offset:timescale_offset+4] = struct.pack('>I', timescale)
                new_duration = int(new_duration_sec * timescale)
                if not (0 <= new_duration <= 0xFFFFFFFF):
                    print(f'{box_type.decode()} duration超出范围，使用最大值')
                    new_duration = 0xFFFFFFFF
                data[duration_offset:duration_offset+4] = struct.pack('>I', new_duration)
                print(f'已修正{box_type.decode()} duration: {new_duration} (timescale={timescale})')
            else:
                print(f'{box_type.decode()} 暂不支持 version 1')
        # 递归 container box
        if typ in [b'moov', b'trak', b'mdia']:
            patch_duration(data, box_type, new_duration_sec, offset+8, offset+size)
        offset += size if size > 0 else 8

def fix_mp4_duration(file_path, output_path, new_duration_sec):
    with open(file_path, 'rb') as f:
        data = bytearray(f.read())
    for box in [b'mvhd', b'tkhd', b'mdhd']:
        patch_duration(data, box, new_duration_sec)
    with open(output_path, 'wb') as f:
        f.write(data)
    print('修复完成，请检查时长')

if __name__ == '__main__':
    fix_mp4_duration(
        r'C:\Users\26549\Downloads\Video\1.mp4',
        r'C:\Users\26549\Downloads\Video\1_fixed.mp4',
        7200
    )