Back to Daft

LeRobot video decode: per-frame → per-shard

benchmarking/lerobot/README.md

0.7.182.1 KB
Original Source

LeRobot video decode: per-frame → per-shard

The daft.datasets.lerobot reader decoded video frames with a per-row UDF that re-opened the MP4 shard for every frame. Because av.open() on a remote shard re-reads and parses the container index over the network, decoding N frames re-opened the shard N times, paying that cost each time - so cost scaled ~linearly at ~3s/frame (the slope of the sweep below).

This directory holds the benchmarks that diagnosed it and the fix that makes the decode batched: rows sharing a shard within a batch are grouped so each shard is opened once per batch, instead of once per frame.

The fix: batched decode

_decode_lerobot_video_timestamp in daft/datasets/lerobot.py is now a @daft.func.batch UDF. Within each batch it groups rows by shard path, opens each shard once, and does a single forward decode assigning the closest frame to every requested timestamp. Output is byte-identical to the old per-row decode.

Original vs batched (rows 1→10)

sweep.py times an end-to-end lerobot.read(...).limit(n).collect() with frame decoding for n = 1..10 rows of a remote test dataset (pepijn223/egodex-test), run once per reader revision (merge-base vs this branch) - the original grows linearly to ~34s; the batched version stays flat at ~4s (all 10 frames share one shard → one open).

rowsoriginalbatched
14.2s4.4s
825.0s3.9s
1034.4s3.9s

8-frame output hashes matched exactly (sha 80bdb30c…) between versions.

Beyond this test dataset, the fix was validated on six public LeRobot v3 datasets spanning av1/h264/mp4v, 5-30 fps, 128x128-1280x720, and 1-3 cameras - pixel-identical output everywhere, 4-13x faster - plus a full-dataset decode and a 100-frame comparison. See real_datasets.md.

Running

bash
python sweep.py --label batched      # rows 1..10 sweep + chart