def get_fps(f): f.seek(0) mp4.find_atom(f, b'moov') moov = mp4.parse_atom(f) for trak in moov.find(b'trak'): if trak.find(b'vmhd'): video_trak = trak break else: raise Exception('FPS: No video track found') stts = video_trak.find(b'stts')[0] mdhd = video_trak.find(b'mdhd')[0] stts_entries = struct.unpack('>I', stts.data[4:4 + 4])[0] sum_samples = 0 sum_delta = 0 for i in range(stts_entries): offset = 8 + i * 8 num_samples = struct.unpack('>I', stts.data[offset:offset + 4])[0] sum_samples += num_samples sum_delta += num_samples * struct.unpack( '>I', stts.data[offset + 4:offset + 8])[0] denom = round(sum_delta / sum_samples) numer = struct.unpack('>I', mdhd.data[12:12 + 4])[0] return numer, denom
def set_fps(f, numer, denom): f.seek(0) mp4.find_atom(f, b'moov') moov_offset = f.tell() moov = mp4.parse_atom(f) for trak in moov.find(b'trak'): if trak.find(b'vmhd'): video_trak = trak break else: raise Exception('FPS: No video track found') stts = video_trak.find(b'stts')[0] mdhd = video_trak.find(b'mdhd')[0] stts_entries = struct.unpack('>I', stts.data[4:4 + 4])[0] num_samples = 0 for i in range(stts_entries): offset = 8 + i * 8 num_samples += struct.unpack('>I', stts.data[offset:offset + 4])[0] stts.data[offset + 4:offset + 8] = struct.pack('>I', denom) mdhd.data[12:12 + 8] = struct.pack('>II', numer, num_samples * denom) f.seek(moov_offset) f.write(moov.flatten())
import mp4 import sys, struct, shutil, os outname = os.path.basename(sys.argv[1]) name, ext = os.path.splitext(outname) outname = name + '_org_fps' + ext print(outname) f = open(sys.argv[1], 'rb') mp4.find_atom(f, b'moov') moov_offset = f.tell() moov = mp4.parse_atom(f) for trak in moov.find(b'trak'): if trak.find(b'vmhd'): video_trak = trak break else: sys.exit(1) #stsz = video_trak.find(b'stsz')[0] stts = video_trak.find(b'stts')[0] mdhd = video_trak.find(b'mdhd')[0] #num_samples = struct.unpack('>I', stsz.data[8:8+4])[0] #stts.data[4:] = struct.pack('>III', 1, num_samples, 1001) stts_entries = struct.unpack('>I', stts.data[4:4 + 4])[0] num_samples = 0 for i in range(stts_entries): offset = 8 + i * 8 num_samples += struct.unpack('>I', stts.data[offset:offset + 4])[0] stts.data[offset + 4:offset + 8] = struct.pack('>I', 1000)
def parse_time(t): t = t.split(':') ts = 0 for i, p in enumerate(reversed(t)): ts += float(p) * 60**i return ts if len(sys.argv) > 3: bb_offset1, bb_time1, bb_offset2, bb_time2 = map(parse_time, sys.argv[3:3 + 4]) else: bb_offset1 = parse_time(sys.argv[3]) bb_time1, bb_offset2, bb_time2 = None, None, None mp4.find_atom(fin, b'moov') moov = mp4.parse_atom(fin) fin.seek(0) mdat_data_size = mp4.find_atom(fin, b'mdat') - mp4.ATOM_HEAD_SIZE mdat_data_offset = fin.tell() + mp4.ATOM_HEAD_SIZE #print(moov) # video_trak = None # audio_trak = None # for trak in moov.find(b'trak'): # if trak.find(b'vmhd'): # video_trak = trak # elif trak.find(b'smhd'): # audio_trak = trak #