Delivery format

HDF5 & zarr delivery format for egocentric episodes

One group per episode, time-major chunks, per-stream nanosecond timestamps.
By the Firsthand capture teamLast updated September 23, 2026

Short answer

HDF5 and zarr store one group per episode with time-major chunking and per-stream nanosecond timestamps. This is the format Firsthand’s own QA tooling reads, so it is the most complete — ideal for random access into long episodes and for verifying sync yourself.

Field mapping

How Firsthand fields map into this format

Container
One .h5 or .zarr group per episode
Chunking
Time-major, 30-frame chunks, blosc-zstd level 5
Timestamps
int64 nanoseconds per stream, PTP domain
Groups
streams/, annotations/, calibration/ mirroring the episode schema
Use case
Random access into long episodes, sync verification

Loading

Loading it

load_hdf5.py
import h5py, numpy as np

with h5py.File("data/EP_0117_KITCHEN_A.h5", "r") as f:
    rgb = f["streams/head_rgb"][100:130]        # a 30-frame chunk
    depth = f["streams/depth_mm"][:]
    hands = f["annotations/hand_joints"][:]      # [T, 2, 21, 3]
    ts_head = f["streams/head_rgb"].attrs["timestamp_ns"]

Gotchas

What to watch for

  • Read whole chunks (30 frames) rather than single frames to avoid decompression overhead.
  • zarr is the better choice for object storage; HDF5 for a single local file.
  • The calibration/ group carries both the opening and closing solves for drift checks.

Get a HDF5 & zarr sample.

40 episodes across 4 environments, delivered in the format your stack already reads.