Download code/desk_robot_checks.py from laion/tyger-speaker-predictor: direct link, hf CLI and curl.
- Browser
- Download file 7.15 kB
-
https://huggingface.co/laion/tyger-speaker-predictor/resolve/main/code/desk_robot_checks.py
- Command line
-
hf download hf://laion/tyger-speaker-predictor/code/desk_robot_checks.py
-
curl -L -o desk_robot_checks.py https://huggingface.co/laion/tyger-speaker-predictor/resolve/main/code/desk_robot_checks.py
7.15 kB
| """Real Chromium software-only 3D, kinematics, expressions and responsive QA. | |
| No microphone, GPU model, camera or hosted API is used by this test. --disable-gpu | |
| proves that the model does not require hardware 3D acceleration. Timings are | |
| observations of this host, not promises for every phone or Raspberry Pi. | |
| """ | |
| import argparse,asyncio,json,time | |
| from pathlib import Path | |
| from playwright.async_api import async_playwright | |
| ROOT=Path(__file__).resolve().parent | |
| async def run(args): | |
| (ROOT/'logs/desk-robot-checks.json').write_text(json.dumps({'passed':False,'running':True,'url':args.url})) | |
| async with async_playwright() as p: | |
| browser=await p.chromium.launch(executable_path='/usr/bin/google-chrome',headless=True, | |
| args=['--no-sandbox','--disable-gpu','--autoplay-policy=no-user-gesture-required']) | |
| try: | |
| page=await browser.new_page(viewport={'width':1440,'height':1100});errors=[];requests=[] | |
| page.on('pageerror',lambda e:errors.append(str(e)));page.on('request',lambda r:requests.append(r.url)) | |
| await page.goto(args.url);await page.wait_for_function('window.robotFace?.rig.snapshot().renderCount>3',timeout=30000) | |
| await page.wait_for_timeout(700) | |
| await page.screenshot(path=str(ROOT/'logs/desk-robot-desktop.png')) | |
| result=await page.evaluate('''async()=>{ | |
| const {rig,pose,profiles}=window.robotFace; | |
| const {DIMENSIONS,buildDeskGeometry}=await import('/static/desk-robot3d.js'); | |
| const meshes=buildDeskGeometry(),baseline=rig.snapshot(); | |
| rig.setManual(130,30);for(let i=0;i<100;i++)rig.update({pose:pose()},100,0); | |
| const limit=rig.snapshot();if(limit.pan>90||limit.tilt>15||limit.roll!==0)throw Error('Mechanical limits violated'); | |
| rig.setManual(-130,-30);for(let i=0;i<100;i++)rig.update({pose:pose()},100,0); | |
| const negative=rig.snapshot();if(negative.pan < -90||negative.tilt < -15)throw Error('Negative limits violated'); | |
| rig.setManual(0,0,false);for(let i=0;i<100;i++)rig.update({pose:pose(),x:1,y:1},100,0); | |
| const gaze=rig.snapshot();if(gaze.pan<40||gaze.tilt> -10||gaze.roll!==0)throw Error('Face-follow control did not steer pan/tilt'); | |
| rig.center();rig.setManual(0,0);for(let i=0;i<70;i++)rig.update({pose:pose()},100,0); | |
| const geometries=[],pixels=[],captures=[]; | |
| for(const profile of profiles){const value=pose(profile.slug,.95,0,42);for(let i=0;i<25;i++)rig.update({pose:value},100,0); | |
| const s=rig.snapshot();geometries.push(JSON.stringify(s.geometry.points.slice(12,89).map(p=>p.map(x=>Math.round(x*100))))); | |
| const canvas=document.querySelector('.desk-robot-canvas');const image=canvas.toDataURL();pixels.push(image);captures.push({name:profile.label,image}); | |
| } | |
| const uniqueGeometry=new Set(geometries).size,uniqueRenders=new Set(pixels).size; | |
| if(uniqueGeometry!==40||uniqueRenders!==40)throw Error('Expressions collapsed: '+uniqueGeometry+'/'+uniqueRenders); | |
| rig.center();for(let i=0;i<50;i++)rig.update({pose:pose()},100,0); | |
| window.deskCaptures=captures; | |
| return {renderer:baseline.renderer,dimensions:DIMENSIONS,mesh_faces:meshes.reduce((n,m)=>n+m.polys.length,0), | |
| positive_limits:{pan:limit.pan,tilt:limit.tilt,roll:limit.roll},negative_limits:{pan:negative.pan,tilt:negative.tilt,roll:negative.roll}, | |
| simulated_gaze_follow:{pan:gaze.pan,tilt:gaze.tilt,roll:gaze.roll,physical_camera_accuracy_measured:false}, | |
| unique_expression_geometry:uniqueGeometry,unique_expression_renders:uniqueRenders, | |
| snapshot:rig.snapshot(),no_svg_arms:!document.querySelector('#arm-left,#arm-right'),webgl_used:false}; | |
| }''') | |
| # Actual animation cadence (not just a requested 30-fps setting). | |
| before=await page.evaluate('window.robotFace.rig.snapshot().renderCount');t0=time.monotonic() | |
| await page.wait_for_timeout(2500) | |
| after=await page.evaluate('window.robotFace.rig.snapshot()') | |
| result['observed_render_fps']=(after['renderCount']-before)/(time.monotonic()-t0) | |
| result['render_p95_ms']=after['renderP95Ms'];result.pop('snapshot',None) | |
| await page.click('.desk-controls summary');await page.click('#desk-threequarter') | |
| await page.fill('#desk-explode','0.65');await page.dispatch_event('#desk-explode','input');await page.wait_for_timeout(200) | |
| result['exploded_control']=await page.evaluate('window.robotFace.rig.snapshot().exploded') | |
| await page.screenshot(path=str(ROOT/'logs/desk-robot-exploded.png')) | |
| await page.click('#desk-center');await page.fill('#desk-explode','0');await page.dispatch_event('#desk-explode','input') | |
| await page.set_viewport_size({'width':390,'height':844});await page.wait_for_timeout(300) | |
| result['mobile_no_overflow']=await page.evaluate('document.documentElement.scrollWidth<=innerWidth') | |
| await page.screenshot(path=str(ROOT/'logs/desk-robot-mobile.png')) | |
| assert result['mobile_no_overflow'],result | |
| captures=await page.evaluate('window.deskCaptures') | |
| gallery=await browser.new_page(viewport={'width':1300,'height':950}) | |
| await gallery.set_content('<body style="margin:0;background:#f7f5ef"></body>') | |
| await gallery.evaluate('''captures=>{const sheet=document.createElement('section');sheet.id='desk-contact-sheet';sheet.style.cssText='display:grid;grid-template-columns:repeat(8,150px);gap:6px;background:#f7f5ef;padding:15px;width:1260px';for(const item of captures){const cell=document.createElement('div');const image=document.createElement('img');image.src=item.image;image.style.cssText='width:150px;height:150px;object-fit:contain';const caption=document.createElement('p');caption.textContent=item.name;caption.style.cssText='font:10px system-ui;text-align:center;margin:0';cell.append(image,caption);sheet.append(cell);}document.body.append(sheet);}''',captures) | |
| await gallery.wait_for_timeout(200) | |
| await gallery.locator('#desk-contact-sheet').screenshot(path=str(ROOT/'logs/desk-robot-40-expressions.png')) | |
| await gallery.close() | |
| result['page_errors']=errors;result['hardware_gpu_disabled']=True | |
| result['remote_mesh_downloads']=[u for u in requests if any(ext in u.lower() for ext in ('.glb','.fbx','.3mf','.obj'))] | |
| assert not errors and not result['remote_mesh_downloads'],result | |
| assert result['render_p95_ms']<50,'Software renderer exceeded 20-fps frame budget on this host' | |
| result['passed']=True | |
| (ROOT/'logs/desk-robot-checks.json').write_text(json.dumps(result,indent=2)) | |
| print(json.dumps(result,indent=2)) | |
| finally:await browser.close() | |
| if __name__=='__main__': | |
| p=argparse.ArgumentParser();p.add_argument('--url',default='http://127.0.0.1:8793/desk-robot/');asyncio.run(run(p.parse_args())) | |