Skip to content

Commit bac4f61

Browse files
authored
refactor: support custom progress parquet overlays (#3640)
1 parent f4b8348 commit bac4f61

1 file changed

Lines changed: 37 additions & 15 deletions

File tree

examples/dataset/create_progress_videos.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
# limitations under the License.
1616

1717
"""
18-
Create MP4 (or GIF) videos with sarm_progress overlay for specified episodes.
18+
Create MP4 (or GIF) videos with per-frame progress overlay for specified episodes.
1919
2020
Downloads datasets from HuggingFace, seeks directly into the episode segment
2121
of the source video, draws a progress line on each frame, and writes the result.
22+
The progress data is read from a parquet file that lives alongside the dataset
23+
(configurable via ``--progress-file``).
2224
2325
Usage:
2426
python examples/dataset/create_progress_videos.py \
@@ -56,22 +58,26 @@
5658
TASK_FONT_SCALE = 0.55
5759

5860

59-
def download_episode_metadata(repo_id: str, episode: int) -> Path:
60-
"""Download only the metadata and sarm_progress files for a dataset.
61+
def download_episode_metadata(
62+
repo_id: str, episode: int, progress_file: str = "sarm_progress.parquet"
63+
) -> Path:
64+
"""Download only the metadata and per-frame progress file for a dataset.
6165
6266
Args:
6367
repo_id: HuggingFace dataset repository ID.
6468
episode: Episode index (used for logging only; all meta is fetched).
69+
progress_file: Filename of the per-frame progress parquet inside the
70+
dataset repo.
6571
6672
Returns:
6773
Local cache path for the downloaded snapshot.
6874
"""
69-
logging.info("[1/4] Downloading metadata for %s (episode %d) ...", repo_id, episode)
75+
logging.info("[1/4] Downloading metadata + %s for %s (episode %d) ...", progress_file, repo_id, episode)
7076
local_path = Path(
7177
snapshot_download(
7278
repo_id=repo_id,
7379
repo_type="dataset",
74-
allow_patterns=["meta/**", "sarm_progress.parquet"],
80+
allow_patterns=["meta/**", progress_file],
7581
ignore_patterns=["*.mp4"],
7682
)
7783
)
@@ -215,25 +221,28 @@ def download_video_file(repo_id: str, local_path: Path, video_rel: str) -> Path:
215221
return video_path
216222

217223

218-
def load_progress_data(local_path: Path, episode: int) -> np.ndarray | None:
219-
"""Load sarm_progress values for an episode.
224+
def load_progress_data(
225+
local_path: Path, episode: int, progress_file: str = "sarm_progress.parquet"
226+
) -> np.ndarray | None:
227+
"""Load per-frame progress values for an episode.
220228
221229
Args:
222230
local_path: Dataset cache root.
223231
episode: Episode index.
232+
progress_file: Filename of the per-frame progress parquet.
224233
225234
Returns:
226235
Sorted (N, 2) array of (frame_index, progress), or None if unavailable.
227236
"""
228-
parquet_path = local_path / "sarm_progress.parquet"
237+
parquet_path = local_path / progress_file
229238
if not parquet_path.exists():
230-
logging.warning("sarm_progress.parquet not found")
239+
logging.warning("%s not found", progress_file)
231240
return None
232241
df = pd.read_parquet(parquet_path)
233-
logging.info(" sarm_progress.parquet columns: %s", list(df.columns))
242+
logging.info(" %s columns: %s", progress_file, list(df.columns))
234243
episode_df = df[df["episode_index"] == episode].copy()
235244
if episode_df.empty:
236-
logging.warning("No sarm_progress rows for episode %d", episode)
245+
logging.warning("No progress rows for episode %d in %s", episode, progress_file)
237246
return None
238247
episode_df = episode_df.sort_values("frame_index")
239248

@@ -576,6 +585,7 @@ def process_dataset(
576585
camera_key: str | None,
577586
output_dir: Path,
578587
create_gif: bool = False,
588+
progress_file: str = "sarm_progress.parquet",
579589
) -> Path | None:
580590
"""Full pipeline: download, extract metadata, composite progress, write output.
581591
@@ -585,24 +595,26 @@ def process_dataset(
585595
camera_key: Camera key to use, or None for auto-selection.
586596
output_dir: Directory to write output files.
587597
create_gif: If True, also generate a GIF from the MP4.
598+
progress_file: Filename of the per-frame progress parquet inside the
599+
dataset repo.
588600
589601
Returns:
590602
Path to the final output file, or None on failure.
591603
"""
592604
safe_name = repo_id.replace("/", "_")
593605
logging.info("Processing: %s | episode %d", repo_id, episode)
594606

595-
local_path = download_episode_metadata(repo_id, episode)
607+
local_path = download_episode_metadata(repo_id, episode, progress_file)
596608
logging.info(" Local cache: %s", local_path)
597609

598610
episode_meta = load_episode_meta(local_path, episode, camera_key)
599611
logging.info(" Episode meta: %s", episode_meta)
600612

601613
video_path = download_video_file(repo_id, local_path, episode_meta["video_rel"])
602614

603-
progress_data = load_progress_data(local_path, episode)
615+
progress_data = load_progress_data(local_path, episode, progress_file)
604616
if progress_data is None:
605-
logging.error("Could not load sarm_progress data. Skipping overlay.")
617+
logging.error("Could not load progress data from %s. Skipping overlay.", progress_file)
606618
return None
607619

608620
logging.info(" Progress frames: %d", len(progress_data))
@@ -627,7 +639,7 @@ def process_dataset(
627639

628640
def main() -> None:
629641
parser = argparse.ArgumentParser(
630-
description="Create MP4/GIF videos with sarm_progress overlay for dataset episodes."
642+
description="Create MP4/GIF videos with per-frame progress overlay for dataset episodes."
631643
)
632644
parser.add_argument(
633645
"--repo-id",
@@ -658,6 +670,15 @@ def main() -> None:
658670
action="store_true",
659671
help="Also generate a GIF from the MP4 output.",
660672
)
673+
parser.add_argument(
674+
"--progress-file",
675+
type=str,
676+
default="sarm_progress.parquet",
677+
help=(
678+
"Filename of the per-frame progress parquet inside the dataset repo "
679+
"(default: 'sarm_progress.parquet')."
680+
),
681+
)
661682
args = parser.parse_args()
662683

663684
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
@@ -670,6 +691,7 @@ def main() -> None:
670691
camera_key=args.camera_key,
671692
output_dir=args.output_dir,
672693
create_gif=args.gif,
694+
progress_file=args.progress_file,
673695
)
674696

675697
if result:

0 commit comments

Comments
 (0)