july 2026: open-sourced the full stera 2.0 stack, including stera_recorder on pub.dev.
may 2026: 200 hours of egocentric capture across 500+ sessions, all recorded through the app, released as stera-10m.
my part was the capture and upload infrastructure the dataset was collected through, not the paper itself.
- resumable uploads for 10gb+ capture sessions
- arkit / arcore capture into mcap · ros2 datasets
- every recording anonymized on device before upload
- 21 joint hand pose lifted through depth
- two phones synced to one timeline within 1-2 ms
- open-sourced the stera capture stack
joining fpv labs
joined in nov 2025 as a mobile engineer. the phone sat in the middle of a robotics data workflow: record the world, move big datasets, and keep going when devices, sensors and networks misbehave.
so a flow was only done when it survived the field, not the simulator.




stability first, then speed
some modules pushed the crash rate toward ~6%, which is not ok when the app is the recorder. i refactored the shaky parts and tightened error handling on ios and android, and got it under 1%.
large uploads that actually finish
capture sessions get heavy fast. i built a cross-platform upload pipeline for 10gb+ files: resumable, running in the background, recovering from failure. an interrupted upload picks up where it stopped instead of starting from zero.


from ar session to dataset
the ar capture system runs on arkit and arcore and records video, pose, point cloud, depth and imu from one session.
sessions are packaged as mcap datasets compatible with ros2, sampled at roughly 30 fps, so the output is usable for robotics work, not just raw sensor noise.




faces never leave the phone
recordings happen in public, so every session is anonymized on device before upload. faces get pixelated in every rgb frame and in the thumbnail.
it isn't a setting. no upload row can exist without the blur marker on disk, enforced in the one function that creates uploads and every recovery path around it. blur goes to a temp file, gets verified, then an atomic replace, then the marker, so killing the app anywhere still leaves it recoverable. it runs at about 0.3-1x the recording time across three workers, with memory capped at six frames.
21 joints, lifted through depth
hand pose is what the recorder exists for. vision detects 21 joint skeletons and we lift them into 3d with the recording's own depth.
unlike blur, hand pose never blocks an upload. it runs after capture, so resolver fixes apply to footage already on disk. buffering ~1 kb a frame instead of serialized bytes keeps twenty minutes of footage at ~12 mb instead of ~236 mb, the difference between working and getting killed by the os. checked offline against wilor, chirality agreement matches inline at ~99.8%.
watching a recording while it happens
debugging a capture used to mean finish, export, open the file somewhere else. too slow when someone's standing in a warehouse wondering if depth even works.
so the phone runs a foxglove websocket server, found over bonjour, and a laptop on the same network watches topics live. the tap mirrors each message after the writer has put it on disk, and a test checks that tapped and untapped recordings are byte-identical, so streaming can't corrupt the file.
two phones, one timeline
one camera sees one side of a task. two phones fix that, until you ask what a timestamp means across two devices.
a shared countdown starts both within 5-25 ms. alignment is the real work: ios has no shared clock, so the phones run a ping/pong protocol into a kalman filter over offset and drift. sync was queued behind collaboration traffic, spiking rtt to 60-200 ms against a 5-8 ms median, so i moved it to the unreliable channel. offline, one command remaps the follower onto the leader's timeline and merges both into one mcap. target is 1-2 ms.
giving up arkit to get raw depth
arkit owns the wide camera and won't drive the ultra wide. to get ultra wide rgb and raw lidar depth from one session, that mode drops arkit and drives the cameras directly with AVCaptureMultiCamSession.
the trade: no live pose, mesh or point cloud, those get recovered offline. wide and depth are hardware synced, ultra wide lands within about one frame, and the recorder logs sync diagnostics for an offline analyzer. it all goes into the same mcap, so nothing downstream needed a new reader.
the rest of the app




- 10gb+ filesresumable uploads
- 30 fpsar capture into mcap
- under 1%crash rate, from ~6%
- 1-2 mstwo device alignment