from pathlib import Path
from PIL import Image,ImageDraw
import subprocess,json
root=Path('/tmp/issue-lead-33443-r1/evidence-capture/20261109T170330Z-final')
scratch=root/'video-review';scratch.mkdir(exist_ok=True)
manifest=json.loads((root.parent/'capture-manifest.json').read_text());videos=[]
for group,sub in [('captures',''),('files','files-final'),('remote','remote-final'),('selection','')]:
 for item in manifest[group]:
  p=root/sub/item['video'];duration=float(subprocess.check_output(['ffprobe','-v','error','-show_entries','format=duration','-of','csv=p=0',str(p)],text=True));frames=[]
  for n,t in enumerate([0,min(.5,duration/5),min(1,duration/3),min(2,duration/2),max(0,duration-.2)]):
   file=scratch/(p.stem+'-'+str(n)+'.png');subprocess.run(['ffmpeg','-y','-v','error','-ss',str(t),'-i',str(p),'-frames:v','1',str(file)],check=True)
   im=Image.open(file).convert('RGB')
   if group=='remote':im=im.crop((int(im.width*.20),int(im.height*.14),int(im.width*.58),int(im.height*.36)))
   elif im.width<im.height:im=im.crop((0,0,im.width,int(im.height*.34)))
   else:im=im.crop((int(im.width*.65),0,im.width,int(im.height*.30)))
   im.thumbnail((320,320));frames.append((im,t))
  sheet=Image.new('RGB',(1600,360),'#bbb');draw=ImageDraw.Draw(sheet)
  for n,(im,t) in enumerate(frames):sheet.paste(im,(n*320,40));draw.text((n*320+4,23),f'{t:.2f}s',fill='black')
  draw.text((4,4),p.name+f' duration {duration:.2f}s',fill='black');out=scratch/(p.stem+'-review.png');sheet.save(out);videos.append({'video':str(p.relative_to(root)),'duration':duration,'review':str(out.relative_to(root))})
(root/'video-review.json').write_text(json.dumps(videos,indent=2))
for row in ['E0','E1','E2']:
 chosen=[x for x in videos if Path(x['video']).name.startswith(row+'-') or Path(x['video']).name.startswith(row+'A-')]
 canvas=Image.new('RGB',(1600,len(chosen)*360),'#bbb')
 for n,item in enumerate(chosen):canvas.paste(Image.open(root/item['review']),(0,n*360))
 canvas.save(scratch/(row+'-videos.png'))
print('Reviewed-frame sheets:',len(videos))
