master
John Lauer Add captioned 3x Fusion routing showcase and Windows playback evidence cefe949 1mo ago
"""Render the preserved live Fusion take with captions and explicit edit provenance."""
import hashlib
import json
from pathlib import Path
import shutil
import subprocess

ROOT = Path(__file__).resolve().parent
SOURCE = ROOT / 'videos/window-8916576-20260905-205212.mp4'
OUT = ROOT / 'videos/fusion-routing-showcase-3x.mp4'
ASS = OUT.with_suffix('.ass')
SPEED, HOLD = 3, 5
FFMPEG = shutil.which('ffmpeg')
probe = json.loads(subprocess.check_output(['ffprobe', '-v', 'error', '-show_streams', '-show_format', '-of', 'json', str(SOURCE)]))
duration = float(probe['format']['duration'])
action = duration / SPEED
end = action + HOLD
header = '''[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
WrapStyle: 2
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Main,Liberation Sans,34,&H00FFFFFF,&H00FFFFFF,&H00130F0A,&H00130F0A,0,0,0,0,100,100,0,0,1,1,0,2,30,30,22,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
'''
def stamp(t):
    cs=round(t*100)
    return f'{cs//360000}:{cs//6000%60:02d}:{cs//100%60:02d}.{cs%100:02d}'
events=[]
def text(a,b,s):
    events.append(f'Dialogue: 0,{stamp(a)},{stamp(b)},Main,,0,0,0,,{s}')
text(0,end,r'{\an7\pos(34,16)\fs38\b1\c&H00E5CF65&}CODEX ASTRA IN ADOM HYDROGEN'+r'{\c&H00FFFFFF&}  /  FUSION ROUTING')
text(0,end,r'{\an7\pos(1490,125)\fs48\b1\c&H00E5CF65&}3x PLAYBACK')
text(0,end,r'{\an7\pos(1490,197)\fs27}Native Fusion capture\NFull sequence retained')
side=[(315,'THE BOARD',r'6 nets / 13 pads\N21 trace segments\N2 through vias'),(500,'THE PATHS',r'Explicit planned waypoints\NKiCad reference fixture\NTop + bottom copper'),(690,'THE CHECKS',r'Board identity + revision\NLive copper read-back\NNative Autodesk DRC')]
for y,title,body in side:
    text(0,end,fr'{{\an7\pos(1490,{y})\fs32\b1\c&H00E5CF65&}}'+title)
    text(0,end,fr'{{\an7\pos(1490,{y+46})\fs27}}'+body)
cues=[(0,3,'fusion_routing_state reads pad coordinates, nets and the board revision.'),(3,6,'fusion_route_net creates each trace and via through Adom Bridge.'),(6,action,'Each edit checks expectedRevision and verifies the resulting native copper.'),(action,end,r'fusion_routing_drc: 6 nets connected.\N0 errors / 0 warnings / 0 airwires.')]
for a,b,s in cues:
    text(a,b,r'{\an2\pos(960,1058)\fs34}'+s)
text(action,end,r'{\an7\pos(1490,895)\fs25\c&H00B9B9B9&}Final frame held for 5 seconds')
ASS.write_text(header+'\n'.join(events)+'\n')
# Timestamp-based speed adjustment preserves the actual source timeline, including VFR.
# Apply the hold BEFORE captions so the result caption remains correct throughout it.
vf=f'setpts=(PTS-STARTPTS)/{SPEED},fps=30,scale=1440:900:force_original_aspect_ratio=decrease,pad=1440:900:(ow-iw)/2:(oh-ih)/2:color=0x0a0f13,pad=1920:1080:0:70:color=0x0a0f13,tpad=stop_mode=clone:stop_duration={HOLD},ass={ASS}'
subprocess.run([FFMPEG,'-hide_banner','-loglevel','warning','-i',str(SOURCE),'-vf',vf,'-an','-c:v','libx264','-preset','fast','-crf','20','-pix_fmt','yuv420p','-movflags','+faststart','-y',str(OUT)],check=True)
manifest={'source':str(SOURCE),'sourceSha256':hashlib.sha256(SOURCE.read_bytes()).hexdigest(),'keptSourceRanges':[[0,duration]],'idleIntervalsRemoved':False,'speed':SPEED,'holdSeconds':HOLD,'expectedDurationSeconds':end,'captions':cues,'geometry':'Explicit waypoint plan adapted from KiCad reference fixture; not general autorouting','validationEvidence':'../evidence/final-take/result.json'}
OUT.with_suffix('.edit.json').write_text(json.dumps(manifest,indent=2)+'\n')
subprocess.run([FFMPEG,'-v','error','-i',str(OUT),'-f','null','-'],check=True)
result=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_streams','-show_format','-of','json',str(OUT)]))
assert abs(float(result['format']['duration'])-end)<.1
assert result['streams'][0]['width']==1920 and result['streams'][0]['height']==1080
(ROOT/'evidence/showcase-video-validation.json').write_text(json.dumps({'fullDecodePassed':True,'source':probe,'output':result},indent=2)+'\n')
print(OUT)