Skip to content

[core][python] Support shared BLOB payloads across rows - #9459

Open
JingsongLi wants to merge 1 commit into
apache:masterfrom
JingsongLi:codex/shared-blob-video-frames
Open

[core][python] Support shared BLOB payloads across rows#9459
JingsongLi wants to merge 1 commit into
apache:masterfrom
JingsongLi:codex/shared-blob-video-frames

Conversation

@JingsongLi

@JingsongLi JingsongLi commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Purpose

A LeRobot-style dataset uses one logical row per video frame. With the ordinary scalar BLOB layout, repeating the same MP4 descriptor on every row also repeats the MP4 payload in the BLOB sidecar.

This change adds opt-in shared BLOB storage for append-only Data Evolution tables, so frame rows can keep their own metadata while referring to one physical video payload.

Storage model

  • Add an independent, versioned shared-blob format with the .shared-blob extension. The existing .blob format and ordinary BLOB behavior are unchanged.
  • Store physical BLOB records once and maintain two footer indexes:
    • a physical-length index locates each encoded BLOB record;
    • a row-reference index maps every logical row position to a file-local physical BLOB ordinal.
  • Configure one scalar BLOB column with blob-shared-field. The first version supports append-only tables and exact descriptor-backed input.
  • Deduplication is based on exact BlobDescriptor identity and is local to one .shared-blob file; there are no cross-file references.
  • Treat blob.target-file-size as a soft limit for the shared field. Once the limit is reached, a contiguous group with the same descriptor remains together and the next different descriptor, null, or placeholder starts a new file.
  • During BLOB compaction, read descriptor ranges from the input files and rewrite one shared output file, rebuilding the row-to-payload mapping without materializing each payload per row.

For a video-frame table, frame_index or frame_timestamp remains in the normal data file. The corresponding shared-BLOB row returns a descriptor for the MP4 range; decoding that frame is a reader-side operation.

PyPaimon

  • Accept Blob and BlobDescriptor values in MultimodalTable.add.
  • Add MultimodalTable.add_batches to keep one writer and one commit across input batches, preserving a contiguous video group across Arrow batch boundaries.
  • Make ScanQuery.to_torch read BLOB columns as descriptors rather than materializing the MP4 for every frame row.
  • Add VideoFrameCollator with a worker-local LRU decoder cache. It resolves descriptor ranges through the table FileIO and lets the supplied decoder select frames by index or timestamp.
  • Add matching Python shared-BLOB readers/writers and Daft file-extension handling.
  • Document ingestion and PyTorch DataLoader usage.

Verification

  • Java shared and ordinary BLOB format tests: 95 passed.
  • Core schema, path, rolling, compaction, and integration tests: 70 passed.
  • CoreOptions shared-BLOB test: 1 passed.
  • Related Python tests: 91 passed, 2 skipped.
  • compileall, flake8, Spotless/static checks, and diff checks passed.
  • A PyTorch multi-worker integration test is included but was not run locally because torch is not installed in the local environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant