The video half of the PRIMO R1 release (paper): source clips plus the pre-extracted anchor frames, packaged as multipart ZIP archives, one group per data source. The JSON annotations that reference these files live in separate repos β primo-bench-json, primo-sft-json, primo-rl-json.
The full release is 6.58 TB across 1,231 archive parts, and behavior-1k alone is 5,981 GB of it β 91%. Nobody needs all of it. Every group is independently downloadable and independently extractable, and one group is enough to run a complete benchmark split or train on a subset mixture.
| Group | Parts | Size |
|---|---|---|
behavior-1k | 1115 | 5,981 GB |
agibot | 66 | 349 GB |
seed-bench-r1 | 28 | 148 GB |
real-humanoid | 6 | 27.6 GB |
perceptiontest | 5 | 24.9 GB |
nextqa | 4 | 17.9 GB |
robotwin | 3 | 12.5 GB |
robovqa | 2 | 9.8 GB |
star | 1 | 5.1 GB |
sharerobot | 1 | 0.97 GB |
Start with robotwin (12.5 GB). It backs both benchmark robotwin splits and both robotwin training subsets, so it is the cheapest way to get an end-to-end run working before committing disk to anything larger.
| Split | Group |
|---|---|
primo-bench-{id,ood}-robotwin | robotwin |
primo-bench-{id,ood}-agibot | agibot |
primo-bench-{id,ood}-behavior-1k | behavior-1k |
primo-bench-ood-real-humanoid | real-humanoid |
| Subset | Group |
|---|---|
robotwin-clean, robotwin-randomized | robotwin (shared) |
agibot | agibot |
behavior-1k | behavior-1k |
robovqa | robovqa |
sharerobot | sharerobot |
seed-bench-r1 (SFT only) | seed-bench-r1 |
nextqa (SFT only) | nextqa |
perceptiontest (SFT only) | perceptiontest |
star (SFT only) | star |
One glob per group. --include "robotwin.z*" matches every part including the final .zip:
hf download LeonOverload/primo-video-media --repo-type dataset \
--include "robotwin.z*" --local-dir /tmp/primo-video-zips
Several groups at once:
hf download LeonOverload/primo-video-media --repo-type dataset \
--include "robotwin.z*" --include "sharerobot.z*" --include "robovqa.z*" \
--local-dir /tmp/primo-video-zips
Or from Python:
from huggingface_hub import snapshot_download
for group in ["robotwin", "sharerobot"]:
snapshot_download(
"LeonOverload/primo-video-media",
repo_type="dataset",
allow_patterns=[f"{group}.z*"],
local_dir="/tmp/primo-video-zips",
)
Add --dry-run to any hf download to see the file list and total size before committing. Use --include / --exclude on their own β passing filenames positionally makes the client ignore both.
Per-part SHA256 is published in two equivalent forms: SHA256SUMS.txt (checksum + filename) and manifest.csv (file,size_bytes,sha256).
cd /tmp/primo-video-zips
# Only the parts you actually downloaded
grep -E '^\S+ robotwin\.' /path/to/SHA256SUMS.txt | sha256sum -c -
# macOS
grep -E '^\S+ robotwin\.' /path/to/SHA256SUMS.txt | shasum -a 256 -c -
Running sha256sum -c SHA256SUMS.txt unfiltered reports every part you did not download as missing, which is expected rather than an error.
Each group is a zip split into ~5.37 GB parts named <group>.z01, <group>.z02, β¦, with the last part being <group>.zip β not the first. All parts must sit in the same directory.
7-Zip reads multipart archives directly, so this is the path to prefer:
cd /tmp/primo-video-zips
7z x robotwin.zip -o"$VIDEO_DATA_ROOT/primo-video/"
Without 7-Zip, concatenate first with zip -FF, then extract:
zip -FF robotwin.zip --out robotwin_fixed.zip
unzip robotwin_fixed.zip -d "$VIDEO_DATA_ROOT/primo-video/"
The zip -FF route needs roughly double the disk of the group while it runs, since robotwin_fixed.zip is a full second copy.
Extract into $VIDEO_DATA_ROOT/primo-video/. Archive entries are rooted at <group>/, and the JSON paths resolve against exactly this prefix β DatasetLoader joins $VIDEO_DATA_ROOT/primo-video/ with the relative path field, and init_frame_path / current_frame_path already start with ./primo-video/. Extracting one level up or down is the usual cause of "video not found" at load time.
The resulting tree, alongside annotations:
$VIDEO_DATA_ROOT/
βββ primo-bench/robotwin/{id,ood}.json
βββ primo-sft/robotwin-clean/train_cot.json
βββ primo-rl/robotwin-clean/train.json
βββ primo-video/
βββ robotwin/
βββ videos/...
βββ frames/...
Each archive ships the pre-extracted anchor frames next to the clips β for example sharerobot/videos/entity_25460.mp4 alongside sharerobot/frames/videos/entity_25460_init.jpg and ..._current.jpg. Training reads those JPEG paths straight from the JSON, so there is no preprocessing step for these archives. src/preprocess_video_frames.py in the code repo exists for datasets you add yourself.
Evaluation is different: eval_interleave.py ignores the frame fields and re-derives the first and last frame with OpenCV at run time. Either way, nothing to run ahead of time.
<group>.z01 β¦ <group>.zip β the multipart archives, 10 groups, 1,231 partsSHA256SUMS.txt β per-part SHA256 for all partsmanifest.csv β file,size_bytes,sha256, same data with sizes.pack_tmp/<group>.{manifest,sha} β per-group subsets of the above, written during packaging| Code | 10-OASIS-01/PRIMO-R1 |
| Collection | PRIMO R1 |
| Paper | arXiv 2603.15600 Β· project page |
| Models | PRIMO-R1-7B Β· PRIMO-COT-SFT-7B |
| Benchmark | primo-bench-json |
| Training data | primo-sft-json Β· primo-rl-json |
If you find our work helpful for your research, please consider citing our work.
@misc{liu2026passiveobserveractivecritic,
title={From Passive Observer to Active Critic: Reinforcement Learning Elicits Process Reasoning for Robotic Manipulation},
author={Yibin Liu and Yaxing Lyu and Daqi Gao and Zhixuan Liang and Weiliang Tang and Shilong Mu and Xiaokang Yang and Yao Mu},
year={2026},
eprint={2603.15600},
archivePrefix={arXiv},
primaryClass={cs.RO},
url={https://arxiv.org/abs/2603.15600},
}
65 commits
The video half of the PRIMO R1 release (paper): source clips plus the pre-extracted anchor frames, packaged as multipart ZIP archives, one group per data source. The JSON annotations that reference these files live in separate repos β primo-bench-json, primo-sft-json, primo-rl-json.
The full release is 6.58 TB across 1,231 archive parts, and behavior-1k alone is 5,981 GB of it β 91%. Nobody needs all of it. Every group is independently downloadable and independently extractable, and one group is enough to run a complete benchmark split or train on a subset mixture.
| Group | Parts | Size |
|---|---|---|
behavior-1k | 1115 | 5,981 GB |
agibot | 66 | 349 GB |
seed-bench-r1 | 28 | 148 GB |
real-humanoid | 6 | 27.6 GB |
perceptiontest | 5 | 24.9 GB |
nextqa | 4 | 17.9 GB |
robotwin | 3 | 12.5 GB |
robovqa | 2 | 9.8 GB |
star | 1 | 5.1 GB |
sharerobot | 1 | 0.97 GB |
Start with robotwin (12.5 GB). It backs both benchmark robotwin splits and both robotwin training subsets, so it is the cheapest way to get an end-to-end run working before committing disk to anything larger.
| Split | Group |
|---|---|
primo-bench-{id,ood}-robotwin | robotwin |
primo-bench-{id,ood}-agibot | agibot |
primo-bench-{id,ood}-behavior-1k | behavior-1k |
primo-bench-ood-real-humanoid | real-humanoid |
| Subset | Group |
|---|---|
robotwin-clean, robotwin-randomized | robotwin (shared) |
agibot | agibot |
behavior-1k | behavior-1k |
robovqa | robovqa |
sharerobot | sharerobot |
seed-bench-r1 (SFT only) | seed-bench-r1 |
nextqa (SFT only) | nextqa |
perceptiontest (SFT only) | perceptiontest |
star (SFT only) | star |
One glob per group. --include "robotwin.z*" matches every part including the final .zip:
hf download LeonOverload/primo-video-media --repo-type dataset \
--include "robotwin.z*" --local-dir /tmp/primo-video-zips
Several groups at once:
hf download LeonOverload/primo-video-media --repo-type dataset \
--include "robotwin.z*" --include "sharerobot.z*" --include "robovqa.z*" \
--local-dir /tmp/primo-video-zips
Or from Python:
from huggingface_hub import snapshot_download
for group in ["robotwin", "sharerobot"]:
snapshot_download(
"LeonOverload/primo-video-media",
repo_type="dataset",
allow_patterns=[f"{group}.z*"],
local_dir="/tmp/primo-video-zips",
)
Add --dry-run to any hf download to see the file list and total size before committing. Use --include / --exclude on their own β passing filenames positionally makes the client ignore both.
Per-part SHA256 is published in two equivalent forms: SHA256SUMS.txt (checksum + filename) and manifest.csv (file,size_bytes,sha256).
cd /tmp/primo-video-zips
# Only the parts you actually downloaded
grep -E '^\S+ robotwin\.' /path/to/SHA256SUMS.txt | sha256sum -c -
# macOS
grep -E '^\S+ robotwin\.' /path/to/SHA256SUMS.txt | shasum -a 256 -c -
Running sha256sum -c SHA256SUMS.txt unfiltered reports every part you did not download as missing, which is expected rather than an error.
Each group is a zip split into ~5.37 GB parts named <group>.z01, <group>.z02, β¦, with the last part being <group>.zip β not the first. All parts must sit in the same directory.
7-Zip reads multipart archives directly, so this is the path to prefer:
cd /tmp/primo-video-zips
7z x robotwin.zip -o"$VIDEO_DATA_ROOT/primo-video/"
Without 7-Zip, concatenate first with zip -FF, then extract:
zip -FF robotwin.zip --out robotwin_fixed.zip
unzip robotwin_fixed.zip -d "$VIDEO_DATA_ROOT/primo-video/"
The zip -FF route needs roughly double the disk of the group while it runs, since robotwin_fixed.zip is a full second copy.
Extract into $VIDEO_DATA_ROOT/primo-video/. Archive entries are rooted at <group>/, and the JSON paths resolve against exactly this prefix β DatasetLoader joins $VIDEO_DATA_ROOT/primo-video/ with the relative path field, and init_frame_path / current_frame_path already start with ./primo-video/. Extracting one level up or down is the usual cause of "video not found" at load time.
The resulting tree, alongside annotations:
$VIDEO_DATA_ROOT/
βββ primo-bench/robotwin/{id,ood}.json
βββ primo-sft/robotwin-clean/train_cot.json
βββ primo-rl/robotwin-clean/train.json
βββ primo-video/
βββ robotwin/
βββ videos/...
βββ frames/...
Each archive ships the pre-extracted anchor frames next to the clips β for example sharerobot/videos/entity_25460.mp4 alongside sharerobot/frames/videos/entity_25460_init.jpg and ..._current.jpg. Training reads those JPEG paths straight from the JSON, so there is no preprocessing step for these archives. src/preprocess_video_frames.py in the code repo exists for datasets you add yourself.
Evaluation is different: eval_interleave.py ignores the frame fields and re-derives the first and last frame with OpenCV at run time. Either way, nothing to run ahead of time.
<group>.z01 β¦ <group>.zip β the multipart archives, 10 groups, 1,231 partsSHA256SUMS.txt β per-part SHA256 for all partsmanifest.csv β file,size_bytes,sha256, same data with sizes.pack_tmp/<group>.{manifest,sha} β per-group subsets of the above, written during packaging| Code | 10-OASIS-01/PRIMO-R1 |
| Collection | PRIMO R1 |
| Paper | arXiv 2603.15600 Β· project page |
| Models | PRIMO-R1-7B Β· PRIMO-COT-SFT-7B |
| Benchmark | primo-bench-json |
| Training data | primo-sft-json Β· primo-rl-json |
If you find our work helpful for your research, please consider citing our work.
@misc{liu2026passiveobserveractivecritic,
title={From Passive Observer to Active Critic: Reinforcement Learning Elicits Process Reasoning for Robotic Manipulation},
author={Yibin Liu and Yaxing Lyu and Daqi Gao and Zhixuan Liang and Weiliang Tang and Shilong Mu and Xiaokang Yang and Yao Mu},
year={2026},
eprint={2603.15600},
archivePrefix={arXiv},
primaryClass={cs.RO},
url={https://arxiv.org/abs/2603.15600},
}
65 commits