Files
Halloween/tools/check_preview.py
T

36 lines
1.6 KiB
Python

"""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<header or offset+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))