sleap-io v0.9.2 Release Notes
Summary
sleap-io v0.9.2 is a focused patch release that fixes a major I/O scalability bug in multi-camera RecordingSession storage. Previously, an entire session — calibration, camera↔video mapping, and every frame group's inline 3D points — was serialized as one JSON string in sessions_json. On a real 3-camera, 108,000-frame project that string reached 524 MB, 78.6% of which was 3D point text, and HDF5 variable-length strings can't be read back past roughly a 0.45 GB ceiling in JS/WASM — making such files effectively unreadable in browser-based tooling. The bulk numeric data now lives in a dedicated columnar /session_data HDF5 group, dropping sessions_json to single-digit MB on that project.
The SLP format advances 2.7 → 2.8 — format 2.8 adds the /session_data group. It's additive and read-on-group-presence: pre-2.8 files load unchanged, and files with no camera sessions stay at format ≤2.7.
Highlights:
- Columnar
RecordingSessionstorage (#546) — moves per-frame 3D point data out ofsessions_jsoninto a chunked, gzip-compressed/session_dataHDF5 group, referenced by row range (mirroring how 2D/pointsare referenced from/instances). Fully backward compatible; no public API changes. A real 108k-frame project'ssessions_jsonshrinks from 524 MB to single-digit MB. - h5wasm identity/category link interop fix (#548) —
read_identity_linksandread_category_linksnow accept the flat-2D +field_namestable encoding thatsleap-io.js(via h5wasm) writes, matching every other structured-table reader. Only affects cross-language interop with sleap-io.js-written files. - Storage Representation Matrix docs (#549) —
docs/formats/slp.mdgains a reference table of every on-disk data structure's representation, introducing format version, and read/write support at format 2.8.
Installation / Upgrade
# One-off CLI usage (no installation needed)
uvx sleap-io@0.9.2 show labels.slp
# Install as CLI tool (new install)
uv tool install "sleap-io[all]"
# Upgrade existing CLI tool installation
uv tool upgrade sleap-io
# Add to project (new dependency)
uv add "sleap-io[all]"
# Upgrade existing project dependency
uv lock --upgrade-package sleap-io && uv syncSee installation docs for more options.
Improvements
Columnar RecordingSession storage: 3D points move out of sessions_json (#546)
RecordingSession (multi-camera calibration) was serialized as a single JSON string per session in the sessions_json HDF5 dataset — calibration, the camcorder_to_video_idx_map, and every frame group with its inline 3D points, all as text. On a real 3-camera, 108,000-frame project that string reached 524 MB, of which 412.7 MB (78.6%) was 3D point text. HDF5 variable-length strings can't be read back past roughly a 0.45 GB ceiling in JS/WASM, so such files were effectively unreadable in browser-based tooling (the coordinated sleap-io.js port).
The unbounded per-frame numeric payload now lives in a dedicated columnar /session_data HDF5 group, referenced by row range from a slim sessions_json — the same pattern already used for how 2D /points are referenced from /instances:
sessions_json(slim): calibration +camcorder_to_video_idx_map+ session metadata + anfg_start/fg_endrange intosession_data/frame_groups./session_data/frame_groups—(frame_idx, ig_start, ig_end)/session_data/instance_groups—(identity_idx, score, instance_3d_score, pts3d_start/end, pts3d_predicted, member_start/end)/session_data/instance_group_members—(camera, lf, inst), the columnarizedcamcorder_to_lf_and_inst_idx_map/session_data/points_3d(N,3)/pred_points_3d(N,4 = xyz+score)— chunked, gzip-compressed float matrices; NaN rows denote missing keypoints/session_data/frame_group_meta/instance_group_meta— optional per-row JSON blobs for lossless typed metadata
On the reported dataset, sessions_json drops from 524 MB to single-digit MB.
Format version: 2.7 → 2.8, bumped only when a session actually has frame groups; session-free/single-view files stay at ≤2.7 and are byte-identical to before.
Compatibility: Fully backward and forward compatible. The reader dispatches on /session_data presence and still parses legacy inline frame_group_dicts from ≤2.7 files. An older (<2.8) reader opening a 2.8 file loads calibration from the slim sessions_json and silently ignores /session_data — no corruption, just absent 3D data. No public API changes: labels.sessions[...].frame_groups[...].instance_groups[...].points works identically; this is purely an on-disk representation change.
Handled consistently across eager I/O (incremental per-session append, bounded peak memory), lazy I/O (raw passthrough — also fixes a prior bug where lazy re-save could silently drop frame groups/3D data), and streaming/remote reads (chunked datasets over fsspec range reads, removing the vlen-string ceiling for large remote files).
Fixes
Read h5wasm flat-2D identity/category links (#548)
read_identity_links and read_category_links read /identity/links and /categories/links via direct structured field access only, with no fallback. h5wasm — the HDF5 layer sleap-io.js writes through — can't create true HDF5 compound datasets, so it stores every structured table as a flat 2-D f8 array plus a field_names attribute, the same convention already handled for points/pred_points/instances/frames, and for /session_data in #546. These two per-detection link readers were the one place not yet wired through the shared flat-2D conversion helper, so a links table written by sleap-io.js raised on read in Python.
Both readers now route through the existing shared conversion helper, which rebuilds a structured array when a field_names attribute is present and passes a genuine compound dataset through unchanged. Only cross-language interop is affected — files written by sleap-io.js (h5wasm) that are read back by Python sleap-io. Plain Python-written .slp/.pkg.slp files are read identically before and after this fix. Closes #547.
Documentation
- New Storage Representation Matrix section in
docs/formats/slp.mdcataloging, for every on-disk data structure at format 2.8, its storage representation (compound, columnar group, EAV, plain matrix, ragged CSR, string, JSON, or attribute), the format version that introduced it, and read/write support — complementing the existing Version History and browser-compatibility sections. - Documents the write/read asymmetry: Python always writes a single native representation per structure, while
compound-kind readers additionally accept thesleap-io.jsh5wasm flat-2D +field_namesencoding for browser interop.
Changelog
- #546: feat(io): Columnar RecordingSession storage: move 3D points out of
sessions_json(SLP 2.8) - #548: fix(io): read h5wasm flat-2D identity/category links (coordinated sleap-io.js port)
- #549: docs(slp): add Storage Representation Matrix (format 2.8)
Full Changelog: v0.9.1...v0.9.2