Skip to content

Add compressed depth sidecar video for LeRobot datasets - #434

Merged
yuecideng merged 1 commit into
DexForce:mainfrom
yuecideng:feat/depth-video-sidecar
Jul 29, 2026
Merged

Add compressed depth sidecar video for LeRobot datasets#434
yuecideng merged 1 commit into
DexForce:mainfrom
yuecideng:feat/depth-video-sidecar

Conversation

@yuecideng

Copy link
Copy Markdown
Contributor

Description

This PR implements issue #424 Path A: an EmbodiChain-owned depth writer that stores camera depth as compressed gray12le/HEVC sidecar videos alongside LeRobot datasets, on Python 3.10/3.11 with lerobot 0.4.4 — without the Python 3.12 / lerobot 0.6.0 upgrade.

Built on top of the merged PR #422 (numeric depth/mask features). Depth quantization math is vendored from lerobot v0.6.0 (depth_utils.py), which has no py3.12-only syntaxrequires-python>=3.12 is a project policy, not a technical barrier of the depth code. The sidecar metadata schema is aligned with the official 0.6.0 reader for a seamless future migration (Path B).

What's added

  • embodichain/data_pipeline/depth_video/depth_utils (quantize/dequantize, vendored), codec (libx265/hevc detection), DepthVideoWriter + DepthSidecarManager (per-episode gray12le/libx265 lossless-or-CRF MP4s + depth_meta.json), DepthVideoReader + load_depth_dataset (decode + dequantize to m/mm).
  • LeRobotRecorderdepth_video config; when enabled, depth is offloaded to the sidecar writer and dropped from lerobot's RGB-only image/video pipeline. Mask stays numeric. Auto-fallback to numeric depth (feat(dataset): preserve depth and mask camera frames #422) when no HEVC encoder is available. Works for both sync and async recorders.
  • Tests (35, ~1s) — quantization round-trip error bounds, lossless 12-bit code bit-exactness, sidecar metadata/stereo/abort, codec detection, and recorder integration.
  • Docs + a benchmark script (scripts/benchmark/data_pipeline/benchmark_depth_size.py).

Storage size (benchmark, 480x640 x 100 frames @ 30fps)

Storage Size vs raw f32 Precision
numeric float32 Parquet (snappy, #422 default) 117.9 MB ~1x exact
numeric uint16 Parquet (zstd) 39.5 MB ~3x exact
sidecar lossless (HEVC) 20.6 MB ~6x 12-bit quantized, sub-mm error
sidecar lossy (CRF28) ~10 KB ~1000x+ lossy

Lossless sidecar is ~6x smaller than the numeric float32 Parquet from #422, and the 12-bit codes survive the encode/decode round-trip bit-exactly (verified; max error 0.6 mm over 0.1-3.0 m).

Key technical note

libx265's default B-frame/lookahead buffering races on the flush of 1-3 frame videos (PatchWelcomeError). Setting bframes=0 makes the flush deterministic (0/24 failures after the fix vs 7/24 before).

Dependencies: none new (uses already-installed av/pyav, numpy, torch).

Fixes #424

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which improves an existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Non-breaking: depth_video defaults to enable=False, so existing recordings are unchanged.

Screenshots

Not applicable; affects structured dataset output.

Checklist

  • I have run the black . command to format the code base.
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • Dependencies have been updated, if applicable. (None updated; uses existing av/numpy/torch.)

🤖 Generated with Claude Code

Add an EmbodiChain-owned depth writer that stores camera depth as
gray12le/HEVC sidecar videos alongside LeRobot datasets on Python
3.10/3.11 with lerobot 0.4.4 (issue DexForce#424 Path A), without requiring
the Python 3.12 / lerobot 0.6.0 upgrade. Depth quantization math is
vendored from lerobot v0.6.0 (no py3.12-only syntax); sidecar schema
is aligned with the official 0.6.0 reader for a future seamless
migration (issue DexForce#424 Path B).

- data_pipeline/depth_video: depth_utils (quantize/dequantize),
  codec detection, DepthVideoWriter + DepthSidecarManager (per-episode
  gray12le/libx265 lossless or CRF MP4s + depth_meta.json),
  DepthVideoReader + load_depth_dataset (decode + dequantize to m/mm).
- LeRobotRecorder: depth_video cfg; offload depth to sidecar and drop
  it from lerobot's RGB-only pipeline; keep mask numeric; auto-fallback
  to numeric depth (PR DexForce#422) when no HEVC encoder is available.
- libx265 bframes=0 to make the encoder flush deterministic for short
  episodes (default B-frame/lookahead buffering races on 1-3 frame
  videos).
- Tests (35) + docs + benchmark script comparing storage size.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 14:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@yuecideng yuecideng added enhancement New feature or request dataset data Related to data_pipeline module gym robot learning env and its related features labels Jul 28, 2026
@yuecideng
yuecideng merged commit 2c73219 into DexForce:main Jul 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data Related to data_pipeline module dataset enhancement New feature or request gym robot learning env and its related features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Add compressed depth storage paths for LeRobot datasets

2 participants