app
Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.
master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
"""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)