"""Inspect MP4 track metadata without external tools.""" import json, struct, sys from pathlib import Path def boxes(data): offset=0 while offset+8<=len(data): size,kind=struct.unpack_from('>I4s',data,offset);header=8 if size==1:size=struct.unpack_from('>Q',data,offset+8)[0];header=16 if size==0:size=len(data)-offset if size
len(data):raise ValueError('Invalid MP4 box') yield kind.decode('ascii'), data[offset+header:offset+size] offset+=size def child(data,name):return next(body for kind,body in boxes(data) if kind==name) def inspect(path): moov=child(Path(path).read_bytes(),'moov');result=[] for kind,trak in boxes(moov): if kind!='trak':continue mdia=child(trak,'mdia');hdlr=child(mdia,'hdlr');kind=hdlr[8:12].decode() mdhd=child(mdia,'mdhd') if mdhd[0]==0:scale,duration=struct.unpack_from('>II',mdhd,12) else:scale=struct.unpack_from('>I',mdhd,20)[0];duration=struct.unpack_from('>Q',mdhd,24)[0] stbl=child(child(mdia,'minf'),'stbl');stsz=child(stbl,'stsz');count=struct.unpack_from('>I',stsz,8)[0] desc=child(stbl,'stsd');entry=next(boxes(desc[8:]));seconds=duration/scale item={'type':kind,'codec':entry[0],'duration_seconds':seconds,'samples':count} if kind=='vide': width,height=struct.unpack_from('>HH',entry[1],24);item.update(width=width,height=height,fps=count/seconds) assert (width,height,count)==(1280,720,480),item assert abs(seconds-20)<.01,item result.append(item) assert any(t['type']=='soun' for t in result),'Missing audio track' return result if __name__=='__main__':print(json.dumps(inspect(sys.argv[1]),indent=2))