master
John Lauer Preserve validated CRR thermal routing recipe and narrated demonstration 92d2870 1mo ago
"""Render verified cuts from native CRR board and activity-palette recordings."""
import json,subprocess,math
from pathlib import Path
from PIL import Image,ImageDraw,ImageFont
P=Path(__file__).resolve().parent;E=P/'edit';T=P/'recording-02'
font='/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf'
voices=json.loads((E/'voice-plan.json').read_text());cuts=json.loads((E/'cuts.json').read_text());audit=json.loads((T/'audit.json').read_text())
board=next(T.glob('window-5837878*.mp4'));palette=next(T.glob('window-4923828*.mp4'))
def panel(i,title,lines,live=False):
 im=Image.new('RGBA',(1920,1080),(14,21,31,255));im.paste((0,0,0,0),(0,115,1460,995));d=ImageDraw.Draw(im);d.text((32,26),title,font=ImageFont.truetype(font,36),fill='white')
 y=690 if live else 150
 for line in lines:d.text((1490,y),line,font=ImageFont.truetype(font,24),fill='#c8e0ed');y+=39
 d.text((30,1025),'Native Fusion on CRR | 3x action + inspection holds | waits removed | edited captions',font=ImageFont.truetype(font,24),fill='#bcd4df');im.save(E/f'panel-{i}.png')
clips=[];cues=[];manifest=[];time=0
for i,c in enumerate(cuts):
 v=voices[c['voice']];dur=max(v['voiceDuration']+1.5,(c['end']-c['start'])/3);panel(i,v['title'],c['lines'],c.get('palette',False));out=E/f'clip-{i:02}.mp4'
 # Crop only the native CAD canvas, preserving the board aspect ratio.
 flt=f'[0:v]setpts=(PTS-STARTPTS)/3,crop=3020:1570:20:370,scale=1460:760,pad=1460:880:0:55:color=0x0e151f,pad=1920:1080:0:115:color=0x0e151f,tpad=stop_mode=clone:stop_duration={dur}[v];[v][1:v]overlay=0:0,fps=30,format=yuv420p[out]'
 extra=[]
 if c.get('palette'):
  extra=['-ss',str(max(0,c['start']-cuts[0].get('paletteOffset',.55))),'-t',str(c['end']-c['start']),'-i',str(palette)]
  flt=flt.replace('format=yuv420p[out]','format=yuv420p[base]')+f';[2:v]setpts=(PTS-STARTPTS)/3,scale=430:-2,tpad=stop_mode=clone:stop_duration={dur}[p];[base][p]overlay=1480:145:shortest=1[out]'
 subprocess.run(['ffmpeg','-v','error','-ss',str(c['start']),'-t',str(c['end']-c['start']),'-i',str(board),'-i',str(E/f'panel-{i}.png'),*extra,'-filter_complex',flt,'-map','[out]','-t',str(dur),'-an','-c:v','libx264','-preset','fast','-crf','20','-threads','4','-y',str(out)],check=True)
 clips.append(out);cues.append({**v,'start':time+.4,'end':time+dur-.2});manifest.append({**c,'outputStart':time,'outputDuration':dur,'speed':3});time+=dur
hold=E/'hold.mp4';subprocess.run(['ffmpeg','-v','error','-sseof','-0.1','-i',str(clips[-1]),'-vf','tpad=stop_mode=clone:stop_duration=5','-t','5','-an','-c:v','libx264','-preset','fast','-crf','20','-threads','4','-y',str(hold)],check=True);clips.append(hold);time+=5
(E/'concat.txt').write_text(''.join("file '"+str(f)+"'\n" for f in clips));subprocess.run(['ffmpeg','-v','error','-f','concat','-safe','0','-i',str(E/'concat.txt'),'-c','copy','-movflags','+faststart','-y',str(E/'fusion-bq25792-astra-thermal-silent.mp4')],check=True)
(E/'script.json').write_text(json.dumps(cues,indent=2));(E/'edit.json').write_text(json.dumps({'duration':time,'stages':manifest,'source':str(board),'paletteRecording':str(palette),'note':'Canvas crop with native palette inset during routing; postproduction captions. Palette offset 0.2333 seconds from encoded durations, visually checked against active net.'},indent=2))
print('Rendered',time,flush=True)