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
John Lauer
Publish thermal bottleneck planner, accepted candidate, analysis and native recording scripts
0049da5
29d ago
"""Native action at 3x, explicitly labeled inspection holds and postproduction analysis."""
import json,subprocess,textwrap
from pathlib import Path
from PIL import Image,ImageDraw,ImageFont
P=Path(__file__).resolve().parent;E=P/'edit';V=next((P/'recording').glob('*.mp4'));voices=json.loads((E/'voices.json').read_text())
font='/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf'
cuts={'intro':(1,4),'neck':(5,11),'N1':(12,42),'VUSB':(43,63),'PGND':(64,92),'tradeoffs':(23,34),'final':(100,121)}
clips=[];manifest=[];pos=0
for i,v in enumerate(voices):
key=v['key'];dur=v['duration']+1.2;out=E/f'clip-{i:02}.mp4';chart=key not in cuts
im=Image.new('RGBA',(1920,1080),'#101925');im.paste((0,0,0,0),(10,125,1450,990));d=ImageDraw.Draw(im)
d.text((30,24),'CODEX ASTRA / FUSION',font=ImageFont.truetype(font,23),fill='#50c9d6')
d.text((30,60),v['title'],font=ImageFont.truetype(font,34),fill='white')
y=220
for line in v['lines']:
for s in textwrap.wrap(line,27):d.text((1480,y),s,font=ImageFont.truetype(font,23),fill='#d7e7f0');y+=37
y+=25
if key in ['N1','VUSB','PGND']:
d.text((1480,650),'Native bridge calls',font=ImageFont.truetype(font,24),fill='#50c9d6')
for z,s in enumerate(['fusion_run_modeling_script','RIPUP / LINE +0','RATSNEST / SHOW','Native layer '+('2' if key=='PGND' else '15')]):d.text((1480,700+z*38),s,font=ImageFont.truetype(font,19),fill='#d7e7f0')
if key=='heat':d.text((1480,680),'ESTIMATE',font=ImageFont.truetype(font,28),fill='#edb659');d.text((1480,725),'Not measured temperature',font=ImageFont.truetype(font,21),fill='#d7e7f0')
footer='POSTPRODUCTION ANALYSIS / stated assumptions' if chart else 'NATIVE FUSION / 3x action + inspection hold / waits removed'
d.text((30,1025),footer,font=ImageFont.truetype(font,22),fill='#aebfcf');im.save(E/(key+'-overlay.png'))
if chart:
ins=['-loop','1','-i',str(E/(key+'.png'))]
flt='[0:v]scale=1420:860,pad=1920:1080:20:125:color=0x101925[v]'
else:
a,b=cuts[key];ins=['-ss',str(a),'-t',str(b-a),'-i',str(V)]
flt=f'[0:v]setpts=(PTS-STARTPTS)/3,crop=3020:1570:20:370,scale=1420:-2,pad=1420:860:0:60:color=0x101925,pad=1920:1080:20:125:color=0x101925,tpad=stop_mode=clone:stop_duration={dur}[v]'
flt+=';[v][1:v]overlay=0:0,fps=30,format=yuv420p[out];[2:a]adelay=400|400,apad[a]'
if not out.exists():subprocess.run(['ffmpeg','-v','error',*ins,'-i',str(E/(key+'-overlay.png')),'-i',v['audio'],'-filter_complex',flt,'-map','[out]','-map','[a]','-t',str(dur),'-c:v','libx264','-preset','fast','-crf','19','-threads','4','-c:a','aac','-b:a','192k','-ar','48000','-y',str(out)],check=True)
clips.append(out);manifest.append({**v,'outputStart':pos,'outputDuration':dur,'sourceInterval':cuts.get(key),'sourceFile':str(V) if not chart else str(E/(key+'.png')),'speed':3 if not chart else None,'hold':not chart});pos+=dur;print(key,round(pos,1),flush=True)
# Last frame held for five seconds; silent audio remains compatible for concatenation.
last=E/'hold.mp4';subprocess.run(['ffmpeg','-v','error','-sseof','-0.1','-i',str(clips[-1]),'-f','lavfi','-i','anullsrc=r=48000:cl=mono','-vf','tpad=stop_mode=clone:stop_duration=5','-t','5','-map','0:v','-map','1:a','-c:v','libx264','-preset','fast','-crf','19','-threads','4','-c:a','aac','-y',str(last)],check=True);clips.append(last)
(E/'concat.txt').write_text(''.join("file '"+str(x)+"'\n" for x in clips))
subprocess.run(['ffmpeg','-v','error','-f','concat','-safe','0','-i',str(E/'concat.txt'),'-c','copy','-y',str(E/'joined.mp4')],check=True)
# Loudness normalization is done separately, with measured two-pass values.
(E/'edit-manifest.json').write_text(json.dumps({'chapters':manifest,'duration':pos+5,'source':str(V),'cutMethod':'Actual encoded frames inspected every six seconds; initial black frames and validation waits removed. Native action accelerated 3x followed by explicit inspection holds. Analysis charts are postproduction.'},indent=2))